On the one hand, in the XPath language, familiar to each programmer is used the comparison operators "equal", "not equal", "less", "more" and others. On the other hand, these operators can work not only with primitive types, but also with whole sets of nodes. Ignorance of the rules for comparing node sets can lead to some surprises.
Try to quickly answer the question, what is the following expression:
foo = 'bar' and foo != 'bar'
If your answer is
false
, the author suggests
read more.
')
Comparing Node to String
A simple task: check if the
foo
attribute is equal to the string
'bar'
:
@foo = 'bar'
When solving the inverse problem, quite often you can see the following code:
@foo != 'bar'
In most cases, this code works as expected. However, in the case where the
foo
attribute is missing, this expression returns
false
. If you carefully read the documentation and translate
@foo != 'bar'
into Russian, you get the following:
there is at least one attribute foo
that is not equal to 'bar'
. In the absence of the
foo
attribute, the condition is not met, hence
false
.
The correct solution of the problem:
not(@foo = 'bar')
What is translated into Russian means:
there is not a single attribute foo
, equal to 'bar'
.
Comparing node set with string
Take the following document:
<list>
<item>foo</item>
<item>bar</item>
<item>baz</item>
</list>
Let us apply various combinations of operators of equality, inequality and negation:
Expression | Transfer | Result |
---|
item = 'foo' | There is at least one element equal to 'foo' . | true |
item != 'bar' | There is at least one element not equal to 'bar' . | true |
not(item = 'foo') | There is not a single element equal to 'foo' . | false |
not(item != 'baz') | All available elements are equal to 'baz' . | false |
As you can see, it is possible that the expression
item = 'foo' and item != 'foo'
returns
true
.
Verify node identity
When comparing the two nodes, they are reduced to a string. What if you need to check not the coincidence of the string representation, but the identity? In other words, it is necessary to establish that the two nodes being checked are the same node. Such a task, for example, is found in
the Münch grouping .
The first solution is pure XPath:
count($foo | $bar) = 1
This expression uses the property of
the union operator , which consists in the fact that the same node cannot enter into the result of an operation twice. If the result is a single node, then the source nodes are identical.
The second solution uses the
generate-id XSLT function:
generate-id($foo) = generate-id($bar)
This function by definition returns the same result for the same node. If the results of the function are equal, then the source nodes are identical.
Comments and additions are welcome.