Return a string value based on XPATH condition

后端 未结 2 839
被撕碎了的回忆
被撕碎了的回忆 2020-12-09 11:34

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\"



        
相关标签:
2条回答
  • 2020-12-09 11:56

    You can't; you'd have to use XQuery for this. see e.g. XQuery Conditional Expressions

    Or, if the resulting string is only used within Java, you can just process the value returned by XPath within your Java code:

    XPathFactory factory = XPathFactory.newInstance();
    XPath xpath = factory.newXPath();
    XPathExpression expr = xpath.compile("//b[@id=23]");
    boolean result = expr.evaluate(doc, XPathConstants.BOOLEAN);
    
    if (result) return "Profit";
    else return "Loss";
    
    0 讨论(0)
  • 2020-12-09 12:01

    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.

    0 讨论(0)
提交回复
热议问题