Subject: Re: [xsl] inconsistent Preceding-Sibling behaviour when nested in For-Each From: Alan Stein <as2@xxxxxxxxxxx> Date: Sat, 02 Nov 2002 17:26:55 -0500 |
Regards, --Alan
Hi Alan,
> I've observed a reproducible XSL behaviour that I just can't > understand. "preceding-sibling", "following-sibling", and > conditional expressions based on these axes appear to behave oddly > when placed in a "for-each" element. > > My observations of the unusual behavior within the "for-each" loop: > > -- "following-sibling" behaves exactly as I would expect > -- "preceding sibling" unexpectedly always refers to the first sibling in > the document
When you collect together a node set and use it to do something in XSLT, for example if you iterate over it using <xsl:for-each> or take the value of the first node with <xsl:value-of>, then XSLT *always* gives you the node set in document order.
When you collect together all the preceding-siblings of a node, and handle them in document order the first of those nodes is the first of the siblings -- the first child of the parent -- not the closest of those siblings.
If you want to get the *closest* of the siblings then you can use [last()] as follows:
<xsl:value-of select="(preceding-sibling::person/name)[last()]" />
Or you can use [1] *in the step when you select the preceding sibling*:
<xsl:value-of select="preceding-sibling::person[1]/name" />
In a step, the order used to evaluate positional predicates such as [1] is based on the axis used in the step. In a forward axis, such as following-sibling, it's the same as document order. In a reverse axis, such as preceding-sibling, it's reverse document order. Basically, if you use [1] you always end up with the node that's closest to the node that you're on.
To summarise: Node sets are always treated as if they were in document order. Within a step, the order of the nodes depends on the axis that's used in the step.
> -- "if" statements behave erraticly: neither comparisons of current > nodes to "preceding-sibling" nor comparisons to "following-sibling" > appear to work completely.
When you make comparisons that involve node sets in XSLT, the comparison actually tests whether any combination of tests between individual nodes and the value would be true. For example, if you do:
<xsl:if test="name = preceding-sibling::person/name">...</xsl:if>
you're actually testing whether the name of this person is the same as the name of *any* preceding sibling's name. Again, if you want to just test the *immediately* preceding sibling's name, then you should use a positional predicate in the step where you select the preceding sibling, so that you only select the first rather than all of them:
<xsl:if test="name = preceding-sibling::person[1]/name">...</xsl:if>
Cheers,
Jeni
--- Jeni Tennison http://www.jenitennison.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] inconsistent Preceding-Si, Jeni Tennison | Thread | Finding the closest node (was Re: [, Peter Flynn |
Re: [xsl] Generating schema target , Trevor Nash | Date | [xsl] XSL Decending Order Query, Amrit Gill |
Month |