Subject: Re: [xsl] Confusion about preceding-sibling axis From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx> Date: Tue, 10 Apr 2001 00:24:38 +0100 |
Hi Darren, > Once I'd created the item_list variable and used this for the > <xsl:for-each> I expected all item elements to have the same > ancestor and therefore all be siblings of each other. The results > suggest that the original document hierarchy is being used instead. > > Am I missing something really obvious here?! I guess so :) *All* XPath axes work on the node tree, *not* on the current node list (the list of nodes that are currently being processed) as defined in the select expression of xsl:for-each or xsl:apply-templates. The siblings of a node are always the same no matter what you're processing - the other children of the same parent in the node tree. It's actually fairly difficult to find out about the other nodes that are being iterated over within XSLT. You can look at the position() of the node that's being processed, so for example you can identify whether the current node is the first node that's being processed: <xsl:template match="root"> <xsl:variable name="item_list" select="//item"/> <html> <body> <xsl:for-each select="$item_list"> <p><b><xsl:value-of select="."/></b><br/> <xsl:if test="position() = 1">First node<br /></xsl:if> </p> </xsl:for-each> </body> </html> </xsl:template> But in order to find the nodes that were processed before it, you have to 'cheat' and index into the same node set again: <xsl:template match="root"> <xsl:variable name="item_list" select="//item"/> <html> <body> <xsl:for-each select="$item_list"> <p><b><xsl:value-of select="."/></b><br/> <!-- record position of this node --> <xsl:variable name="pos" select="position()" /> <xsl:choose> <xsl:when test="$pos = 1">First node<br /></xsl:when> <xsl:otherwise>Nodes before in document order are: <!-- iterate over the same node list, but only pick those whose position is less than the position of the node --> <xsl:for-each select="$item_list[position() < $pos]"> <xsl:value-of select="." /> <xsl:text> </xsl:text> </xsl:for-each> </xsl:otherwise> </xsl:choose> </p> </xsl:for-each> </body> </html> </xsl:template> The other method is to change the siblings of an element by making a new node tree in which the element has different siblings. You can do this by creating a variable that contains *copies* of the elements you're interested in within a new result tree fragment: <xsl:variable name="item_list"> <xsl:copy-of select="//item" /> </xsl:variable> You can then access the result tree fragment as a node set, by first converting it to a node set with a node-set extension function such as saxon:node-set(), msxsl:node-set(), lxslt:node-set() or equivalent for whatever processor you're using (or exsl:node-set() when processors adopt EXSLT). If you iterate over that node set, you can use your original code: <xsl:for-each select="exsl:node-set($item_list)"> <p><b><xsl:value-of select="."/></b><br/> <xsl:choose> <xsl:when test="count(preceding-sibling::*) < 1">No preceding siblings<br/></xsl:when> <xsl:otherwise>Preceding siblings are: <xsl:for-each select="preceding-sibling::*"> <xsl:value-of select="."/>  </xsl:for-each> </xsl:otherwise> </xsl:choose> </p> </xsl:for-each> (You'll probably find it more efficient to just test whether there are any preceding siblings rather than counting them all and comparing it to '1' - just use test="not(preceding-sibling::*)".) The other things you might be interested in are the preceding:: and following:: axes, which don't just select nodes with the same parent. You could have used: <xsl:for-each select="$item_list"> <p><b><xsl:value-of select="."/></b><br/> <xsl:choose> <xsl:when test="not(preceding::item)">No preceding items<br/></xsl:when> <xsl:otherwise>Preceding items are: <xsl:for-each select="preceding::item"> <xsl:value-of select="."/>  </xsl:for-each> </xsl:otherwise> </xsl:choose> </p> </xsl:for-each> Sorry to go on - it's just I think that playing with these different approaches can really help you understand what's going on. I hope that helps anyway, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Confusion about preceding-sib, SCOTT, Darren, FM | Thread | RE: [xsl] Confusion about preceding, Michael Kay |
RE: [xsl] Generating multi-level re, Joel P Thornton | Date | Re: [xsl] Re: RE: grouping content, Jeni Tennison |
Month |