XPath guide
XPath predicates, position(), and parentheses
Predict which node set an XPath predicate filters, distinguish numeric from boolean predicates, and select the first match at the intended scope.
8 min read · Updated 2026-08-21
The short answer
A predicate filters the node set produced by the step immediately before it. A numeric predicate such as [1] keeps nodes whose proximity position is 1, while a boolean predicate keeps nodes for which its expression is true. Parenthesize a complete path before [1] when you mean the first result overall rather than the first matching child under each parent.Identify the node set being filtered
XPath evaluates an axis and node test, then applies its predicates in order. The context position and size are recalculated for the current node set, so moving brackets or parentheses changes the question even when the same tokens remain visible.
//section/item[1](//section/item)[1]Separate numeric and boolean predicate semantics
The predicate [2] is positional: it is shorthand for [position() = 2]. A string or node-set expression is converted to boolean instead, so [price] keeps nodes that have a price child and [price='10'] keeps nodes with a matching value.
- Use [n] for a proximity position in the current axis order.
- Use [child] to require that child node set to be non-empty.
- Use [condition][position] when the position should apply after filtering.
- Remember that reverse axes have reverse proximity positions.
//item[@available='true'][2]//item[2][@available='true']Test scope with multiple parents and near misses
A one-parent sample cannot reveal whether [1] is applied per parent or globally. Add at least two parents, missing children, and non-matching siblings, then compare the selected node paths rather than only the returned text values.
Use last() only after deciding the current set. //section/item[last()] returns the last item under each section; (//section/item)[last()] returns the last item in the combined path result.
Prove the fix
- Run both scopesCompare node paths returned before and after parenthesizing the complete expression.
- Review position()Inspect how proximity position changes inside the current predicate context.
- Review last()Use context size only after confirming which node set is being filtered.
Related guides
- XPath first match vs first match per parentWhy //item[1] can return several nodes while (//item)[1] returns one, and how predicate context changes the result.
- Why XPath matches nothing in a default namespaceThe XPath 1.0 namespace rule behind an empty //loc result, with the prefix-bound solution and the local-name fallback.
- XPath local-name() vs namespace prefixesChoose explicit namespace bindings for precise XPath, and reserve local-name() fallbacks for deliberate namespace-agnostic inspection.
Get started
Bring order to the XML your team can't afford to ignore.
Create a free account and get a private workspace to search, validate, diff, and monitor your XML feeds, sitemaps, schemas, and vendor integrations.