Jesper Tverskov, September 21, 2007

13 XPath axes

An XPath axis is a path through the node tree making use of particular relationship between nodes. We use the "child::*" axis and the "attribute::*" axis all the time but mostly their short form: "*" and "@*". The other axes are used far less often. If we need them or not very much depends on what we want to achieve. For more information see XPath axes in the W3C Recommendation.

1. Axis examples

Most often the axes, e.g.: "descendant::", are followed by an "*" (element) or an element name but comment(), processing-instruction() and text-node() can also be used. Only root node and elements can have children.

The construct node() only selects nodes being children of other nodes: element(), text(), comment(), processing-instruction(). An attribute has a parent element but attribute and namespace nodes are not children and not included in the node() construct or type.

descendant::*All elements being children and children's children, etc, of context node.
descendant::stockAll "stock" elements being children and children's children, etc, of context node.
descendant::comment()All comment nodes being children of context node.
descendant::*|comment()All element and comment nodes being children or children's children, etc, of context node.
descendant::node()All nodes being children or children's children, etc, of context node.

2. Axis diagrams

The diagrams are not showing attribute() and namespace() nodes and I have not made diagrams for the attribute and namespace axes. The namespace axis is deprecated. The functions in-scope-prefixes() and namespace-uri-for-prefix() should be used instead.

When using axes it is often important to remember that the nodes are processed in document order (indicated below). If both a node's children and siblings are included in an axis, the node's children are always processed before its following siblings. The order is sometimes a little tricky especially for reverse axes until you get used to it. See the preceding axis as example.

2.1 ancestor

Ancestor axis: parent and parent's parent, etc.

India is context node: count(ancestor::*) returns 2.

2.2 ancestor-or-self

Ancestor-or-self axis: context node and parent and parent's parent, etc.

India is context node: count(ancestor-or-self::*) returns 3.

2.3 child

Child axis: children of context node.

Charlie is context node, e.g.: count(child::*) returns 2. Same as count(*).

2.4 descendant

Descendant axis: children and their children, etc.

Charlie is context node, e.g.: count(descendant::*) returns 5.

2.5 descendant-or-self

Descendant-or-self axis: context node and children and their children, etc.

Charlie is context node, e.g.: count(descendant-or-self::*) returns 6.

2.6 following

Following axis: following siblings and their children and their children, etc.

Charlie is context node, e.g.: count(following::*) returns 4.

2.7 following-sibling

Following-sibling axis: following siblings.

Charlie is context node, e.g.: count(following::*) returns 2.

2.8 parent

Parent axis: The parent of context node.

India is context node, e.g.: if (parent::* eq 'Charlie') then '...' else '...'

2.9 preceding

Preceding axis: preceding siblings and their children and their children, etc.

Charlie is context node, e.g.: count(preceding::*) returns 3

2.10 preceding-sibling

Preceding-sibling axis: preceding siblings.

Charlie is context node, e.g.: count(preceding-sibling::*) returns 1

2.11 self

Self axis: context node.

Charlie is context node, e.g.: if (self::* eq 'Charlie') then '...' else '...'

3. Stylesheet example

The distinct-values() function is new in XPath 2.0. In XPath 1.0 it was necessary to use the preceding axis to count unique values. The following XPath expression says: "Count all the country elements being children of context node, but don't count an element if its content is equal to one of the country elements you have already counted.

count(country[not(. = preceding::country)])

countries.xml - countries.xsl - distinct-values-xml

Updated 2009-08-06