XPath menguji apakah nilai node adalah angka

89

Bagaimana cara memeriksa apakah nilai node adalah angka yang menggunakan XPath?

Ada ide?

Harold Sota
sumber

Jawaban:

124

Uji nilai terhadap NaN :

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

Ini adalah versi yang lebih pendek (terima kasih @Alejandro ):

<xsl:if test="number(myNode) = myNode">
    <!-- myNode is a number -->
</xsl:if>
Oded
sumber
10
Karena di XPath 1.0 NaNnilai tipe data angka tidak sama dengan nilai angka manapun dan untuk perbandingan jika setidaknya satu argumen adalah data angka yang diketik maka yang lain dilemparkan ke angka, ini adalah tes angka terpendek:number(MyNode)=MyNode
10
Versi singkat oleh @Alejandro benar-benar gagal dengan XPath 2.0 karena jenis ketidakcocokan pada = operator ( Required item type of first operand of '=' is numeric; supplied value has item type xs:string;), solusi Dimitre bekerja dengan baik namun.
Lucero
61

Cara sesingkat mungkin untuk menguji apakah nilai yang terkandung dalam variabel $vdapat digunakan sebagai angka adalah :

number($v) = number($v)

Anda hanya perlu mengganti di $vatas dengan ekspresi yang nilainya ingin Anda uji.

Penjelasan :

number($v) = number($v)jelas benar, jika $vadalah angka, atau string yang mewakili angka.

Ini juga berlaku untuk nilai boolean, karena a number(true())bernilai 1 dan number(false)bernilai 0.

Kapanpun $vtidak bisa digunakan sebagai angka, maka number($v)NaN

dan NaN tidak sama dengan nilai lainnya, bahkan untuk nilai itu sendiri.

Jadi, ekspresi di atas benar hanya untuk $vyang nilainya dapat digunakan sebagai angka, dan salah jika tidak.

Dimitre Novatchev
sumber
1
+1 penjelasan yang berguna. Dapatkah seseorang mengomentari kasus-kasus di mana memberikan number($v) = number($v)hasil yang berbeda number($v) = $v?
LarsH
@ LarsH: Saya sudah mengomentari kasus ini. Bisakah Anda menunjukkan kasus yang belum didiskusikan?
Dimitre Novatchev
Maksud saya, bisakah seseorang mendaftar kasus-kasus di mana number($v) = number($v)menghasilkan hasil yang berbeda number($v) = $v? Tidak diragukan lagi itu berasal dari apa yang Anda tulis, tetapi saya tidak melihat di mana Anda menjawab pertanyaan ini secara eksplisit. Maaf jika saya sedang bebal. IOW, apakah solusi Anda dan solusi @ Oded / @ Alejandro selalu memberikan hasil yang sama?
LarsH
@ LarsH: Saya belum melihat solusi Oded karena ini jelas sesuatu yang tidak ingin saya gunakan. Saya pikir solusi Al2jandro dan solusi saya memberikan jawaban yang sama untuk setiap nilai $ v
Dimitre Novatchev
1
@EricS, Sepertinya orang hanya dapat mengakses standar IEEE dengan membelinya ... Byt lihat di sini: cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF . Secara khusus, paragraf ini: "IEEE 754 memberikan nilai ke semua ekspresi relasional yang melibatkan NaN. Dalam sintaks C, predikat x! = Y adalah True tetapi yang lainnya, x <y, x <= y, x == y, x> = y dan x> y, bernilai False jika x atau y atau keduanya adalah NaN "
Dimitre Novatchev
18

Ada operator uji tipe luar biasa di XPath 2.0 yang dapat Anda gunakan:

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

Saya tidak mencoba memberikan solusi alternatif lain, tetapi "tampilan meta" untuk masalah ini.

Jawaban yang sudah diberikan oleh Oded dan Dimitre Novatchev benar tapi apa yang orang maksud dengan frase "nilai adalah angka" adalah, bagaimana saya mengatakannya, terbuka untuk interpretasi.

Di satu sisi, semuanya sampai pada pertanyaan yang terdengar aneh ini: "bagaimana Anda ingin mengekspresikan nilai numerik Anda?"

Fungsi XPath number()memproses angka yang memiliki

  • spasi di depan atau di belakang mungkin
  • karakter tanda sebelumnya hanya pada nilai negatif
  • titik sebagai pemisah desimal (opsional untuk bilangan bulat)
  • semua karakter lain dari rentang [0-9]

Perhatikan bahwa ini tidak termasuk ekspresi untuk nilai numerik itu

  • diekspresikan dalam bentuk eksponensial (misalnya 12.3E45)
  • dapat berisi karakter tanda untuk nilai positif
  • memiliki perbedaan antara nol positif dan negatif
  • sertakan nilai untuk positif atau negatif tak terhingga

Ini bukan hanya kriteria yang dibuat-buat. Elemen dengan konten yang sesuai dengan skema dengan xs:floatnilai yang valid mungkin berisi salah satu karakteristik yang disebutkan di atas. Namun number()akan mengembalikan nilai NaN.

Jadi jawaban atas pertanyaan Anda "Bagaimana saya dapat memeriksa dengan XPath jika nilai node adalah angka?" adalah "Gunakan solusi yang telah disebutkan menggunakannumber() " atau "dengan ekspresi XPath 1.0 tunggal, Anda tidak bisa". Pikirkan tentang kemungkinan format angka yang mungkin Anda temui, dan jika perlu, tulis beberapa jenis logika untuk validasi / penguraian angka. Dalam pemrosesan XSLT, ini dapat dilakukan dengan beberapa templat tambahan yang sesuai, misalnya.

PS. Jika Anda hanya peduli dengan angka bukan nol, tes terpendek adalah

<xsl:if test="number(myNode)">
    <!-- myNode is a non-zero number -->
</xsl:if>
jasso
sumber
1
+1 Penjelasan mendetail yang baik tentang masalah di balik pertanyaan: apa maksud OP atau yang akan dimaksudkan jika dia tahu apa yang harus ditanyakan.
LarsH
9

Yang menurut saya sangat berguna adalah sebagai berikut:

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

Anda selalu bisa menggunakan sesuatu seperti ini:

string(//Sesscode) castable as xs:decimal

castable didokumentasikan oleh W3C di sini .

Martti
sumber
1

Saya telah berurusan dengan 01 - yang merupakan numerik.

string(number($v)) != string($v) membuat pemisahan

Florimond
sumber