XPath verifica se il valore del nodo è numero


89

Come posso verificare se il valore di un nodo è un numero utilizzando XPath?

Qualche idea?

Risposte:


124

Verifica il valore rispetto a NaN :

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

Questa è una versione più breve (grazie @Alejandro ):

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

10
Poiché in XPath 1.0 il NaNvalore del tipo di dati numerico non è uguale a nessun valore numerico e per confronto se almeno un argomento è un numero digitato, l'altro viene number(MyNode)=MyNode

10
La versione breve di @Alejandro fallisce completamente con XPath 2.0 a causa della mancata corrispondenza del tipo sull'operatore = ( Required item type of first operand of '=' is numeric; supplied value has item type xs:string;), la soluzione di Dimitre funziona comunque bene.
Lucero

60

Il modo più breve possibile per verificare se il valore contenuto in una variabile $vpuò essere utilizzato come numero è :

number($v) = number($v)

Devi solo sostituire quanto $vsopra con l'espressione di cui vuoi testare il valore.

Spiegazione :

number($v) = number($v)è ovviamente vero, se $vè un numero o una stringa che rappresenta un numero.

È vero anche per un valore booleano, perché a number(true())è 1 ed number(false)è 0.

Ogni volta che $vnon può essere utilizzato come numero, number($v)è NaN

e NaN non è uguale a nessun altro valore, nemmeno a se stesso.

Pertanto, l'espressione precedente è vera solo per il $vcui valore può essere utilizzato come numero e falsa in caso contrario.


1
+1 spiegazione utile. Qualcuno può commentare casi in cui number($v) = number($v)produce un risultato diverso number($v) = $v?
LarsH

@ LarsH: ho già commentato questi casi. Può segnalare ancora un caso indiscusso?
Dimitre Novatchev

Volevo dire che qualcuno potrebbe elencare i casi in cui number($v) = number($v)produce un risultato diverso number($v) = $v? Senza dubbio è derivabile da quello che hai scritto, ma non vedo dove hai affrontato questa domanda in modo esplicito. Scusa se sono ottuso. IOW, la tua soluzione e quella di @ Oded / @ Alejandro producono sempre gli stessi risultati?
LarsH

@ LarsH: non ho esaminato la soluzione di Oded perché ovviamente è qualcosa che non vorrei usare. Penso che la soluzione di Al2jandro e la mia soluzione diano le stesse risposte per qualsiasi valore di $ v
Dimitre Novatchev

1
@EricS, sembra che si possa accedere allo standard IEEE solo acquistandolo ... Byt dai un'occhiata qui: cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF . In particolare, questo paragrafo: "IEEE 754 assegna valori a tutte le espressioni relazionali che coinvolgono NaN. Nella sintassi di C, il predicato x! = Y è True ma tutti gli altri, x <y, x <= y, x == y, x> = y e x> y, sono false ogni volta che x o y o entrambi sono NaN "
Dimitre Novatchev

18

C'è un fantastico operatore di test di tipo in XPath 2.0 che puoi usare:

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

15

Non sto cercando di fornire un'altra soluzione alternativa, ma una "meta view" a questo problema.

Le risposte già fornite da Oded e Dimitre Novatchev sono corrette, ma ciò che la gente potrebbe veramente intendere con la frase "il valore è un numero" è, come direi, aperto all'interpretazione.

In un certo senso tutto arriva a questa bizzarra domanda: "come vuoi esprimere i tuoi valori numerici?"

La funzione XPath number()elabora i numeri che hanno

  • possibile spazio bianco iniziale o finale
  • carattere segno precedente solo su valori negativi
  • punto come separatore decimale (opzionale per interi)
  • tutti gli altri caratteri dell'intervallo [0-9]

Nota che questo non include espressioni per valori numerici che

  • sono espressi in forma esponenziale (es. 12.3E45)
  • può contenere un segno per i valori positivi
  • hanno una distinzione tra zero positivo e negativo
  • includi il valore per l'infinito positivo o negativo

Questi non sono solo criteri inventati. Un elemento con contenuto che è secondo lo schema un xs:floatvalore valido potrebbe contenere una qualsiasi delle caratteristiche sopra menzionate. Eppure number()restituirebbe valore NaN.

Quindi rispondi alla tua domanda "Come posso verificare con XPath se il valore di un nodo è un numero?" è "Usa soluzioni già menzionate usando number()" o "con una singola espressione XPath 1.0, non puoi". Pensa ai possibili formati numerici che potresti incontrare e, se necessario, scrivi un qualche tipo di logica per la convalida / l'analisi del numero. Nell'elaborazione XSLT, questo può essere fatto con pochi modelli aggiuntivi adatti, ad esempio.

PS. Se ti interessano solo i numeri diversi da zero, il test più breve è

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

1
+1 Buona spiegazione dettagliata dei problemi alla base della domanda: cosa avrebbe potuto significare o avrebbe significato l'OP se avesse saputo cosa chiedere.
LarsH

9

Quello che ho trovato molto utile è il seguente:

<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

Puoi sempre usare qualcosa del genere:

string(//Sesscode) castable as xs:decimal

castable è documentato da W3C qui .


1

Ho a che fare con 01, che è un numero.

string(number($v)) != string($v) fa la segregazione

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.