XPath Predicates and Node-Set Evaluation
This article provides an overview of XPath predicates, explaining what they are, their syntax, and the exact mechanics behind how the XPath engine evaluates them to filter XML node-sets. You will learn about evaluation contexts, data type conversions, numeric indexing, and the behavior of chained predicates.
What Are XPath Predicates?
An XPath predicate is an expression enclosed in square brackets
[...] that is appended to an XPath location step. Its
primary role is to filter a sequence or node-set by testing each node
against a specific condition. Only nodes that satisfy the condition are
retained in the final result.
Syntax example:
/bookstore/book[price < 30]
In this expression, [price < 30] is the predicate
applied to all <book> child elements of
<bookstore>.
The Evaluation Process Against Node-Sets
When an XPath processor encounters a predicate, it does not evaluate the entire collection at once. Instead, it follows a structured iterative evaluation against the initial node-set:
1. Establishing the Context
For every node in the target node-set, the processor establishes an evaluation context consisting of three primary components:
- Context Node: The specific node currently being evaluated.
- Context Position: The 1-based index of the current
node relative to the node-set being filtered (accessible via the
position()function). - Context Size: The total number of nodes in the
node-set being filtered (accessible via the
last()function).
2. Evaluating the Predicate Expression
The expression inside the brackets is executed once for each node using that node’s context. The expression produces a result, which is then converted to a boolean value based on the data type:
- Numeric Values: If the predicate evaluates to a
number, it is treated as a positional comparison. The condition is true
if
number == position(). For example,//item[3]is shorthand for//item[position() = 3]. - Node-Sets: If the predicate evaluates to another
node-set, it evaluates to
trueif the node-set contains at least one node, andfalseif it is empty. For example,//book[author]checks if a<book>has at least one<author>child. - Booleans: Standard boolean expressions (using
=,!=,<,>,and,or,not()) evaluate directly totrueorfalse. - Strings: A string evaluates to
trueif its length is greater than zero, andfalseif it is an empty string"".
3. Filtering the Nodes
- If the result evaluates to
true, the context node remains in the resulting node-set. - If the result evaluates to
false, the context node is discarded.
Chained Predicates
Multiple predicates can be applied sequentially to a single step:
//book[price < 30][1]
When predicates are chained: 1. The first predicate
([price < 30]) filters the original node-set to produce
an intermediate node-set. 2. The second predicate ([1]) is
evaluated against the intermediate node-set, meaning the
context positions and context sizes are recalculated starting from
1.
In this example, the expression returns the first book whose price is under 30, rather than checking if the very first book in the document costs under 30.