redDevil
redDevil

Reputation: 1919

How to extract all values pointed to by an XPath?

I have the below xml

<test>
    <nodeA>
           <nodeB>key</nodeB>
           <nodeC>value1</nodeC>
    </nodeA>
    <nodeA>
           <nodeB>key</nodeB>
           <nodeC>value2</nodeC>
    </nodeA>
</test>

How to concatenate and get all the values in the xpath /test/nodeA/nodeC ? My expected output in this scenario would be value1value2

I am not sure from what I have read that it is possible with xpath, but thanks for your help.

P.S: I am using VTD-XML from Ximpleware to parse the same in Java. Any java based solution is also welcome. Currently my java solution gives only the first value, i.e. value1

Upvotes: 1

Views: 663

Answers (4)

vtd-xml-author
vtd-xml-author

Reputation: 3377

This is how I would do it with VTD-XML...

import com.ximpleware.*;


public class concat {
     public static void main(String[] s) throws VTDException{
         VTDGen vg = new VTDGen();
         if (!vg.parseFile("input.xml", false))
             return;
         VTDNav vn = vg.getNav();
         AutoPilot ap = new AutoPilot(vn);
         ap.selectXPath("/test/*/nodeC/text()");
         StringBuilder sb = new StringBuilder(100);
         int i=0;
         while((i=ap.evalXPath())!=-1){
             sb.append(vn.toString(i));
         }
         System.out.println(sb.toString());
     }

}

Upvotes: 0

lance-java
lance-java

Reputation: 27976

Here's a groovy implementation (in 2 lines of code!) using XmlSlurper

def xml = new groovy.util.XmlSlurper().parse(new File('sample.xml'))
print xml.nodeA*.nodeC.join("")

Outputs

value1value2

I don't use groovy in production code but for local mucking about it's great. I often have little groovy utilities in gradle build files.

Upvotes: 1

Martin Honnen
Martin Honnen

Reputation: 167471

If you want a single XPath expression to return the string with a concatenation of the selected values then you need XPath 2.0 (or later) respectively XQuery 1.0 (or later) where you can do string-join(/test/nodeA/nodeC, ''). XPath 1.0 does not have the expressive power to give you a string but of course, as already shown in another answer, you can iterate over the selected nodes and concatenate the selected values in a host language like Java.

Upvotes: 0

sh0rug0ru
sh0rug0ru

Reputation: 1626

XPath will return a NodeList which you can iterate and concatenate:

StringBuilder concatenated = new StringBuilder():
XPath xpath = XPathFactory.newInstance().newXPath();
String expression = "/test/nodeA/nodeC/text()";
InputSource inputSource = new InputSource("sample.xml");
NodeList nodes = (NodeList) xpath.evaluate(expression, inputSource, XPathConstants.NODESET);
for(int i = 0; i < nodes.getLength(); i++) {
    concatenated.append(nodes.item(i).getTextContent());
}

Upvotes: 5

Related Questions