XPath-Test, wenn der Knotenwert die Nummer ist

89

Wie kann ich mit XPath überprüfen, ob ein Knotenwert eine Zahl ist?

Irgendwelche Ideen?

Harold Sota
quelle

Antworten:

124

Testen Sie den Wert gegen NaN :

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

Dies ist eine kürzere Version (danke @Alejandro ):

<xsl:if test="number(myNode) = myNode">
    <!-- myNode is a number -->
</xsl:if>
Oded
quelle
10
Da in XPath 1.0 der NaNWert des Zahlendatentyps keinem Zahlenwert entspricht und zum Vergleich, wenn mindestens ein Argument aus Zahlendaten besteht, das andere in Zahl umgewandelt wird, ist dies der kürzeste number(MyNode)=MyNode
10
Die Kurzversion von @Alejandro schlägt mit XPath 2.0 aufgrund von Typinkongruenzen auf dem Operator = vollständig fehl. Required item type of first operand of '=' is numeric; supplied value has item type xs:string;Die Lösung von Dimitre funktioniert jedoch einwandfrei.
Lucero
59

Der kürzest mögliche Weg, um zu testen, ob der in einer Variablen enthaltene Wert $vals Zahl verwendet werden kann, ist :

number($v) = number($v)

Sie müssen nur das $vObige durch den Ausdruck ersetzen, dessen Wert Sie testen möchten.

Erklärung :

number($v) = number($v)ist offensichtlich wahr, wenn $ves sich um eine Zahl oder eine Zeichenfolge handelt, die eine Zahl darstellt.

Dies gilt auch für einen booleschen Wert, da a number(true())1 und number(false)0 ist.

Wann $vimmer nicht als Zahl verwendet werden kann, number($v)ist NaN

und NaN ist keinem anderen Wert gleich, auch nicht sich selbst gegenüber.

Somit ist der obige Ausdruck nur wahr, für $vdessen Wert eine Zahl verwendet werden kann, und ansonsten falsch.

Dimitre Novatchev
quelle
1
+1 hilfreiche Erklärung. Kann jemand Fälle kommentieren, in denen number($v) = number($v)ein anderes Ergebnis erzielt wird als number($v) = $v?
LarsH
@LarsH: Ich habe diese Fälle bereits kommentiert. Können Sie noch auf einen nicht diskutierten Fall hinweisen?
Dimitre Novatchev
Ich meinte, könnte jemand die Fälle number($v) = number($v)auflisten, in denen ein anderes Ergebnis erzielt wird als number($v) = $v? Zweifellos lässt sich das von dem ableiten, was Sie geschrieben haben, aber ich sehe nicht, wo Sie diese Frage explizit angesprochen haben. Entschuldigung, wenn ich dicht bin. IOW, liefern Ihre Lösung und die Lösung von @ Oded / @ Alejandro immer die gleichen Ergebnisse?
LarsH
@LarsH: Ich habe mir Odeds Lösung nicht angesehen, weil ich sie offensichtlich nicht gerne verwenden würde. Ich denke, Al2jandros Lösung und meine Lösung geben die gleichen Antworten für jeden Wert von $ v
Dimitre Novatchev
1
@EricS, anscheinend kann man nur durch den Kauf auf den IEEE-Standard zugreifen ... Schauen Sie doch mal hier vorbei: cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF . Insbesondere dieser Absatz: "IEEE 754 weist allen relationalen Ausdrücken, an denen NaN beteiligt ist, Werte zu. In der Syntax von C ist das Prädikat x! = Y True, aber alle anderen, x <y, x <= y, x == y, x> = y und x> y sind falsch, wenn x oder y oder beide NaN sind "
Dimitre Novatchev
18

In XPath 2.0 gibt es einen erstaunlichen Typ-Test-Operator, den Sie verwenden können:

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

Ich versuche nicht, eine weitere alternative Lösung bereitzustellen, sondern eine "Meta-Ansicht" für dieses Problem.

Die Antworten von Oded und Dimitre Novatchev sind richtig, aber was die Leute wirklich mit dem Ausdruck "Wert ist eine Zahl" meinen könnten, ist, wie würde ich sagen, offen für Interpretationen.

In gewisser Weise kommt alles auf diese bizarr klingende Frage an: "Wie wollen Sie Ihre numerischen Werte ausdrücken?"

Die XPath-Funktion number()verarbeitet Zahlen mit

  • mögliche führende oder nachfolgende Leerzeichen
  • Vorzeichen nur bei negativen Werten
  • Punkt als Dezimaltrennzeichen (optional für ganze Zahlen)
  • alle anderen Zeichen aus dem Bereich [0-9]

Beachten Sie, dass dies keine Ausdrücke für numerische Werte enthält, die

  • werden in Exponentialform ausgedrückt (zB 12.3E45)
  • kann Vorzeichen für positive Werte enthalten
  • unterscheiden zwischen positiver und negativer Null
  • Wert für positive oder negative Unendlichkeit einschließen

Dies sind nicht nur erfundene Kriterien. Ein Element mit einem Inhalt, dessen Schema einem gültigen xs:floatWert entspricht, kann eines der oben genannten Merkmale enthalten. Dennoch number()würde Wert zurückgeben NaN.

Beantworten Sie also Ihre Frage "Wie kann ich mit XPath prüfen, ob ein Knotenwert eine Zahl ist?" ist entweder "Verwenden Sie bereits erwähnte Lösungen mit number()" oder "Mit einem einzelnen XPath 1.0-Ausdruck können Sie nicht". Denken Sie über die möglichen Zahlenformate nach, auf die Sie möglicherweise stoßen, und schreiben Sie bei Bedarf eine Logik für die Validierung / Zahlenanalyse. Innerhalb der XSLT-Verarbeitung kann dies beispielsweise mit wenigen geeigneten zusätzlichen Vorlagen erfolgen.

PS. Wenn Sie sich nur für Zahlen ungleich Null interessieren, ist der kürzeste Test

<xsl:if test="number(myNode)">
    <!-- myNode is a non-zero number -->
</xsl:if>
jasso
quelle
1
+1 Gute detaillierte Erklärung der Probleme hinter der Frage: Was hätte das OP bedeuten können oder hätte bedeuten können, wenn er gewusst hätte, was zu fragen ist?
LarsH
9

Das, was ich sehr nützlich fand, ist das Folgende:

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

Sie könnten immer so etwas verwenden:

string(//Sesscode) castable as xs:decimal

castable wird hier von W3C dokumentiert .

Martti
quelle
1

Ich habe es mit 01 zu tun - was eine Zahl ist.

string(number($v)) != string($v) macht die Trennung

Florimond
quelle