I. Решение XPath 2.0 (рекомендуется, если у вас есть доступ к движку XPath 2.0)
(: XPath 2.0 has if ... then ... else ... :)
if(//b[@id=23])
then 'Profit'
else 'Loss'
II. Решение XPath 1.0 :
Использование:
concat(substring('Profit', 1 div boolean(//b[@id=23])),
substring('Loss', 1 div not(//b[@id=23]))
)
Проверка с использованием XSLT 1.0 :
Это преобразование:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:value-of select=
"concat(substring('Profit', 1 div boolean(//b[@id=23])),
substring('Loss', 1 div not(//b[@id=23]))
)"/>
</xsl:template>
</xsl:stylesheet>
при применении к предоставленному документу XML (исправлено, чтобы сделать его правильно сформированным):
<a>
<b id="23"/>
<c></c>
<d></d>
<e>
<f id="23">
<i>123</i>
<j>234</j>
</f>
<f id="24">
<i>345</i>
<j>456</j>
</f>
<f id="25">
<i>678</i>
<j>567</j>
</f>
</e>
</a>
дает желаемый, правильный результат :
Profit
При замене в XML-документе :
<b id="23"/>
с
<b id="24"/>
снова получается правильный результат :
Loss
Объяснение
Мы используем тот факт, что:
substring($someString, $N)
- пустая строка для всех $N > string-length($someString)
.
Кроме того, число Infinity
является единственным числом, превышающим длину строки любой строки .
Наконец:
number(true())
равно 1
по определению
number(false())
по определению 0
.
Таким образом:
1 div $someCondition
равно 1
точно, когда $someCondition
равно true()
и Infinity
точно, когда $someCondition
равно false()
Таким образом, из этого следует, что если мы хотим произвести $stringX
, когда $Cond
равно true()
, и произвести $stringY
, когда $Cond
равно false()
, один из способов выразить это
concat(substring($stringX, 1 div $cond),
substring($stringY, 1 div not($cond)),
)
В приведенном выше выражении ровно один из двух аргументов функции concat()
является непустым .