If I have the below XML, how to specify a xpath to return a string based on a condition. For example here if //b[@id=23] then "Profit" else "Loss"
<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>
Using XPath in Conditions. XPath expressions can be used as tests when creating conditions. When a document is processed the expression is evaluated and the result converted to a boolean value. If that value is true, the condition is considered to match.
If the return type is XPathConstants. NODESET , the result will in general be a Java List containing node objects in the selected object model. It may also contain non-node objects if that's what the XPath expression returned.
This XPath will give you all nodes that have attributes containing 'Foo' regardless of node name or attribute name: //attribute::*[contains(., 'Foo')]/.. Of course, if you're more interested in the contents of the attribute themselves, and not necessarily their parent node, just drop the /.. Save this answer.
Node Functions XPath node function provide the node related function like last(), position(), id(), count(). node(): function return node value. text(): function return text value of specific node. comment(): function matches comment node and return that specific comment node.
I. XPath 2.0 solution (recommended if you have access to an XPath 2.0 engine)
(: XPath 2.0 has if ... then ... else ... :)
if(//b[@id=23])
then 'Profit'
else 'Loss'
II. XPath 1.0 solution:
Use:
concat(substring('Profit', 1 div boolean(//b[@id=23])),
substring('Loss', 1 div not(//b[@id=23]))
)
Verification using XSLT 1.0:
This transformation:
<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>
when applied on the provided XML document (corrected to make it well-formed):
<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>
produces the wanted, correct result:
Profit
When we replace in the XML document:
<b id="23"/>
with:
<b id="24"/>
again the correct result is produced:
Loss
Explanation:
We use the fact that:
substring($someString, $N)
is the empty string for all $N > string-length($someString)
.
Also, the number Infinity
is the only number greater than the string-length of any string.
Finally:
number(true())
is 1
by definition,
number(false())
is 0
by definition.
Therefore:
1 div $someCondition
is 1
exactly when the $someCondition
is true()
and is Infinity
exactly when $someCondition
is false()
Thus it follows from this that if we want to produce $stringX
when $Cond
is true()
and to produce $stringY
when $Cond
is false()
, one way to express this is by:
concat(substring($stringX, 1 div $cond),
substring($stringY, 1 div not($cond)),
)
In the above expression exactly one of the two arguments of the concat()
function is non-empty.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With