In some cases, you want to find the common ancestor of two given nodes. To do this, you can use the intersect expression. The intersect expression returns all nodes that occur in both given sequences.
let $nodeA := //nodeA, $nodeB := //nodeB return ($nodeA/ancestor-or-self::* intersect $nodeB/ancestor-or-self::*)[last()]
This example explained:
The let statement is used to easily access the two given nodes.
$nodeboth result in a sequence of ancestors.
The intersection of these two sequences (or sets) is determined using the intersect expression.
The parentheses ("()") around the intersect expression are used to prevent the filter from becoming a part of the $nodeB/ancestor-or-self::* path expression.
The last step is to get the first ancestor that is common to both given nodes. For that, we'll use the
[last()]filter. Why do we use
last()if we're looking for the first ancestor that matched, you may ask? Well, that's because the result of the intersect will be sorted in document order.
Highes level nodes
This example replaces the blueprint
In some cases you want to find the highest level nodes in a given sequence of nodes. This means that we're looking for the nodes that do not have an ancestor in the given sequence. To do this, the fn:outermost function can be used.
Highest level nodes
(: Selecting some nodes. <tips> is an ancestor of <tip> :) let $input := (//tips, //tip[@id = "examples"], //title) return outermost($input)
We can check whether a node contains another node by comparing the ancestry of the node to check with the possible ancestor node.
let $possibleAncestor := //tips, $nodeToCheck := //tip[@id = "example"] return $nodeToCheck/ancestor::* = $possibleAncestor