xsl-list
[Top] [All Lists]

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

2014-06-28 00:45:13


On 28.06.2014 05:44, Peter West lists(_at_)pbw(_dot_)id(_dot_)au 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::… is just a shorthand for exists(current-group()[1]/self::marker-element[…]) because within for-each-group, current-group[1] is the context element. -->
          <section epub:type="…">
            <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
Geschäftsfü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(_dot_)imsieke(_at_)le-tex(_dot_)de, http://www.le-tex.de

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

Geschäftsführer: Gerrit Imsieke, Svea Jelonek,
Thomas Schmidt, Dr. Reinhard Vöckler
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--

<Prev in Thread] Current Thread [Next in Thread>