Kiểm tra XPath nếu giá trị nút là số


89

Làm cách nào để kiểm tra xem giá trị nút có phải là một số hay không bằng cách sử dụng XPath?

Bất kỳ ý tưởng?

Câu trả lời:


124

Kiểm tra giá trị so với NaN :

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

Đây là phiên bản ngắn hơn (cảm ơn @Alejandro ):

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

10
Bởi vì trong XPath 1.0 NaNgiá trị của kiểu dữ liệu số không bằng bất kỳ giá trị số và để so sánh nếu có ít nhất một đối số là dữ liệu số gõ thì khác là diễn viên đến số, đây là bài kiểm tra số ngắn nhất:number(MyNode)=MyNode

10
Phiên bản ngắn của @Alejandro hoàn toàn không thành công với XPath 2.0 do kiểu không khớp trên = operator ( Required item type of first operand of '=' is numeric; supplied value has item type xs:string;), tuy nhiên, giải pháp của Dimitre hoạt động tốt.
Lucero

60

Cách ngắn nhất có thể để kiểm tra xem giá trị chứa trong một biến $vcó thể được sử dụng như một số hay không là :

number($v) = number($v)

Bạn chỉ cần thay thế $vở trên bằng biểu thức có giá trị mà bạn muốn kiểm tra.

Giải thích :

number($v) = number($v)rõ ràng là đúng, nếu $vlà một số hoặc một chuỗi biểu thị một số.

Nó cũng đúng với một giá trị boolean, vì a number(true())là 1 và number(false)là 0.

Bất cứ khi nào $vkhông thể được sử dụng như một số, thì number($v)NaN là

và NaN không bằng bất kỳ giá trị nào khác, ngay cả với chính nó.

Do đó, biểu thức trên chỉ đúng với $vgiá trị của nó có thể được sử dụng như một số và sai nếu không.


1
+1 lời giải thích hữu ích. Ai đó có thể nhận xét về các trường hợp number($v) = number($v)mang lại kết quả khác với number($v) = $v?
LarsH

@LarsH: Tôi đã bình luận về những trường hợp này. Bạn có thể chỉ ra một trường hợp chưa được bào chữa?
Dimitre Novatchev

Ý tôi là ai đó có thể liệt kê các trường hợp number($v) = number($v)mang lại kết quả khác với number($v) = $v? Không nghi ngờ gì nữa, điều đó bắt nguồn từ những gì bạn đã viết, nhưng tôi không biết bạn đã giải quyết câu hỏi này ở đâu một cách rõ ràng. Xin lỗi nếu tôi đang dày đặc. IOW, giải pháp của bạn và giải pháp của @ Oded / @ Alejandro có luôn mang lại kết quả giống nhau không?
LarsH

@LarsH: Tôi chưa xem xét giải pháp của Oded vì nó rõ ràng là thứ tôi không muốn sử dụng. Tôi nghĩ rằng giải pháp và mỏ Al2jandro của giải pháp đưa ra câu trả lời tương tự cho bất kỳ giá trị của $ v
Dimitre Novatchev

1
@EricS, Có vẻ như người ta chỉ có thể truy cập tiêu chuẩn IEEE bằng cách mua nó ... Bạn có thể xem ở đây: cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF . Cụ thể, đoạn này: "IEEE 754 gán giá trị cho tất cả các biểu thức quan hệ liên quan đến NaN. Trong cú pháp của C, vị từ x! = Y là True nhưng tất cả các giá trị khác, x <y, x <= y, x == y, x> = y và x> y, là False bất cứ khi nào x hoặc y hoặc cả hai đều là NaN"
Dimitre Novatchev

18

Có một toán tử kiểm tra kiểu tuyệt vời trong XPath 2.0 mà bạn có thể sử dụng:

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

15

Tôi không cố gắng cung cấp một giải pháp thay thế nào khác, mà là một "chế độ xem meta" cho vấn đề này.

Các câu trả lời đã được cung cấp bởi Oded và Dimitre Novatchev là đúng nhưng những gì mọi người thực sự có thể có nghĩa là với cụm từ "giá trị là một con số", tôi sẽ nói như thế nào, hãy để ý giải thích.

Theo một cách nào đó, tất cả đều đi đến câu hỏi nghe có vẻ kỳ lạ này: "bạn muốn thể hiện giá trị số của mình như thế nào?"

Hàm XPath number()xử lý các số có

  • khoảng trắng đầu hoặc cuối có thể có
  • ký tự dấu trước chỉ trên các giá trị âm
  • dấu chấm làm dấu phân cách thập phân (tùy chọn cho số nguyên)
  • tất cả các ký tự khác từ phạm vi [0-9]

Lưu ý rằng điều này không bao gồm các biểu thức cho các giá trị số

  • được thể hiện dưới dạng hàm mũ (ví dụ: 12.3E45)
  • có thể chứa ký tự dấu cho các giá trị dương
  • có sự phân biệt giữa số 0 dương và âm
  • bao gồm giá trị vô cùng dương hoặc âm

Đây không chỉ là các tiêu chí được tạo thành. Một phần tử có nội dung theo lược đồ một giá xs:floattrị hợp lệ có thể chứa bất kỳ đặc điểm nào được đề cập ở trên. Tuy nhiên, number()sẽ trả về giá trị NaN.

Vì vậy, hãy trả lời cho câu hỏi của bạn "Làm cách nào tôi có thể kiểm tra bằng XPath nếu giá trị nút là số?" là "Sử dụng các giải pháp đã được đề cập bằng cách sử dụng number()" hoặc "với một biểu thức XPath 1.0 duy nhất, bạn không thể". Hãy suy nghĩ về các định dạng số khả thi mà bạn có thể gặp phải và nếu cần, hãy viết một số loại logic để xác thực / phân tích cú pháp số. Trong quá trình xử lý XSLT, điều này có thể được thực hiện với một số mẫu bổ sung phù hợp, chẳng hạn.

Tái bút. Nếu bạn chỉ quan tâm đến các số khác 0, bài kiểm tra ngắn nhất là

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

1
+1 Giải thích chi tiết tốt về các vấn đề đằng sau câu hỏi: OP có thể có nghĩa là gì hoặc sẽ có nghĩa là gì nếu ông ấy biết những gì cần hỏi.
LarsH

9

Một điều tôi thấy rất hữu ích là:

<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

Bạn luôn có thể sử dụng một cái gì đó như sau:

string(//Sesscode) castable as xs:decimal

castable được W3C ghi lại ở đây .


1

Tôi đã đối phó với 01 - là một số.

string(number($v)) != string($v) tạo ra sự tách biệt

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.