How can I check if a node value is a number using XPath?
Any ideas?
Test the value against NaN:
<xsl:if test="string(number(myNode)) != 'NaN'">
<!-- myNode is a number -->
</xsl:if>
This is a shorter version (thanks @Alejandro):
<xsl:if test="number(myNode) = myNode">
<!-- myNode is a number -->
</xsl:if>
The shortest possible way to test if the value contained in a variable $v
can be used as a number is:
number($v) = number($v)
You only need to substitute the $v
above with the expression whose value you want to test.
Explanation:
number($v) = number($v)
is obviously true, if $v
is a number, or a string that represents a number.
It is true also for a boolean value, because a number(true())
is 1 and number(false)
is 0.
Whenever $v
cannot be used as a number, then number($v)
is NaN
and NaN is not equal to any other value, even to itself.
Thus, the above expression is true only for $v
whose value can be used as a number, and false otherwise.
number($v) = number($v)
yields a different result from number($v) = $v
?
number($v) = number($v)
yields a different result from number($v) = $v
? Doubtless that's derivable from what you wrote, but I'm not seeing where you addressed this question explicitly. Sorry if I'm being dense. IOW, does your solution and @Oded's/@Alejandro's solution always yield the same results?
There's an amazing type test operator in XPath 2.0 you can use:
<xsl:if test="$number castable as xs:double">
<!-- implementation -->
</xsl:if>
I'm not trying to provide a yet another alternative solution, but a "meta view" to this problem.
Answers already provided by Oded and Dimitre Novatchev are correct but what people really might mean with phrase "value is a number" is, how would I say it, open to interpretation.
In a way it all comes to this bizarre sounding question: "how do you want to express your numeric values?"
XPath function number()
processes numbers that have
possible leading or trailing whitespace
preceding sign character only on negative values
dot as an decimal separator (optional for integers)
all other characters from range [0-9]
Note that this doesn't include expressions for numerical values that
are expressed in exponential form (e.g. 12.3E45)
may contain sign character for positive values
have a distinction between positive and negative zero
include value for positive or negative infinity
These are not just made up criteria. An element with content that is according to schema a valid xs:float
value might contain any of the above mentioned characteristics. Yet number()
would return value NaN
.
So answer to your question "How i can check with XPath if a node value is number?" is either "Use already mentioned solutions using number()
" or "with a single XPath 1.0 expression, you can't". Think about the possible number formats you might encounter, and if needed, write some kind of logic for validation/number parsing. Within XSLT processing, this can be done with few suitable extra templates, for example.
PS. If you only care about non-zero numbers, the shortest test is
<xsl:if test="number(myNode)">
<!-- myNode is a non-zero number -->
</xsl:if>
The one I found very useful is the following:
<xsl:choose>
<xsl:when test="not(number(myNode))">
<!-- myNode is a not a number or empty(NaN) or zero -->
</xsl:when>
<xsl:otherwise>
<!-- myNode is a number (!= zero) -->
</xsl:otherwise>
</xsl:choose>
You could always use something like this:
string(//Sesscode) castable as xs:decimal
castable is documented by W3C here.
I've been dealing with 01 - which is a numeric.
string(number($v)) != string($v)
makes the segregation
Success story sharing
NaN
value of number data type doesn't equal to any number value and for comparison if at least one argument is number data typed then the other is cast to number, this is the shortest number test:number(MyNode)=MyNode
Required item type of first operand of '=' is numeric; supplied value has item type xs:string;
), Dimitre's solution works fine however.