Reputation: 105043
This is my XML:
<f>
<a>10</a>
<a>2</a>
<a>4</a>
<a>13</a>
<b>55</b>
<b>4</b>
</f>
I'm trying to match elements <b/>
which are not equal to <a/>
:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="b[. != //a]">
<xsl:text>found!</xsl:text>
</xsl:template>
</xsl:stylesheet>
However, it doesn't work. I believe, my expression . != //a
is wrong, since //a
matches only the first occurrence of <a/>
. What is the right expression?
It's a test sample, please don't suggest other possible ways of solving this task. I only need a fix to the XPath expression.
Upvotes: 0
Views: 245
Reputation: 116959
The smart (and efficient) way to do this is to use a key:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="a" match="a" use="." />
<!-- other templates -->
<xsl:template match="b[not(key('a', .))]">
<!-- do something -->
</xsl:template>
</xsl:stylesheet>
To further clarify the reason why your attempt did not work is that you are comparing sequences. This comparison is defined to return true
if there is a pair of atomic values, one in the first operand sequence and the other in the second operand sequence, that have the required magnitude relationship.
IOW, your expression b[. != //a]
returns true
for any b
that is unequal to at least one a
- which in your example means for all of them.
Upvotes: 2
Reputation: 167426
Most XPath users using e.g. . != $sequence
want rather not(. = $sequence)
e.g. not(. = //a)
i.e. the current .
item is not equal to any a
element.
Upvotes: 2