Ответ 1
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()
не является пустым.