Selecting nodes

The path expression is used to select one or more nodes. A path expression consists of one or more step expressions, separated by a single slash ("/") or a double ("//"). There are two types of path expressions: absolute path expressions and relative path expressions.

Absolute path expression

An absolute path expression starts with a path operator ("/"). The most simple absolute path expression looks like this, just a single slash:

Absolute path expression

XQuery

/

Open example in playground

Here's another example, with multiple path operators and step expressions:

Absolute path expression with multiple steps

XQuery

/child::xml/child::tips/child::tip

Open example in playground

Absolute path expressions start from the root of the XML document in which the context node is located, assuming the node is in the document. If the node is not in the document, an error will be thrown (XPDY0050). You can do this by starting a path from a newly created node:

Absolute path starting from a detached node

XQuery

<newNode/>/(/)

Open example in playground

Relative path expression

A relative path expression does not start with a path operator ("/"). Instead, it directly starts with a step expression. It differs from the absolute path expression in that this expression starts at the context node.

Relative path expression

XQuery

child::tips

Open example in playground

Relative path expression with multiple steps

XQuery

child::tips/child::tip

Open example in playground

Step expression

Step expressions form the building blocks of the path expression. A step expression will generate a sequence of items. These items are optionally filtered by predicates.

A step expression consists of an axis and a node test. The used axis determines the "direction" in which the step will move. The node test determines which nodes are selected by the step expression.

Axes

An axis contains nodes. Which nodes it contains depends on the context node and which axis is used. An axis will return the nodes it contains. An axis may return an empty sequence when it does not contain any nodes.

There are two categories of axes: forward axes and reverse axes. A forward axis only ever contains the context node or nodes that are after the context node in document order. A reverse axis only ever contains nodes that are before the context node in document order.

Ancestor axis

The ancestor axis is a reverse axis. It contains the ancestors of the context node. These include the context node's parent, the parent of the parent, and so on. This axis will return an empty sequence when the context node has no ancestors.

Ancestor axis

XQuery

ancestor::element()

Open example in playground

Ancestor or self axis

The ancestor-or-self axis is a reverse axis. It contains the context node itself and its ancestors. This means that this axis will always contain the root node of the XML document if the context node is attached.

Ancestor or self axis

XQuery

ancestor-or-self::element()

Open example in playground

Attribute axis

The attribute axis is a forward axis. It contains the attributes of the context node. This axis will return an empty sequence when the context node does not have any attributes or when the context node is not an element.

Attribute axis

XQuery

attribute::attribute()

Open example in playground

Child axis

The child axis is a forward axis. It contains the children of the context node. Only elements and document nodes can have children. This axis will return an empty sequence for all other node types or when the node has no children.

Child axis

XQuery

child::element()

Open example in playground

Descendant axis

The descendant axis is a forward axis. It contains the descendants of the context node. These include the context node's children, the children of the children, and so on. This axis will return an empty sequence when the context node has no descendants.

Descendant axis

XQuery

descendant::element()

Open example in playground

Descendant or self axis

The descendant-or-self axis is a forward axis. It contains the context node and its descendants. This axis will always contain at least one node.

Descendant or self axis

XQuery

descendant-or-self::element()

Open example in playground

Following axis

The following axis is a forward axis. It contains all nodes that are not descendants of the context node and occur after the context node in document order. This axis will return an empty sequence when there are no nodes after the context node in document order.

Following axis

XQuery

following::element()

Open example in playground

Following sibling axis

The following-sibling axis is a forward axis. It contains all node that are the children of the context node's parent that occur after the context node in document order. This axis will return an empty sequence when there are no sibling nodes after the context node in document order.

Following sibling axis

XQuery

following-sibling::element()

Open example in playground

Parent axis

The parent axis is a reverse axis. It contains the parent node of the context node. This axis will return an empty sequence when the context node has no parent node.

Parent axis

XQuery

parent::element()

Open example in playground

Preceding axis

The preceding axis is a reverse axis. It contains all nodes that are not descendants of the context node and occur before the context node in document order. This axis will return an empty sequence when there are no nodes before the context node in document order.

Preceding axis

XQuery

preceding::element()

Open example in playground

Preceding sibling axis

The preceding-sibling axis is a reverse axis. It contains all nodes that are children of the context node’s parent that occur before the context node in document order. This axis will return an empty sequence when there are no sibling nodes before the context node in document order.

Preceding sibling axis

XQuery

preceding-sibling::element()

Open example in playground

Self axis

The self axis is a forward axis. It simply contains the context node and thus is never empty if the test matches the context node.

Self axis

XQuery

self::element()

Open example in playground

Node test

With the axes we can determine which "direction" we want to move. The node test determines which nodes will be selected from the used axis. Nodes can be tested based on their name, their kind, or their type annotation.

Name test

The name test selects nodes based on their name. The node tested with the name test can be either an element or an attribute.

Name test for elements

XQuery

child::nodeName

Open example in playground

Name test for attributes

XQuery

attribute::attributeName

Open example in playground

Kind test

The kind test selects nodes based on their kind. It can test for text nodes, comments, elements, processing instructions, document nodes, or attributes.

