Concept XML XLST preceding-sibling and ancestor
The preceding-sibling:: axis
The preceding-sibling::
axis is an axis of navigation that includes all the preceding sibling elements to the focus element. By "sibling" we mean a different element which has the same parent to the reference item. By "preceding" we mean a node that occurs before the reference one. The order of the preceding-sibling
axis is the reverse document order. Take a look at this document:
<fruit>
<banana>
<lady-finger-banana/>
</banana>
<apple/>
<pear/>
<kiwi/>
</fruit>
If the focus node is pear, then the sequence preceding-sibling::*
is ...
- apple
- banana
Note: fruit, pear, lady-finger-banana and kiwi are not in the sequence.
So the following is true:
preceding-sibling::*[ 1]
is the applepreceding-sibling::*[ 2]
is the bananacount( preceding-sibling::*)
is 2preceding-sibling::apple[ 1]
is also the applepreceding-sibling::banana[ 1]
is the bananapreceding-sibling::*[ 3]
is absent or the empty sequence
preceding-sibling::pop/ancestor::inventory/totalprice Example
We have to alter your sample document a little bit to usefully study this example
<product>
<inventory>
<drink>
<lemonade>
<price>$2.50</price>
<amount>20</amount>
</lemonade>
<pop>
<price>$1.50</price>
<amount>10</amount>
</pop>
<focus-item />
</drink>
<totalprice>$15</totalprice>
</inventory>
</product>
Let us say the focus is on the element focus-item.
To evaluate the expression preceding-sibling::pop/ancestor::inventory/totalprice
follow these steps:
preceding-sibling::pop
selects all the precedingpop
elements to focus-item. This evaluates to a sequence of one node.For each item in the left hand sequence (just one
pop
element it so happens), set this item as a temporary focus item, and evaluate the expression of the right of the / operator which is ...ancestor::inventory
There is only one such node, which is the ancestral inventory node. Thus the first / operator evaluates to a sequence of one inventory node.
Now we evaluate the effect of the second / and its right-hand operand expression total price. For each item in the left hand sequence (just one inventory node so it happens), set this as a temporary focus item and evaluate
totalprice
.totalprice
is short forchild::totalprice
. There is only one total price element on the child axis of the temporary focus node, so the final result is a sequence of one node, which is the total price node.
Understanding by Diagrams
Here is a diagram for preceding-sibling::
. In it the reference node is Charlie and the node on the preceding-sibling::
axis is in green. It is the only such node.
Axes useful for navigation through the node tree. So it depends from your problem what kind of axis is useful.
The following stylesheet illustrates the difference.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="snack">
<xsl:variable name="siblings" select="ancestor::node()"/>
<debug>
<xsl:for-each select="preceding-sibling::node()">
<sibling>
<xsl:value-of select="local-name()"/>
</sibling>
</xsl:for-each>
<xsl:for-each select="ancestor::node()">
<ancestor>
<xsl:value-of select="local-name()"/>
</ancestor>
</xsl:for-each>
</debug>
</xsl:template>
<xsl:template match="*">
<xsl:apply-templates select="*"/>
</xsl:template>
</xsl:stylesheet>