Re: [xsl] Creating hierarchies from in-line markers

Subject: Re: [xsl] Creating hierarchies from in-line markers
From: "Imsieke, Gerrit, le-tex gerrit.imsieke@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 28 Jun 2014 05:44:59 -0000
On 28.06.2014 05:44, Peter West lists@xxxxxxxxx wrote:
I'm sure the subject text is obscurely expressed, which may be why I couldn't find anything appropriate in the archive.

I am looking at epub2 xml in which "structure markers" are interspersed with general content. For instance, new chapters are marked with an H2, and the content of the chapter is on the following-sibling axis, as is the subsequent H2. Similarly, footnotes are marked by DIVs, with the text of the note in one or more P siblings.

In order to make these into hierarchies, I have been using a model like this:

<template match="marker-element[appropriate conditions]">
   blah blah blah
   <apply-templates mode="whatever" select=
    "following-sibling::node() intersect
     (following-sibling::marker-element[appropriate conditions] union end-element)[1]/preceding-sibling::node()"/>
</template>

and suppressing the "normal" processing of the siblings.

I feel your pain; however, this seems to work. What nicer ways are there of achieving this?

Use xsl:for-each-group [1], as it is meant to deal with this kind of problems.


<xsl:template match="*[marker-element[appropriate conditions]]">
<xsl:copy>
<xsl:copy-of select="@*"/><!-- or apply-templates w/ identity template -->
<xsl:for-each-group select="* (: or node() if you want to keep the (presumably all-whitespace) text nodes :)"
group-starting-with="marker-element[appropriate conditions]">
<!-- please note that in group-starting-with and group-ending-with, you use matching patterns (as in xsl:template match attributes), while in group-adjacent or group-by you'd use an XPath expression that returns atomizable values, for ex., "exists(self::marker-element)" or just "appropriate conditions" -->
<xsl:choose>
<!-- Check whether current group starts with marker element.
(The first group may start otherwise.) -->
<xsl:when test="self::marker-element[appropriate conditions]">
<!-- The test self::b& is just a shorthand for exists(current-group()[1]/self::marker-element[b&]) because within for-each-group, current-group[1] is the context element. -->
<section epub:type="b&">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/><!-- or copy-of -->
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>


This won't nest the sections recursively though.

See [2] (and the post linked from there) for a more generic approach using a recursively called function. It can also be achieved by a recursively called template.

Gerrit

[1] http://www.w3.org/TR/xslt20/#element-for-each-group
[2] http://xsl.markmail.org/message/5otmmsaovdpynkew



Peter West

"...for I am gentle and lowly in heart, and you will find rest for your souls."



-- Gerrit Imsieke GeschC$ftsfC<hrer / Managing Director le-tex publishing services GmbH Weissenfelser Str. 84, 04229 Leipzig, Germany Phone +49 341 355356 110, Fax +49 341 355356 510 gerrit.imsieke@xxxxxxxxx, http://www.le-tex.de

Registergericht / Commercial Register: Amtsgericht Leipzig
Registernummer / Registration Number: HRB 24930

GeschC$ftsfC<hrer: Gerrit Imsieke, Svea Jelonek,
Thomas Schmidt, Dr. Reinhard VC6ckler

Current Thread