At 01:54 PM 2/23/2006, you wrote:
Thank you very much for the reply. I actually hadn't been aware of
the << and >> operators, I shall have to read up on them.
Yes, they're fun, and ought to be useful for all kinds of neat things
we haven't discovered yet.
Yes indeed! So I ended up using <<, it seems to be exactly what I
wanted. It is still processing elements unnecessarily because my
expression has it testing all following-siblings, but hopefully the
testing of position in document order is less intensive then doing all
that unnecessary grouping.
I decided to make it more readable (to me, at least) by splitting the
creation of a $stop node from the processing of the following-sibling
sections.
Here's the complete solution for my merging problem:
<!--
Recursively merge adjoining sections into a single section.
We test $sections to see if there is any instance of a
section whose first preceding-sibling element is a section
with an identical id.
If the test is true, we recursively call ourselves, passing
in the document returned by the merged_toc template, which
merges adjacent sections sharing a section id.
-->
<xsl:template name="merge_sections">
<xsl:param name="sections" as="document-node()" />
<xsl:choose>
<xsl:when test="exists($sections//section[(_at_)id =
preceding-sibling::element()[1][self::section]/@id])">
<xsl:call-template name="merge_sections">
<xsl:with-param name="sections">
<xsl:apply-templates select="$sections" mode="merged_toc" />
</xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="$sections" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!--
Merge adjoining sections sharing a section id into a single group,
skipping sections we infer were previously handled.
-->
<xsl:template match="section" mode="merged_toc" as="element(section)?">
<!--
If the immediately preceding element is a section which has the
same id, it should have already been handled. Otherwise we want
to copy it.
-->
<xsl:if test="not(preceding-sibling::element()[1][self::section][(_at_)id =
current()/@id])">
<xsl:copy>
<xsl:sequence select="@*" />
<xsl:apply-templates select="*" mode="#current" />
<!--
Now we want to pull in the children of any consecutive sequence
of immediately following sibling sections which have the same id
as the current section.
We first test to see if the immediately following element is
a section with the same id as the current section. If this
isn't the case, we know we aren't supposed to do any merges.
If we pass the test, we construct $stop, setting it to the
first following-sibling::element() which is not a section
with an identical section id to our own.
If $stop has a value, we apply templates to following-sibling
sections which are positioned, in document order, before $stop.
If $stop does not have a value, all the following-sibling
sections share our section id, and we can merge them all.
-->
<xsl:if test="following-sibling::element()[1][self::section][(_at_)id =
current()/@id]">
<xsl:variable name="stop"
select="following-sibling::element()[
self::article or self::section[(_at_)id !=
current()/@id]][1]" />
<xsl:choose>
<xsl:when test="$stop">
<xsl:apply-templates select="following-sibling::section[.
<< $stop]/*" mode="#current" />
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="following-sibling::section/*"
mode="#current" />
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:copy>
</xsl:if>
</xsl:template>
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
James A. Robinson
jim(_dot_)robinson(_at_)stanford(_dot_)edu
Stanford University HighWire Press http://highwire.stanford.edu/
+1 650 7237294 (Work) +1 650 7259335 (Fax)
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--