Тест 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

60

Найкоротший можливий спосіб перевірити, чи значення, яке міститься у змінній, $vможе використовуватися як число :

number($v) = number($v)

Вам потрібно лише замінити $vнаведене вище виразом, значення якого ви хочете перевірити.

Пояснення :

number($v) = number($v)очевидно істинно, якщо $vце число або рядок, що представляє число.

Це справедливо і для булевого значення, оскільки a number(true())дорівнює 1 і number(false)дорівнює 0.

Всякий раз, коли $vне може бути використаний як число, number($v)це NaN

а NaN не дорівнює будь-якому іншому значенню, навіть самому собі.

Таким чином, наведений вище вираз є істинним лише для $vзначення, яке може використовуватися як число, а в іншому випадку - false.


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: Я не дивився на рішення Одеда, оскільки це, очевидно, те, що я не хотів би використовувати. Я думаю, що рішення Al2jandro і моє рішення дають однакові відповіді для будь-якого значення $ v
Димитр Новатчев,

1
@EricS, здається, отримати доступ до стандарту IEEE можна лише придбавши його ... Byt таки подивись тут: 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 "
Димитр Новатчев

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 Хороше детальне пояснення питань, що стоять за цим запитанням: що міг би означати або міг би означати ОП, якби він знав, що запитати.
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

кастування задокументоване W3C тут .


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.