Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get element's value from XML using SAX parser in startElement?

Is it possible to get the content of an element from a XML file in startElement function that is the override function of the SAX handler?

Below is the specification.

1) XML file

<employees>
   <employee id="111">
      <firstName>Rakesh</firstName>
      <lastName>Mishra</lastName>
      <location>Bangalore</location>
   </employee>
   <employee id="112">
      <firstName>John</firstName>
      <lastName>Davis</lastName>
      <location>Chennai</location>
   </employee>
   <employee id="113">
      <firstName>Rajesh</firstName>
      <lastName>Sharma</lastName>
      <location>Pune</location>
   </employee>
</employees>

2) startElement function

@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
    .......code in here..........
}

3) Expected result

element name   : employee
attribute name : id
attribute value: 111
firstName      : Rakesh
lastName       : Mishra
location       : Bangalore

element name   : employee
attribute name : id
attribute value: 112
firstName      : John
lastName       : Davis
location       : Chennai

element name   : employee
attribute name : id
attribute value: 113
firstName      : Rajesh
lastName       : Sharma
location       : Pune
like image 559
sakura Avatar asked Jun 09 '14 04:06

sakura


1 Answers

You can get the element's name in startElement and endElement. You can also get attributes in startElement. Values you should get in characters.

Here is a very basic example on how to get the value of an element using a ContentHandler:

public class YourHandler extends DefaultHandler {

    boolean inFirstNameElement = false;

    public class startElement(....) {
        if(qName.equals("firstName") {
            inFirstNameElement = true;
        }
    }

    public class endElement(....) {
        if(qName.equals("firstName") {
            inFirstNameElement = false;
        }
    }

    public class characters(....) {
        if(inFirstNameElement) {
            // do something with the characters in the <firstName> element
        }
    }
}

If you have a simple example, setting boolean flags for each tag is OK. If you have a more complex scenario, you might prefer store the flags in a map using element names as keys, or even create one or more Employee classes mapped to your XML, instantiate them every time <employee> is found in startElement, populate its properties, and add it to a Collection in endElement.

Here is a complete ContentHandler example that works with your example file. I hope it helps you get started:

public class SimpleHandler extends DefaultHandler {

    class Employee {
        public String firstName;
        public String lastName;
        public String location;
        public Map<String, String> attributes = new HashMap<>();
    }
    boolean isFirstName, isLastName, isLocation;
    Employee currentEmployee;
    List<Employee> employees = new ArrayList<>();

    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes atts) throws SAXException {
        if(qName.equals("employee")) {
            currentEmployee = new Employee();
            for(int i = 0; i < atts.getLength(); i++) {
                currentEmployee.attributes.put(atts.getQName(i),atts.getValue(i));
            }
        }
        if(qName.equals("firstName")) { isFirstName = true; }
        if(qName.equals("lastName"))  { isLastName = true;  }
        if(qName.equals("location"))  { isLocation = true;  }
    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        if(qName.equals("employee")) {
            employees.add(currentEmployee);
            currentEmployee = null;
        }
        if(qName.equals("firstName")) { isFirstName = false; }
        if(qName.equals("lastName"))  { isLastName = false;  }
        if(qName.equals("location"))  { isLocation = false;  }
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        if (isFirstName) {
            currentEmployee.firstName = new String(ch, start, length);
        }
        if (isLastName) {
            currentEmployee.lastName = new String(ch, start, length);
        }
        if (isLocation) {
            currentEmployee.location = new String(ch, start, length);
        }
    }

    @Override
    public void endDocument() throws SAXException {
        for(Employee e: employees) {
            System.out.println("Employee ID: " + e.attributes.get("id"));
            System.out.println("  First Name: " + e.firstName);
            System.out.println("  Last Name: " + e.lastName);
            System.out.println("  Location: " + e.location);
        }
    }
}
like image 137
helderdarocha Avatar answered Nov 16 '22 04:11

helderdarocha