XPath ทดสอบว่าค่าโหนดเป็นตัวเลขหรือไม่


คำตอบ:


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
เนื่องจากในNaNค่าXPath 1.0 ของชนิดข้อมูลตัวเลขไม่เท่ากับค่าตัวเลขใด ๆ และสำหรับการเปรียบเทียบหากอาร์กิวเมนต์อย่างน้อยหนึ่งอาร์กิวเมนต์เป็นข้อมูลตัวเลขที่พิมพ์จากนั้นอีกอาร์กิวเมนต์จะถูกส่งไปยังตัวเลขนี่เป็นการทดสอบตัวเลขที่สั้นที่สุด:number(MyNode)=MyNode

10
เวอร์ชันสั้นโดย @Alejandro ล้มเหลวอย่างสมบูรณ์กับ XPath 2.0 เนื่องจากพิมพ์ไม่ตรงกันบนตัวดำเนินการ = ( Required item type of first operand of '=' is numeric; supplied value has item type xs:string;) โซลูชันของ Dimitre ทำงานได้ดี
Lucero

61

วิธีที่สั้นที่สุดในการทดสอบว่าค่าที่อยู่ในตัวแปร$vสามารถใช้เป็นตัวเลขได้หรือไม่คือ :

number($v) = number($v)

คุณต้องแทนที่$vข้างต้นด้วยนิพจน์ที่คุณต้องการทดสอบเท่านั้น

คำอธิบาย :

number($v) = number($v)เห็นได้ชัดว่าเป็นจริงถ้า$vเป็นตัวเลขหรือสตริงที่แสดงถึงตัวเลข

เป็นจริงสำหรับค่าบูลีนเนื่องจาก a number(true())คือ 1 และnumber(false)เป็น 0

เมื่อใดก็ตามที่$vไม่สามารถใช้เป็นตัวเลขได้ก็number($v)จะเป็น NaN

และ NaN ไม่เท่ากับค่าอื่น ๆ แม้แต่กับตัวมันเอง

ดังนั้นนิพจน์ด้านบนจึงเป็นจริงเฉพาะสำหรับ$vค่าที่สามารถใช้เป็นตัวเลขได้และเป็นเท็จ


1
+1 คำอธิบายที่เป็นประโยชน์ ใครสามารถแสดงความคิดเห็นเกี่ยวกับกรณีที่number($v) = number($v)ให้ผลลัพธ์ที่แตกต่างจากnumber($v) = $v?
LarsH

@LarsH: ฉันแสดงความคิดเห็นเกี่ยวกับกรณีเหล่านี้แล้ว คุณสามารถชี้ให้เห็นถึงกรณีที่ยังไม่ได้สนทนาได้หรือไม่?
Dimitre Novatchev

ฉันหมายถึงใครบางคนสามารถระบุกรณีที่number($v) = number($v)ให้ผลลัพธ์ที่แตกต่างจากnumber($v) = $v? ไม่ต้องสงสัยเลยว่ามีที่มาจากสิ่งที่คุณเขียน แต่ฉันไม่เห็นว่าคุณตอบคำถามนี้อย่างชัดเจนที่ใด ขออภัยหากฉันหนาแน่น IOW โซลูชันของคุณและโซลูชันของ @ Oded / @ Alejandro ให้ผลลัพธ์เหมือนกันหรือไม่?
LarsH

@ LarsH: ฉันไม่ได้ดูวิธีแก้ปัญหาของ Oded เพราะเห็นได้ชัดว่าเป็นสิ่งที่ฉันไม่ต้องการใช้ ฉันคิดว่าโซลูชันของ Al2jandro และโซลูชันของฉันให้คำตอบเหมือนกันสำหรับมูลค่า $ v
Dimitre Novatchev

