Reputation: 455
What is the difference between the not()
operator and !=
?
See this example:
<?xml version="1.0" encoding="UTF-8"?>
<body>
<test>123</test>
</body>
<xsl:template match="/">
<xsl:if test = "/body/test = (123, 2)">true1</xsl:if>
<xsl:if test = "not(/body/test != (123, 2))">true2</xsl:if>
</xsl:template>
http://xsltransform.net/jyH9rMx
Why do i get true1
as a result, but not true2
? I would expect the two lines to be equivalent. Why are they not?
Upvotes: 5
Views: 7416
Reputation: 163262
It might be worth noting the difference between how XPath handles this and how SQL handles it. SQL uses three-valued logic and NULL values, so the effect is that if AUTHOR is absent (null) then AUTHOR="Kay"
and AUTHOR!="Kay"
both produce "null" (or "undefined", I think they call it), which means that when either expression is used as a predicate in a WHERE clause, the relevant row is not selected. XPath also produces the result that if AUTHOR is absent, neither of the predicates AUTHOR="Kay"
and AUTHOR!="Kay"
cause the item to be selected; but unlike SQL, there is no three-valued logic, and this is achieved by having both predicates return false. But the consequence of the predicate returning false is that its inverse (not(P))
returns true, which leads to the surprising result that not(AUTHOR="Kay")
has a different effect from AUTHOR!="Kay"
.
Upvotes: 2
Reputation: 122364
The key thing to realise with the "general" comparison operators in XPath (including =
and !=
) is that they are implicitly existentially quantified over their argument sequences. The expression X = Y
means the same as the explicitly quantified expression
some $x in X, $y in Y satisfies $x eq $y
(eq
being the single item equality operator). So not(X = Y)
means
not(some $x in X, $y in Y satisfies $x eq $y)
which is equivalent to saying
every $x in X, $y in Y satisfies $x ne $y
Conversely X != Y
means
some $x in X, $y in Y satisfies $x ne $y
Upvotes: 3
Reputation: 22617
I have no idea why you are testing against a sequence of items, but the reason
/body/test != (123,2)
returns true
is that there is indeed one element in this sequence which is not equal to the value inside test
, namely "123". This kind of condition returns true, even if not all items in a sequence pass the test.
If you remove ,2
from this sequence:
/body/test != (123)
this will no longer return true, and its inverse
not(/body/test != (123)
will return true.
Stylesheet
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="text" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<xsl:if test = "/body/test = (123,2,3,4)">true1</xsl:if>
<xsl:if test = "not(/body/test != (123))">true2</xsl:if>
</xsl:template>
</xsl:transform>
Result
true1true2
Upvotes: 1
Reputation: 116959
To answer the question/s you didn't ask, but should have:
"123 = (123, 2)"
returns true because 123 is equal to 123.
"not(123 = (123, 2))"
returns false because as shown above, the inner expression is true - and the outer not() merely reverses it.
"123 != (123, 2)"
returns true, because 123 is not-equal to 2.
"not(123 != (123, 2))"
returns false because as shown above, the inner expression is true, and the outer not() merely reverses it.
For reference, see: http://www.w3.org/TR/xpath20/#id-value-comparisons
Upvotes: 6