ChatGPT解决这个技术问题 Extra ChatGPT

XPath test if node value is number

How can I check if a node value is a number using XPath?

Any ideas?


C
Community

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>

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
The short version by @Alejandro completely fails with XPath 2.0 due to type mismatch on the = operator (Required item type of first operand of '=' is numeric; supplied value has item type xs:string;), Dimitre's solution works fine however.
D
Dimitre Novatchev

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.


+1 helpful explanation. Can someone comment on cases where number($v) = number($v) yields a different result from number($v) = $v?
@LarsH: I already commented on these cases. Can you point out yet an undiscussed case?
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: 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
@EricS, It seems one can only access the IEEE standard by purchasing it... Byt do have a look here: cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF . In particular, this paragraph: "IEEE 754 assigns values to all relational expressions involving NaN . In the syntax of C , the predicate x != y is True but all others, x < y , x <= y , x == y , x >= y and x > y , are False whenever x or y or both are NaN"
s
shapiy

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>

j
jasso

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>

+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.
j
jkpd

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>

N
Necrolis

You could always use something like this:

string(//Sesscode) castable as xs:decimal

castable is documented by W3C here.


F
Florimond

I've been dealing with 01 - which is a numeric.

string(number($v)) != string($v) makes the segregation