Re: select immediately following siblings with constr
> 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[@id = preceding-sibling::element()[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()[self::section][@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()[self::section][@id = current()/@id]"> <xsl:variable name="stop" select="following-sibling::element()[ self::article or self::section[@id != current()/@id]]" /> <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.robinson@xxxxxxxxxxxx Stanford University HighWire Press http://highwire.stanford.edu/ +1 650 7237294 (Work) +1 650 7259335 (Fax)
PURCHASE STYLUS STUDIO ONLINE TODAY!
Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!
Download The World's Best XML IDE!
Accelerate XML development with our award-winning XML IDE - Download a free trial today!
Subscribe in XML format