How to get the value of each node's first child in NodeList?

th30d0rab1e picture th30d0rab1e · Feb 16, 2016 · Viewed 8k times · Source

Id like to get the element name and value of the first child of each element. But I'm getting null values. Im pretty new to XML and I am stumped, just trying to get something working with pretty font. Theres about 15 children to the root, and theyre all called "DEvent", I would like my output to be:

Event: Wednesday Trail Walks

Event: BOW - Dog Mushing!

etc.

    <DNREvents>
<DEvent>
<event eid="1">Wednesday Trail Walks</event>
<date>2/03/2016</date>
<time>1-2:30 PM</time>
<description>...</description>
<location>Brown's Creek State Trail</location>
<cost>Free</cost>
<infoPhone>651-231-6968</infoPhone>
<infoEmail>[email protected]</infoEmail>
</DEvent>
<DEvent>
<event eid="2">BOW - Dog Mushing!</event>
<date>2/04/2016 thru 2/07/2016</date>
<time>Unknown</time>
<description>
This off the grid adventure is for those who want to actively participate in every aspect of learning to run your own small team of sled dogs through miles and miles of beautiful trails in the remote wilderness of northern Minnesota. Limited to 4 participants
</description>
<location>Grand Marais/Hovland</location>
<cost>$895</cost>
<infoPhone>218-370-0283</infoPhone>
<infoEmail>linda@points_unknown.com</infoEmail>
</DEvent>
<DEvent>...</DEvent>
<DEvent>...</DEvent>
<DEvent>...</DEvent>
<DEvent>...</DEvent>
<DEvent>...</DEvent>
<DEvent>...</DEvent>
<DEvent>...</DEvent>
<DEvent>...</DEvent>
<DEvent>...</DEvent>
<DEvent>...</DEvent>
<DEvent>...</DEvent>
<DEvent>...</DEvent>
<DEvent>...</DEvent>
</DNREvents>

My java to show the results-

Element DNR = root;
        NodeList EventList=DNR.getElementsByTagName("DEvent");
        for (int i=0; i< EventList.getLength();i++)
        {
            Node thisNode = EventList.item(i);
            Node child = thisNode.getFirstChild();
            String x = child.getNodeValue();
            System.out.println(thisNode+ x);
        }

Answer

pczeus picture pczeus · Feb 16, 2016

Here is a working example. The firstChild in your code was a #Text node and you needed to get the nextSibling() of that node (So your event node is not the first node after all):

    import org.w3c.dom.*;
    import java.io.*;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.DocumentBuilder;

    File xmlFile = new File("/data/test/test.xml");
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document doc = dBuilder.parse(xmlFile);

    NodeList eventList = doc.getElementsByTagName("DEvent");
    for (int i=0; i< eventList.getLength(); i++) {
        Node thisNode = eventList.item(i);

        if(thisNode.hasChildNodes()){
            NodeList event = thisNode.getChildNodes().getFirstChild().getNextSibling();
            String eid = event.getAttributes().getNamedItem("eid");
            String value = event.getFirstChild().getNodeValue();
            System.out.println("EID: " + eid + " Value: " + value + "\n");
        }
    }

Be aware that this line will be fragile if you don't do additional null checking to verify the xml is well formed with the proper child nodes. And, this doesn't enforce the order of the child nodes in the xml is in the order you expect:

NodeList child = thisNode.getChildNodes().getFirstChild().getNextSibling();

With that said, I think a better implementation would be to use XPath, which allows you to select the nodes you want without traversing manually down the tree and is more compact and 'fail safe':

    XPath xpath = XPathFactory.newInstance().newXPath();
    String expression = "/DNREvents/DEvent/event";
    InputSource inputSource = new InputSource(new BufferedReader(new FileReader("/data/test/test.xml")));
    NodeList eventList = (NodeList) xpath.evaluate(expression, inputSource, XPathConstants.NODESET);

    for (int i=0; i< eventList.getLength(); i++) {
        Node eventNode = eventList.item(i);

        String eid = xpath.evaluate("@eid", eventNode);
        String value = xpath.evaluate("./text()", eventNode);
        System.out.println("EID: " + eid + ", Value: " + value + "\n");
    }