xpath multiple tag select
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
.
Pavithra Gunasekara
Updated on June 04, 2022Comments
-
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 almost 13 yearsHi ,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 almost 13 yearsim not java expert - what is this class that you are using - can you post a code that compiles?
-
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 almost 13 yearsHm, 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 almost 13 yearsNo, that's probably related to the object you are using in C# which starts from a. So you are inferring bad.
-
Pavithra Gunasekara almost 13 yearsThanks 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 almost 13 yearsThanks a lot Dimitre this way is much simpler... :)
-
Emiliano Poggi almost 13 yearsHere's finally where my rep. 15 is gone :P! +1 anyway you are true.
-
Emiliano Poggi almost 13 years@Paithra: do not worry! That's the rep ;-)