1
@EricS ดูเหมือนว่าเพียงคนเดียวที่สามารถเข้าถึงมาตรฐาน IEEE โดยการซื้อมัน ... คอนจะมีรูปลักษณ์ที่นี่: cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF โดยเฉพาะอย่างยิ่งย่อหน้านี้: "IEEE 754 กำหนดค่าให้กับนิพจน์เชิงสัมพันธ์ทั้งหมดที่เกี่ยวข้องกับ NaN ในไวยากรณ์ของ C เพรดิเคต x! = y เป็น True แต่อื่น ๆ ทั้งหมดคือ x <y, x <= y, x == y, x> = y และ x> y เป็น False เมื่อใดก็ตามที่ x หรือ y หรือทั้งคู่เป็น NaN "
Dimitre Novatchev

18

มีตัวดำเนินการทดสอบประเภทที่น่าทึ่งใน XPath 2.0 ที่คุณสามารถใช้ได้:

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

15

ฉันไม่ได้พยายามหาทางเลือกอื่น แต่เป็น "มุมมองเมตา" สำหรับปัญหานี้

คำตอบที่ Oded และ Dimitre Novatchev ให้ไว้แล้วนั้นถูกต้อง แต่สิ่งที่ผู้คนอาจหมายถึงจริงๆกับวลี "value is a number" คือฉันจะพูดอย่างไรโดยเปิดให้มีการตีความ

ในทางกลับกันคำถามที่ฟังดูแปลกประหลาดนี้: "คุณต้องการแสดงค่าตัวเลขของคุณอย่างไร"

ฟังก์ชัน XPath number()ประมวลผลตัวเลขที่มี

  • ช่องว่างนำหน้าหรือต่อท้ายที่เป็นไปได้
  • อักขระเครื่องหมายนำหน้าเฉพาะค่าลบ
  • จุดเป็นตัวคั่นทศนิยม (ไม่บังคับสำหรับจำนวนเต็ม)
  • อักขระอื่น ๆ ทั้งหมดจากช่วง [0-9]

โปรดทราบว่าสิ่งนี้ไม่รวมนิพจน์สำหรับค่าตัวเลขที่

  • แสดงในรูปแบบเลขชี้กำลัง (เช่น 12.3E45)
  • อาจมีอักขระเครื่องหมายสำหรับค่าบวก
  • มีความแตกต่างระหว่างศูนย์บวกและลบ
  • รวมค่าอินฟินิตี้บวกหรือลบ

สิ่งเหล่านี้ไม่ได้สร้างขึ้นเพียงเกณฑ์ องค์ประกอบที่มีเนื้อหาตามสคีมาxs:floatค่าที่ถูกต้องอาจมีลักษณะที่กล่าวถึงข้างต้น แต่จะกลับมาคุ้มค่าnumber()NaN

ดังนั้นตอบคำถามของคุณ "ฉันจะตรวจสอบกับ XPath ได้อย่างไรว่าค่าโหนดเป็นตัวเลข" คือ "ใช้โซลูชันที่กล่าวถึงแล้วโดยใช้number()" หรือ "ด้วยนิพจน์ XPath 1.0 เดียวคุณทำไม่ได้" ลองนึกถึงรูปแบบตัวเลขที่เป็นไปได้ที่คุณอาจพบและหากจำเป็นให้เขียนตรรกะบางอย่างสำหรับการตรวจสอบความถูกต้อง / การแยกวิเคราะห์ตัวเลข ภายในการประมวลผล XSLT สามารถทำได้โดยใช้เทมเพลตพิเศษที่เหมาะสมไม่กี่ตัวอย่างเช่น

ปล. หากคุณสนใจเฉพาะตัวเลขที่ไม่ใช่ศูนย์การทดสอบที่สั้นที่สุดคือ

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

1
+1 คำอธิบายโดยละเอียดที่ดีเกี่ยวกับปัญหาที่อยู่เบื้องหลังคำถาม: สิ่งที่ OP อาจหมายถึงหรือมีความหมายหากเขารู้ว่าจะถามอะไร
LarsH

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

castable เป็นเอกสารโดย W3C ที่นี่


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.