XPath test if node value is number

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.


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>