Recipe 1.6. Taming Complex Logic Using Quantifiers
Problem
You need to test
a
sequence for the existence of a condition in some or all of its
items.
Solution
XPath 1.0
If the condition is based on equality, then the semantics of the
= and != operators in XPath 1.0
and 2.0 will suffice.
(: True if at least one section is referenced. :)
//section/@id = //ref/@idref
(: True if all section elements are referenced by some ref element. :)
count(//section) = count(//section[@id = //ref/@idref])
XPath 2.0
In XPath 2.0, use some and
every expressions to do the same.
(: True if at least one section is referenced. :)
some $id in //para/@id satisfies $id = //ref/@idref
(: True if all section elements are referenced by some ref element. :)
every $id in //section/@id satisfies $id = //ref/@idref
However, you can go quite a bit further with less effort in XPath 2.0.
(: There exists a section that references every section except itself. :)
some $s in //section satisfies
every $id in //section[@id ne $s/@id]/@id satisfies $id = $s/ref/@idref
(: $sequence2 is a sub-sequence of $sequence1 :)
count($sequence2) <= count($sequence1) and
every $pos in 1 to count($sequence1),
$item1 in $sequence1[$pos],
$item2 in $sequence2[$pos] satisfies $item1 = $item2
If you remove the count check in the preceding expression, it would
assert that at least the first count($sequence1)
items in $sequence2 are the same as corresponding
items in $sequence1.
Discussion
The semantics of =, !=, <, >, <=, >= in XPath 1.0 and 2.0
sometimes surprise the uninitiated when one of the operands is a
sequence or XPath 1.0 node set. This is because the operators
evaluate to true if there is at least one pair of values from each
side of the expression which compare according to the relation. In
XPath 1.0, this can sometimes work to your advantage, as we have
shown previously, but other times it can leave your head spinning and
you longing to be back in the 5th grade where math made sense. For
example, one would guess that $x = $x should
always be true, but if $x is the empty sequence,
it is not! This follows from the fact that you cannot find a pair of
items within each empty sequence that are equal.
 |