Search code examples
javaxmlxpathjaxp

Retrieve value of XML node and node attribute using XPath in JAXP


Given an xml document that looks like the following:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <entry key="agentType">STANDARD</entry>
    <entry key="DestinationTransferStates"></entry>
    <entry key="AgentStatusPublishRate">300</entry>
    <entry key="agentVersion">f000-703-GM2-20101109-1550</entry>
    <entry key="CommandTimeUTC">2010-12-24T02:25:43Z</entry>
    <entry key="PublishTimeUTC">2010-12-24T02:26:09Z</entry>
    <entry key="queueManager">AGENTQMGR</entry>
</properties>

I want to print the values of the "key" attribute and the element so it looks like this:

agentType = STANDARD
DestinationTransferStates = 
AgentStatusPublishRate = 300
agentVersion = f000-703-GM2-20101109-1550
CommandTimeUTC = 2010-12-24T02:25:43Z
PublishTimeUTC = 2010-12-24T02:26:09Z
queueManager = AGENTQMGR

I'm able to print the node values with no problem using this code:

XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr = xpath.compile("//properties/entry/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()); 
}

And I can print the values of the "key" attribute by changing the xpath expression and the node methods as follows:

XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr = xpath.compile("//properties/entry");
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).getAttributes().getNamedItem("key").getNodeValue()); 
}

It seems like there would be a way to get at both of these values in a single evaluate. I could always evaluate two NodeLists and iterate through them with a common index but I'm not sure they are guaranteed to be returned in the same order. Any suggestions appreciated.


Solution

  • What about getTextContent()? This should do the work.

    Object result = expr.evaluate(doc, XPathConstants.NODESET);
    NodeList nodes = (NodeList) result;
    for (int i = 0; i < nodes.getLength(); i++)
    {
        Node currentItem = nodes.item(i);
        String key = currentItem.getAttributes().getNamedItem("key").getNodeValue();
        String value = currentItem.getTextContent();
    
        System.out.printf("%1s = %2s\n", key, value);
    }
    

    For further informations please see the javadoc for getTextContent(). I hope this will help you.