tags:

views:

63

answers:

3

How i can check with xpath if e node value is number?

Any ideas?

+7  A: 

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>
Oded
@Oded: Because in XPath 1.0 `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`
Alejandro
Also +1 for correct answer.
Alejandro
+2  A: 

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.

Dimitre Novatchev
+1 helpful explanation. Can someone comment on cases where `number($v) = number($v)` yields a different result from `number($v) = $v`?
LarsH
@LarsH: I already commented on these cases. Can you point out yet an undiscussed case?
Dimitre Novatchev
@Dimitre: I meant could someone list the cases where `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?
LarsH
@LarsH: I haven't looked at Oded's solution because it is obviously something I wouldn't like to use. I think Al2jandro's solution and mine solution give the same answers for any value of $v
Dimitre Novatchev
+1  A: 

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>
jasso
+1 Good detailed explanation of the issues behind the question: what the OP might have meant or would have meant if he'd known what to ask.
LarsH