Prueba XPath si el valor del nodo es número

89

¿Cómo puedo verificar si un valor de nodo es un número usando XPath?

¿Algunas ideas?

Harold Sota
fuente

Respuestas:

124

Pruebe el valor contra NaN :

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

Esta es una versión más corta (gracias @Alejandro ):

<xsl:if test="number(myNode) = myNode">
    <!-- myNode is a number -->
</xsl:if>
Oded
fuente
10
Debido a que en XPath 1.0 el NaNvalor del tipo de datos numéricos no es igual a ningún valor numérico y para la comparación, si al menos un argumento son datos numéricos escritos, el otro se convierte en número, esta es la prueba de número más corta:number(MyNode)=MyNode
10
La versión corta de @Alejandro falla completamente con XPath 2.0 debido a una falta de coincidencia de tipos en = operator ( Required item type of first operand of '=' is numeric; supplied value has item type xs:string;), la solución de Dimitre funciona bien.
Lucero
60

La forma más corta posible de probar si el valor contenido en una variable $vse puede utilizar como un número es :

number($v) = number($v)

Solo necesita sustituir lo $vanterior por la expresión cuyo valor desea probar.

Explicacion :

number($v) = number($v)es obviamente cierto, si $ves un número o una cadena que representa un número.

También es cierto para un valor booleano, porque a number(true())es 1 y number(false)es 0.

Siempre $vque no se pueda usar como número, entonces number($v)es NaN

y NaN no es igual a ningún otro valor, ni siquiera a sí mismo.

Por lo tanto, la expresión anterior es verdadera solo para $vcuyo valor se puede usar como un número y falsa en caso contrario.

Dimitre Novatchev
fuente
1
+1 explicación útil. ¿Alguien puede comentar sobre casos en los que se number($v) = number($v)obtiene un resultado diferente number($v) = $v?
LarsH
@LarsH: Ya comenté estos casos. ¿Puede señalar todavía un caso no discutido?
Dimitre Novatchev
Quiero decir, ¿podría alguien enumerar los casos en los que se number($v) = number($v)obtiene un resultado diferente number($v) = $v? Sin duda, eso se deriva de lo que escribió, pero no veo dónde se dirigió explícitamente a esta pregunta. Lo siento si estoy siendo tonto. IOW, ¿su solución y la solución de @ Oded / @ Alejandro siempre dan los mismos resultados?
LarsH
@LarsH: No he mirado la solución de Oded porque obviamente es algo que no me gustaría usar. Creo que la solución de Al2jandro y la solución mía dan las mismas respuestas para cualquier valor de $ v
Dimitre Novatchev
1
@EricS, parece que uno solo puede acceder al estándar IEEE comprándolo ... Byt, eche un vistazo aquí: cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF . En particular, este párrafo: "IEEE 754 asigna valores a todas las expresiones relacionales que involucran NaN. En la sintaxis de C, el predicado x! = Y es verdadero pero todos los demás, x <y, x <= y, x == y, x> = y y x> y, son falsas siempre que x o
yo
18

Hay un operador de prueba de tipo increíble en XPath 2.0 que puede usar:

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

No estoy tratando de proporcionar una solución alternativa más, sino una "meta vista" para este problema.

Las respuestas ya proporcionadas por Oded y Dimitre Novatchev son correctas, pero lo que la gente realmente podría querer decir con la frase "el valor es un número" es, cómo lo diría, abierto a interpretación.

En cierto modo, todo se reduce a esta pregunta que suena extraña: "¿cómo quieres expresar tus valores numéricos?"

La función XPath number()procesa números que tienen

  • posibles espacios en blanco iniciales o finales
  • carácter de signo anterior solo en valores negativos
  • punto como separador decimal (opcional para enteros)
  • todos los demás caracteres del rango [0-9]

Tenga en cuenta que esto no incluye expresiones para valores numéricos que

  • se expresan en forma exponencial (por ejemplo, 12.3E45)
  • puede contener un carácter de signo para valores positivos
  • tener una distinción entre cero positivo y negativo
  • incluir valor para infinito positivo o negativo

Estos no son solo criterios inventados. Un elemento con contenido que, según el esquema, es un xs:floatvalor válido puede contener cualquiera de las características mencionadas anteriormente. Sin embargo number(), devolvería valor NaN.

Entonces, responda a su pregunta "¿Cómo puedo verificar con XPath si el valor de un nodo es un número?" es "Use las soluciones ya mencionadas usando number()" o "con una sola expresión XPath 1.0, no puede". Piense en los posibles formatos de números que puede encontrar y, si es necesario, escriba algún tipo de lógica para la validación / análisis de números. Dentro del procesamiento XSLT, esto se puede hacer con pocas plantillas adicionales adecuadas, por ejemplo.

PD. Si solo te preocupan los números distintos de cero, la prueba más corta es

<xsl:if test="number(myNode)">
    <!-- myNode is a non-zero number -->
</xsl:if>
Jasso
fuente
1
+1 Buena explicación detallada de los problemas detrás de la pregunta: qué podría haber significado o hubiera significado el OP si hubiera sabido qué preguntar.
LarsH
9

El que encontré muy útil es el siguiente:

<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>
jkpd
fuente
2

Siempre puedes usar algo como esto:

string(//Sesscode) castable as xs:decimal

calcinable está documentado por W3C aquí .

Martti
fuente
1

He estado tratando con 01, que es numérico.

string(number($v)) != string($v) hace la segregación

Florimond
fuente