Question

I would like to get the siblings of an XML element in Java.

The xml file is as follows:

  <parent>
    <child1> value 1 </child1>
    <child2> value 2 </child2>
    <child3> value 3 </child3>
  </parent>

My code in JAVA with DOM parser is as follows:

 package dom_stack;

 import java.io.File;
 import java.io.IOException;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import org.w3c.dom.Document;
 import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;


 public class DOM_stack {


     public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {


      File file = new File("root.xml");
      if (file.exists()){
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

            Document doc;
             doc = dbf.newDocumentBuilder().parse("root.xml");


            NodeList elemNodeList = doc.getElementsByTagName("child1");                 

            for(int j=0; j<elemNodeList.getLength(); j++) {

                System.out.println("The node's value that you are looking now is : " +  elemNodeList.item(j).getTextContent());
                System.out.println(" Get the Name of the Next Sibling " + elemNodeList.item(j).getNextSibling().getNodeName());
                System.out.println(" Get the Value of the Next Sibling " + elemNodeList.item(j).getNextSibling().getNodeValue());

            }


        }//if file exists
     }
    }

Unfortunately the result is:

    run:
    The node's value that you are looking now is :  value 1 
     Get the Name of the Next Sibling #text
     Get the Value of the Next Sibling 

and it should be:

    run:
    The node's value that you are looking now is :  value 1 
     Get the Name of the Next Sibling child2
     Get the Value of the Next Sibling value2

So, how can i get the desirable output?

thanks, in advance

Was it helpful?

Solution

<parent>
  <child1> value 1 </child1>
  <child2> value 2 </child2>
  <child3> value 3 </child3>
</parent>

What you are getting is the whitespace text node between the child1 and child2 elements.

You need to keep walking the siblings to skip over whitespace, comments, etc, to get the next element node:

Node child1 = elemNodeList.item(j);
Node sibling = child1.getNextSibling();
while (!(sibling instanceof Element) && sibling != null) {
  sibling = sibling.getNextSibling();
}
System.out
      .println(" Get the Name of the Next Sibling " + sibling.getNodeName());
System.out
      .println(" Get the Value of the Next Sibling " + sibling.geTextContent());

OTHER TIPS

Or, you can do it easily with XPath:

    XPath xp = XPathFactory.newInstance().newXPath();

    // Select the first child of the root element
    Element c1 = (Element) xp.evaluate("/parent/*[1]", doc,
            XPathConstants.NODE);

    // Select the siblings of the first child
    NodeList siblings = (NodeList) xp.evaluate("following-sibling::*", c1,
            XPathConstants.NODESET);
    for (int i = 0; i < siblings.getLength(); ++i) {
        System.out.println(siblings.item(i));
    }

When you call this line:

NodeList elemNodeList = doc.getElementsByTagName("child1");

You are gathering a list of all the elements that have the name "child1". You are expecting elements with the names "child2" and "child3" to be in there also.

What you can do instead is get the root Element (which is "parent") through doc.getDocumentElement(). Then, you can get a NodeList of that document's child nodes by calling rootElement.getChildNodes() and then loop through that list.

Since @McDowell 's solution haven't worked for me I changed it a bit and got it working so the Node sibling will be the "next" xml tag (e,g, if the Node current is <child1>, the Node sibling will be <child2>):

Node sibling = current.getNextSibling();
while (null != sibling && sibling.getNodeType() != Node.ELEMENT_NODE) {
    sibling = sibling.getNextSibling();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top