XPath проверяет, является ли значение узла числом

89

Как с помощью 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
Поскольку в XPath 1.0 NaNзначение числового типа данных не равно никакому числовому значению, и для сравнения, если хотя бы один аргумент представляет собой 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: Я уже комментировал эти случаи. Можете ли вы указать на еще не обсужденный случай?
Димитр Новачев
Я имел в виду, может ли кто-нибудь перечислить случаи, когда number($v) = number($v)дает другой результат number($v) = $v? Несомненно, это вытекает из того, что вы написали, но я не понимаю, где вы конкретно ответили на этот вопрос. Извините, если я веду себя глупо. IOW, всегда ли ваше решение и решение @Oded / @ Alejandro дают одинаковые результаты?
LarsH
@LarsH: Я не смотрел на решение Одеда, потому что, очевидно, мне не хотелось бы его использовать. Я думаю, что решение Al2jandro и мое решение дают одинаковые ответы для любого значения $ v
Димитр Новачев
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, ложны, если x, y или оба равны NaN »
Димитр Новачев 06
18

В XPath 2.0 есть замечательный оператор проверки типов, который вы можете использовать:

<xsl:if test="$number castable as xs:double">
    <!-- implementation -->
</xsl:if>
шапий
источник
15

Я не пытаюсь предложить еще одно альтернативное решение, а пытаюсь предложить "мета-взгляд" на эту проблему.

Ответы, уже предоставленные Одедом и Димитром Новачевыми, верны, но то, что люди действительно могут иметь в виду под фразой «значение - это число», как я бы сказал, открыто для интерпретации.

В некотором смысле все сводится к этому странно звучащему вопросу: «как вы хотите выразить свои числовые значения?»

Функция XPath number()обрабатывает числа,

  • возможные начальные или конечные пробелы
  • предшествующий знак знака только для отрицательных значений
  • точка как десятичный разделитель (необязательно для целых чисел)
  • все остальные символы из диапазона [0-9]

Обратите внимание, что это не включает выражения для числовых значений, которые

  • выражаются в экспоненциальной форме (например, 12.3E45)
  • может содержать знаковый символ для положительных значений
  • есть различие между положительным и отрицательным нулем
  • включить значение для положительной или отрицательной бесконечности

Это не просто выдуманные критерии. Элемент с содержимым, которое согласно схеме является допустимым xs:floatзначением, может содержать любую из вышеупомянутых характеристик. Пока number()не вернул бы значение NaN.

Итак, ответьте на ваш вопрос: «Как я могу проверить с помощью XPath, является ли значение узла числом?» это либо «Использовать уже упомянутые решения с помощью number()», либо «с одним выражением XPath 1.0 нельзя». Подумайте о возможных форматах чисел, с которыми вы можете столкнуться, и, если необходимо, напишите какую-нибудь логику для проверки / анализа чисел. В рамках обработки XSLT это можно сделать, например, с помощью нескольких подходящих дополнительных шаблонов.

PS. Если вас интересуют только ненулевые числа, самый короткий тест -

<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>
jkpd
источник
2

Вы всегда можете использовать что-то вроде этого:

string(//Sesscode) castable as xs:decimal

castable задокументирован W3C здесь .

Martti
источник
1

Я имел дело с 01 - числовым.

string(number($v)) != string($v) делает сегрегацию

Флоримонд
источник