XPath测试节点值是否为数字


89

如何使用XPath检查节点值是否为数字?

有任何想法吗?

Answers:


124

根据NaN测试值:

<xsl:if test="string(number(myNode)) != 'NaN'">
    <!-- myNode is a number -->
</xsl:if>

这是一个较短的版本(感谢@Alejandro):

<xsl:if test="number(myNode) = myNode">
    <!-- myNode is a number -->
</xsl:if>

10
因为在XPath 1.0中NaN,数字数据类型的值不等于任何数字值,并且为了比较,如果至少一个参数是数字数据类型,则将另一个number(MyNode)=MyNode

10
@Alejandro的简短版本由于=运算符(Required item type of first operand of '=' is numeric; supplied value has item type xs:string;)上的类型不匹配而在XPath 2.0中完全失败,但是Dimitre的解决方案可以正常工作。
Lucero

60

测试变量中包含的值是否$v可以用作数字的最短方法是

number($v) = number($v)

您只需要用$v要测试其值的表达式替换上面的内容。

说明

number($v) = number($v)如果$v是数字或表示数字的字符串,则显然是正确的。

对于布尔值也是如此,因为a number(true())为1并且number(false)为0。

每当$v不能用作数字时,number($v)NaN

NaN不等于任何其他值,甚至不等于其自身。

因此,以上表达式仅对$v于其值可以用作数字的情况为真,否则为false。


1
+1有用的解释。有人可以评论number($v) = number($v)产生不同结果的情况number($v) = $v吗?
LarsH

@LarsH:我已经对这些案例发表了评论。您能指出一个尚未讨论的案例吗?
Dimitre Novatchev

我的意思是,有人可以列出number($v) = number($v)产生不同结果的情况number($v) = $v吗?毫无疑问,这可以从您写的内容中得出,但是我看不到您在哪里明确提出了这个问题。对不起,如果我很忙。IOW,您的解决方案和@ Oded's / @ Alejandro的解决方案是否总是产生相同的结果?
LarsH 2010年

@LarsH:我没有看过Oded的解决方案,因为显然我不想使用它。我认为Al2jandro的解决方案和我的解决方案对于$ v的任何值都给出相同的答案
Dimitre Novatchev 2010年

1
@EricS,看来只有购买才能访问IEEE标准... Byt的确在这里查看:cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF。特别是,本段:“ IEEE 754将值赋给涉及NaN的所有关系表达式。在C的语法中,谓词x!= y为True,但所有其他谓词x <y,x <= y,x == y, x> = y和x> y,每当x或y或两者均为NaN时均为False”
Dimitre Novatchev

18

XPath 2.0中有一个很棒的类型测试操作符,您可以使用:

<xsl:if test="$number castable as xs:double">
    <!-- implementation -->
</xsl:if>

15

我不是要提供另一个替代解决方案,而是要解决此问题的“元视图”。

Oded和Dimitre Novatchev已经提供的答案是正确的,但人们对“价值就是数字”一词的真正含义是,我怎么说,这是可以解释的。

在某种程度上,这涉及到一个听起来很奇怪的问题:“您想如何表达数值?”

XPath函数number()处理具有

  • 可能的前导或尾随空格
  • 前面的符号字符仅在负值上
  • 作为小数点分隔符(整数可选)
  • [0-9]范围内的所有其他字符

请注意,这不包括数值表达式

  • 以指数形式表示(例如12.3E45)
  • 可能包含正号的符号字符
  • 区分正负零
  • 包含正或负无穷大的值

这些不仅仅是组成标准。内容根据架构为有效值的元素xs:float可能包含上述任何特征。然而,number()将返回值NaN

因此,回答您的问题“如果节点值是数字,我如何使用XPath进行检查?” 是“使用已经提到的解决方案使用number()”或“不能使用单个XPath 1.0表达式”。考虑一下您可能会遇到的数字格式,如果需要,请编写某种逻辑进行验证/数字解析。例如,在XSLT处理中,这可以使用少量合适的额外模板来完成。

PS。如果您只关心非零数字,则最短的检验是

<xsl:if test="number(myNode)">
    <!-- myNode is a non-zero number -->
</xsl:if>

1
+1很好地详细说明了问题背后的问题:如果OP知道要问什么,则OP可能意味着什么。
LarsH 2010年

9

我发现非常有用的是以下内容:

<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>

2

您可以始终使用以下内容:

string(//Sesscode) castable as xs:decimal

W3C 在此处记录了Castable 。


1

我一直在处理01-这是一个数字。

string(number($v)) != string($v) 使隔离

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.