xpath multiple tag select

10,557

Solution 1

Use:

 //a/b/*[not(self::e or self::f)]
|
 //a/b/*/*[self::g or self::h]

In case you know the structure of the XML document well and it is true that the only grand-children that //a/b can have are g and/or h, then this can be simplified to:

 //a/b/*[not(self::e or self::f)]
|
 //a/b/*/*

In XPath 2.0 this can be written even simpler as:

 //a/b/(*[not(self::e or self::f)] | */*)

Solution 2

Use this xpath if you want to select all c, d, g, h nodes:

"//c|//d|//g|//h"

Use this, if you want to specify the full path from the root:

"/a/b/c|/a/b/d|/a/b/f/g|/a/b/f/h"

Or if you want all c, d, g or h, which are within b:

"//b//c|//b//d|//b//g|//b//h"

Also, in your code: use nodes.item(i).getTextContent() instead of GetNodeValue.

Solution 3

how can I select c,d,g,h (which will be child tags of b not in j) using xpath?

XPath 2.0

"/a/b//*[matches(name(),'^c$|^d$|^g$|^h$')]"

To stay with your initial location path, XPath 1.0 should be:

"/a/b//*[name()='c' 
  or name()='d' 
  or name()='g' 
  or name()='h']"

Or, following your usage of axis:

 "/a/b//*[self::c 
  or self::d 
  or self::g 
  or self::h]"

By appending to the location paths above text(), you will get the text node from each related tag.

PS: The solution given by @fiver sould be changed to /a/b/c|/a/b/d|/a/b/f/g|/a/b/f/h.

Share:
10,557
Pavithra Gunasekara
Author by

Pavithra Gunasekara

Updated on June 04, 2022

Comments

  • Pavithra Gunasekara
    Pavithra Gunasekara almost 2 years

    For the given XML how can I select c,d,g,h (which will be child tags of b not in j) using xpath?

    XML

    <a>
     <b>
      <c>select me</c>
      <d>select me</d>
      <e>do not select me</e>
      <f>
        <g>select me</g>
        <h>select me</h>
      </f>
     </b>
    
     <j>
      <c>select me</c>
      <d>select me</d>
      <e>do not select me</e>
      <f>
        <g>select me</g>
        <h>select me</h>
      </f>
     </j>
    </a>
    

    I thought of using following to grab the result but it doesn't give me g,h values

    xpath.compile("//a/b/*[self::c or self::d or self::f/text()");
    

    java code I used

    import org.w3c.dom.*;
    import javax.xml.xpath.*;
    import javax.xml.parsers.*;
    import java.io.IOException;
    import org.xml.sax.SAXException;
    
     public class XPathDemo {
    
       public static void main(String[] args) 
       throws ParserConfigurationException,SAXException,IOException,PathExpressionException {
    
       DocumentBuilderFactory domFactory = 
       DocumentBuilderFactory.newInstance();
       domFactory.setNamespaceAware(true); 
       DocumentBuilder builder = domFactory.newDocumentBuilder();
       Document doc = builder.parse("test.xml");
       XPath xpath = XPathFactory.newInstance().newXPath();
    
       XPathExpression expr = xpath.compile("//a/b/*[self::c or self::d or self::f]/text()");
    
      Object result = expr.evaluate(doc, XPathConstants.NODESET);
      NodeList nodes = (NodeList) result;
        for (int i = 0; i < nodes.getLength(); i++) {
            System.out.println(nodes.item(i).getNodeValue()); 
       }
    }
    

    }

    Can anyone help me with this?

    Thanks a lot!!!

  • Pavithra Gunasekara
    Pavithra Gunasekara almost 13 years
    Hi ,thanks for your help, I edited question I need only the tags inside b... I tried using your query but something is wrong, it doesn't give any result ...
  • Petar Ivanov
    Petar Ivanov almost 13 years
    im not java expert - what is this class that you are using - can you post a code that compiles?
  • Emiliano Poggi
    Emiliano Poggi almost 13 years
    "Note that you shouldn't include a in the xpath, because a is the root." is this assertion a java-related one? Because in XPath it's totally wrong. The root is /.
  • Petar Ivanov
    Petar Ivanov almost 13 years
    Hm, I thought so too in fact. I am not java expert, I tested this in C# and when I had /a it didn't work - so I assumed it's because it's root...
  • Emiliano Poggi
    Emiliano Poggi almost 13 years
    No, that's probably related to the object you are using in C# which starts from a. So you are inferring bad.
  • Pavithra Gunasekara
    Pavithra Gunasekara almost 13 years
    Thanks a lot for your help... I used this and solved my problem XPathExpression expr = xpath.compile("//b/c | //b/d | //b/f/g |//b/f/h/text()");
  • Pavithra Gunasekara
    Pavithra Gunasekara almost 13 years
    Thanks a lot Dimitre this way is much simpler... :)
  • Emiliano Poggi
    Emiliano Poggi almost 13 years
    Here's finally where my rep. 15 is gone :P! +1 anyway you are true.
  • Emiliano Poggi
    Emiliano Poggi almost 13 years
    @Paithra: do not worry! That's the rep ;-)