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 ...

  1. apple
  2. banana

Note: fruit, pear, lady-finger-banana and kiwi are not in the sequence.

So the following is true:

  • preceding-sibling::*[ 1] is the apple
  • preceding-sibling::*[ 2] is the banana
  • count( preceding-sibling::*) is 2
  • preceding-sibling::apple[ 1] is also the apple
  • preceding-sibling::banana[ 1] is the banana
  • preceding-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:

  1. preceding-sibling::pop selects all the preceding pop elements to focus-item. This evaluates to a sequence of one node.
  2. 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.

  3. 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.

  4. totalprice is short for child::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.

enter image description here


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>

Tags:

Xml

Xpath

Xslt