Kennard
Kennard

Reputation: 875

Parse xml with Java(get optional childnode value)

I need to parse an xml file called students, every student has rollno, firstname, lastname as attributes, but not all student has a club. The xml file looks like this:

<?xml version="1.0"?>
<class>
   <student rollno="393" firstname="Dinkar" lastname="Kad">
    <club name="Asian-Caucus" />
   </student>
   <student rollno="493" firstname="Vaneet" lastname="Gupta"/>
   <student rollno="593" firstname="jasvir" lastname="jazz">
      <club name="Students-for-Corporate-Citizenship"/>
   </student>
   <student rollno="693" firstname="Joseph" lastname="Patterson"/>
</class>

I would like to retrieve information about each student, get their rollno, first name, lastname and club name if exist. My code can get information about required attributes, but club name is always empty(even when there should be a club associated with this student): My code is like following:

    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;

    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;

    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.NamedNodeMap;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;


    public class TestParser {


        public void parseXML() throws Exception{
              DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
              DocumentBuilder docBuilder = factory.newDocumentBuilder();
              File file = new File("c:\\My Documents\\students.xml");
              Document doc = docBuilder.parse(file);




              NodeList list = doc.getElementsByTagName("student");
              for(int i=0; i<list.getLength(); i++){

                  int rollno = 0;
                  String firstname = "";
                  String lastname = "";
                  String clubname  = "";

                  Element cur = (Element)list.item(i);

                  NamedNodeMap curAttr = cur.getAttributes();


                  for(int j=0; j<curAttr.getLength(); j++){
                      Node attr = curAttr.item(j);
                      if(attr.getNodeName().equals("rollno"))
                          rollno = Integer.parseInt(attr.getNodeValue());
                      if(attr.getNodeName().equals("firstname")) 
                          firstname = attr.getNodeValue();
                      if(attr.getNodeName().equals("lastname")) 
                          lastname = attr.getNodeValue();
                      if(attr.getNodeName().equals("club name")) 
                          clubname = attr.getNodeValue();

                  } // end for each attribute
                  System.out.print("rollno: " + rollno);
                  System.out.print(" firstname: " + firstname);
                  System.out.print(" lastname: " + lastname);
                  System.out.println(" club name: " + clubname);



              }// end for each element


        }     


        public static void main(String[] args) throws Exception {
            // TODO Auto-generated method stub
            TestParser tp = new TestParser();
            tp.parseXML();

        }

    }



Output looks like this:

    rollno: 393 firstname: Dinkar lastname: Kad club name: 
    rollno: 493 firstname: Vaneet lastname: Gupta club name: 
    rollno: 593 firstname: jasvir lastname: jazz club name: 
    rollno: 693 firstname: Joseph lastname: Patterson club name: 

Any idea to fix this problem, so that student has a club can print out the correct club name? I'm very new to xml parsing, any suggestion is appreciated. Thanks a lot!

Update: Revised the code according to answer by @tanjir, now the program can get childnode club's value smoothly:)

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


public class TestParser {


    public void parseXML() throws Exception{
          DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
          DocumentBuilder docBuilder = factory.newDocumentBuilder();
          File file = new File("c:\\My Documents\\students.xml");
          Document doc = docBuilder.parse(file);




          NodeList list = doc.getElementsByTagName("student");
          for(int i=0; i<list.getLength(); i++){

              int rollno = 0;
              String firstname = "";
              String lastname = "";
              String clubname  = "";

              Element cur = (Element)list.item(i);

              NamedNodeMap curAttr = cur.getAttributes();


              for(int j=0; j<curAttr.getLength(); j++){
                  Node attr = curAttr.item(j);
                  if(attr.getNodeName().equals("rollno"))
                      rollno = Integer.parseInt(attr.getNodeValue());
                  if(attr.getNodeName().equals("firstname")) 
                      firstname = attr.getNodeValue();
                  if(attr.getNodeName().equals("lastname")) 
                      lastname = attr.getNodeValue();
                  if(attr.getNodeName().equals("name")) 
                      clubname = attr.getNodeValue();

              } // end for each attribute


              //check if there is any optional childnode
              if(cur.hasChildNodes()) {
                  NodeList stChildNodes = cur.getChildNodes();
                  // Loop through all the nodes and find the club node only
                  for(int c=0; c<stChildNodes.getLength(); c++) {
                      Node child = stChildNodes.item(c);
                      if(child.getNodeName().equals("club")) {
                        //"club" node detected. now loop through the attributes
                          NamedNodeMap curChildAttr = child.getAttributes();
                          for(int j=0; j<curChildAttr.getLength(); j++){
                              Node attr = curChildAttr.item(j);
                              if(attr.getNodeName().equals("name")) {
                                  clubname = attr.getNodeValue();
                            }
                        }
                      }
                  }
              }// end if hasChildNodes



              System.out.print("rollno: " + rollno);
              System.out.print(" firstname: " + firstname);
              System.out.print(" lastname: " + lastname);
              System.out.println(" club name: " + clubname);



          }// end for each element


    }     


    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        TestParser tp = new TestParser();
        tp.parseXML();

    }

}

Upvotes: 1

Views: 1169

Answers (1)

tanjir
tanjir

Reputation: 1334

You need to get the club node and then loop through it's attribute- similar to the way you already did..

       //check if there is any optional childnode
          if(cur.hasChildNodes()) {
            NodeList stChildNodes = cur.getChildNodes();
             // Loop through all the nodes and find the club node only
            for(Node child : stChildNodes) {
              if(child.getNodeName().equals("club") {
                  //"club" node detected. now loop through the attributes like the way you already did for students
                  NamedNodeMap clubAttr = child.getAttributes();
                  for(int j=0; j<clubAttr.getLength(); j++){
                    Node clattr = clubAttr.item(j);
                    if(clattr.getNodeName().equals("name")) {
                      clubname = clattr.getNodeValue();
                    }
                  }
                  break; // probably we are not interested in other nodes
               }
             }
          }

Upvotes: 2

Related Questions