Kind test for nodes

XQuery

child::node()

Open example in playground

Kind test for text nodes

XQuery

child::text()

Open example in playground

Kind test for comments

XQuery

child::comment()

Open example in playground

Kind test for elements

XQuery

child::element()

Open example in playground

Kind test for elements with a specified element name

XQuery

child::element(elementName)

Open example in playground

Kind test for processing instructions

XQuery

child::processing-instruction()

Open example in playground

Kind test for document nodes

XQuery

ancestor::document-node()

Open example in playground

Kind test for attributes

XQuery

attribute::attribute()

Open example in playground

Kind test for attributes with a specified attribute name

XQuery

attribute::attribute(attributeName)

Open example in playground

Abbreviated syntax

Some bits and pieces of path expressions can be abbreviated. These abbreviations are aptly called the abbreviated syntax.

Attribute axis

The attribute axis can be abbreviated with a single "@". The following queries will yield the same result:

Attribute axis without abbreviated syntax

XQuery

attribute::attributeName

Open example in playground

Attribute axis with abbreviated syntax

XQuery

@attributeName

Open example in playground

Child axis

The child axis can be abbreviated by simply omitting it. The following queries will yield the same result:

Child axis without abbreviated syntax

XQuery

child::elementName

Open example in playground

Child axis with abbreviated syntax

XQuery

elementName

Open example in playground

Descendant or self axis

The descendant or self axis can be abbreviated with two slashes ("//"). These double slashes replace the path operator (single slash). The following queries will yield the same result:

Descendant or self axis without abbreviated syntax

XQuery

descendant-or-self::node()/child::element()

Open example in playground

Descendant or self axis with abbreviated syntax

XQuery

//child::element()

Open example in playground

Parent axis

The parent axis can be abbreviated with two dots (".."). The following queries will yield the same result:

Parent axis without abbreviated syntax

XQuery

parent::node()/child::element()

Open example in playground

Parent axis with abbreviated syntax

XQuery

../child::element()

Open example in playground

Element kind test

The element kind test can be abbreviated with a single asterisk ("*"). The following queries will yield the same result:

Element kind test without abbreviated syntax

XQuery

child::element()

Open example in playground

Element kind test with abbreviated syntax

XQuery

child::*

Open example in playground

Predicates within steps

A predicate within a step looks the same as a predicate within a filter expression. But it does not work exactly the same. It differs in the way the context position is set for the evaluation of the predicate. The context position for the predicate is

The input sequence is sorted in document order if the predicate is in a forward-axis step. The input sequence is sorted in reverse document order if the predicate is in a reverse-axis step. The sequence will keep its original order when the predicate is not in a step.

Examples

Predicates within steps are very similar to predicates within filters. However, there are some interesting differences, some of which may leave you wondering why your XPath query does not work.

Selecting the Nth element

This example selects the second li element that is a child of the context node. The way this predicate works does not deviate from the way a filter predicate works.

Predicate in step returning a numeric value

XQuery

child::li[2]

Open example in playground

The following two examples demonstrate that the context position is dependent on whether the step uses a forward or a reverse axis. The descendant axis is a forward axis. Selecting the first element from the sequence returned by the step returns the first following sibling as seen from the context node.

Predicate in step selecting the first following sibling

XQuery

following-sibling::element()[1]

Open example in playground

The ancestor axis is a reverse axis. Selecting the first element from the sequence returned by the step returns the first preceding sibling as seen from the context node, not the first element in document order.

Predicate in step selecting the first preceding sibling

XQuery

preceding-sibling::element()[1]

Open example in playground

Selecting elements with specific attributes

Predicates can also be used to select elements that contain an attribute. Or even an attribute with a specific value.

Predicate in step selecting nodes based on the presence of a class attribute

XQuery

child::li[attribute::class]

Open example in playground

Predicate in step selecting nodes based on the value of an attribute

XQuery

child::li[attribute::class = "even"]

Open example in playground

Selecting elements with a specific child

You can also use predicates to select elements with a specific child node. This, of course, can be done with any axis.

Predicate in step selecting an element based on the presence of a child element

XQuery

child::li[child::p]

Open example in playground

Predicate in step selecting an element based on the presence of multiple childnodes

XQuery

child::li[child::p][child::ul]

Open example in playground

A common trap

This example shows a common trap that might leave you wondering why your XPath query does not work. Imagine that you have the following DOM:

Example DOM

XML

<xml>
  <ul>
    <li><p>List item 1</p></li>
    <li><p>List item 2</p></li>
    <li><p>List item 3</p></li>
    <li><p>List item 4</p></li>
    <li><p>List item 5</p></li>
  </ul>
</xml>

Let's assume you want to select the second text node. A selector you might write is the following:

Predicate in step: A common trap

XQuery

li/p/text()[2]

Open example in playground

The result of this selector is an empty sequence. Why? Because the predicate is part of the step expression. This selector selects the second text node child of any p element child of any li element child. And since the p elements contain only one text node each, this selector won't return any nodes.

Predicate in step: Solution to the common trap

XQuery

(li/p/text())[2]

Open example in playground