XPath - retrieve multiple values from different paths based on same condition

13,946

Solution 1

This would be the correct path:

/root/entry[value[@name = 'ID'] = 11]/value[@name = 'NAME']

To retrieve a list of nodes, you need to use the version of xPath.evaluate() that takes a returnType parameter:

InputSource document = new InputSource(new FileInputStream("user1.xml"));
String xpath = "/root/entry[value[@name = 'ID'] = 11]/value[@name = 'NAME']";
NodeSet result = (NodeSet)xPath.evaluate(xpath, document, XPathConstants.NODESET); 
for(int index = 0; index < result.getLength(); index ++) {      
    Node node = result.item(index);
    String name = node.getNodeValue();
}

Solution 2

/root/entry[value[@name="ID" and .=11]]/value[@name="NAME"]

or

/root/entry/value[@name="ID" and .=11]/../value[@name="NAME"]

or

/descendant::entry[value=11 and value/@name="ID"]/value[@name="NAME"]

or

//value[.=11]/@name[.="ID"]/ancestor::entry/value[@name="NAME"]

or many other variations

Solution 3

Use:

/*/*[*[@name='ID'] = 11]/*[@name='NAME']

XSLT - based verification:

<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:copy-of select="/*/*[*[@name='ID'] = 11]/*[@name='NAME']"/>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the provided XML document:

<root>
    <entry id="1">
        <value name="ID">11</value>
        <value name="ENABLE">0</value>
        <value name="NAME">USER1</value>
    </entry>
    <entry id="2">
        <value name="ID">11</value>
        <value name="ENABLE">0</value>
        <value name="NAME">USER2</value>
    </entry>
    <entry id="3">
        <value name="ID">12</value>
        <value name="ENABLE">0</value>
        <value name="NAME">USER1</value>
    </entry>
</root>

the XPath expression is evaluated and the result of this evaluation (all selected nodes) is copied to the output:

<value name="NAME">USER1</value>
<value name="NAME">USER2</value>
Share:
13,946
Abi
Author by

Abi

SOreadytohelp

Updated on June 05, 2022

Comments

  • Abi
    Abi almost 2 years

    This is my XML

    <root>
       <entry id="1">
          <value name="ID">11</value>
          <value name="ENABLE">0</value>
          <value name="NAME">USER1</value>
       </entry>
       <entry id="2">
          <value name="ID">11</value>
          <value name="ENABLE">0</value>
          <value name="NAME">USER2</value>
       </entry>
       <entry id="3">
          <value name="ID">12</value>
          <value name="ENABLE">0</value>
          <value name="NAME">USER1</value>
       </entry>
    </root>
    

    I need an XPath query to retrieve all the names whose id is 11.

    I tried:

    String xpath = "/root/entry/value[@name=ID/text()='11']/value[@name='NAME']";
    String xpath = "/root/entry/value[@name=ID/text()='11']/NAME";
    

    Can someone tell me what is wrong in my query?

    EDIT:

    Expected Output:

    USER1
    USER2
    

    both these have ID = 11

  • Abi
    Abi over 11 years
    Nope,I am getting 11 as the output
  • jeewiya
    jeewiya over 11 years
    i have missing NAME part,check it now
  • Abi
    Abi over 11 years
    i am getting only one user value returned
  • Abi
    Abi over 11 years
    first option - infinite loop. second option - returns only one user USER1
  • Abi
    Abi over 11 years
    fourth option also returns only one value
  • JLRishe
    JLRishe over 11 years
    @Abi Sorry, I had an extra slash. Please try it now.
  • Abi
    Abi over 11 years
    Thanks, this is working but is XSL the only way to go about it? Cannot be done using normal XPath?Because when I tried using that Xpath in my class it returned only user1
  • JLRishe
    JLRishe over 11 years
    @Abi Both Dimitre's example and mine should find USER1 and USER2. If you're only getting one value, it's the way you're applying the XPath that's wrong. Please show us your actual code.
  • Abi
    Abi over 11 years
    @JLRishe - yes that may be the mistake, code is String xpath = "/root/entry[value[@name = 'ID'] = 11]/value[@name = 'NAME']"; String result = xPath.evaluate(xpath, new InputSource(new FileInputStream("user1.xml")));
  • Dimitre Novatchev
    Dimitre Novatchev over 11 years
    @abi, the result from evaluate() most probably is Object -- and needs to be cast to a list of nodes. Your mistake is that you are assigning it to a String. I don't know what XPath API you are using (the PL seems to be Java) -- please, read well the documentation and review any available code examples, so that you can correct your current code.
  • Abi
    Abi over 11 years
    MYBAD!!! didnt realize i had messed up in the reading the result part. Thanks alot for all your answers