Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return a string value based on XPATH condition

Tags:

xpath

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>
like image 323
Sivaraman L Avatar asked Aug 12 '11 19:08

Sivaraman L


People also ask

Can conditions be evaluated using XPath?

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.

What is the return type of XPath?

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.

How use attribute for contain in XPath?

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.

What are valid XPath functions?

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.


1 Answers

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.

like image 105
Dimitre Novatchev Avatar answered Sep 23 '22 03:09

Dimitre Novatchev