How do I get attributes of element during SAX parsing?

This example show you how to get the attributes of elements in an XML file using the SAX parser.

package org.kodejava.xml;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.InputStream;

public class SAXElementAttribute {
    public static void main(String[] args) {
        SAXElementAttribute demo = new SAXElementAttribute();
        demo.run();
    }

    private void run() {
        try {
            // Create SAXParserFactory instance and a SAXParser
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();

            // Get an InputStream to the elements.xml file and parse
            // its contents using the SAXHandler.
            InputStream is =
                    getClass().getResourceAsStream("/elements.xml");
            DefaultHandler handler = new SAXHandler();
            parser.parse(is, handler);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static class SAXHandler extends DefaultHandler {
        @Override
        public void startElement(String uri, String localName,
                                 String qName, Attributes attributes)
                throws SAXException {

            int attributeLength = attributes.getLength();
            if ("person".equals(qName)) {
                for (int i = 0; i < attributeLength; i++) {
                    // Get attribute names and values
                    String attrName = attributes.getQName(i);
                    String attrVal = attributes.getValue(i);
                    System.out.print(attrName + " = " + attrVal + "; ");
                }
                System.out.println();
            }
        }
    }
}

The elements.xml file is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <persons>
        <person name="Foo" age="25" />
        <person name="Bar" age="22" />
    </persons>
</root>

How do I handle error when parsing an XML file using SAX?

The ErrorHandler interface implemented by the org.xml.sax.helpers.DefaultHandler class provides some methods for error handling mechanism in SAX parsing. The methods are warning(), error(), and fatalError().

package org.kodejava.xml;

import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.InputStream;

public class SAXErrorHandlerDemo {
    public static void main(String[] args) throws Exception {
        SAXErrorHandlerDemo demo = new SAXErrorHandlerDemo();
        demo.run();
    }

    public void run() throws Exception {
        // Creates the SAXParserFactory and SAXParser instance.
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();

        // Parse the error.xml file using MySAXHandler as the 
        // DefaultHandler implementation.
        InputStream is = getClass().getResourceAsStream("/error.xml");
        DefaultHandler handler = new MySAXHandler();
        parser.parse(is, handler);
    }

    // Override the error handling methods defined by the ErrorHandler
    // interface. This method will handler exceptions thrown by the
    // parsing process.
    static class MySAXHandler extends DefaultHandler {
        @Override
        public void warning(SAXParseException e) throws SAXException {
            System.out.println("warning   : " + e.getMessage());
        }

        @Override
        public void error(SAXParseException e) throws SAXException {
            System.out.println("error     : " + e.getMessage());
        }

        @Override
        public void fatalError(SAXParseException e) throws SAXException {
            System.out.println("fatalError: " + e.getMessage());
        }
    }
}

How do I build object from XML file using SAX?

This example will show you how to parse an XML file using SAX parser and build an object graph from the parsed XML. We will read the records.xml file that contains some recording information and create the Record object from it.

The DefaultHandler in this example created as an anonymous class. We override some method related to the ContentHandler interface such as the startElement, endElement and characters methods.

package org.kodejava.xml;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import org.kodejava.xml.support.Record;

public class SAXDataDemo {
    // List of our records.
    private final List<Record> records = new ArrayList<>();

    // Stacks for storing the elements and objects.
    private final Stack<String> elements = new Stack<>();
    private final Stack<Record> objects = new Stack<>();

    public static void main(String[] args) {
        SAXDataDemo demo = new SAXDataDemo();
        demo.run();
    }

    private void run() {
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();

            String filename = "/records.xml";
            InputStream is = getClass().getResourceAsStream(filename);

            parser.parse(is, new DefaultHandler() {
                @Override
                public void startElement(String uri, String localName, String qName,
                                         Attributes attributes) throws SAXException {
                    elements.push(qName);
                    if ("record".equals(qName)) {
                        Record record = new Record();
                        objects.push(record);
                        records.add(record);
                    }
                }

                @Override
                public void endElement(String uri, String localName,
                                       String qName) throws SAXException {
                    elements.pop();
                }

                @Override
                public void characters(char[] ch, int start, int length)
                        throws SAXException {

                    String value = new String(ch, start, length);
                    if (value.length() == 0) {
                        return;
                    }

                    if ("title".equals(currentElement())) {
                        Record record = objects.peek();
                        record.setTitle(value);
                    } else if ("artist".equals(currentElement())) {
                        Record record = objects.peek();
                        record.setArtist(value);
                    } else if ("genre".equals(currentElement())) {
                        Record record = objects.peek();
                        record.setGenre(value);
                    } else if ("year".equals(currentElement())) {
                        Record record = objects.peek();
                        record.setYear(Integer.parseInt(value));
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }

        for (Record record : records) {
            System.out.println("record = " + record);
        }
    }

    private String currentElement() {
        return elements.peek();
    }
}

The Record class.

package org.kodejava.xml.support;

public class Record {
    private String title;
    private String artist;
    private String genre;
    private int year;

    public Record() {
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    public void setGenre(String genre) {
        this.genre = genre;
    }

    public void setYear(int year) {
        this.year = year;
    }

    @Override
    public String toString() {
        return "Record{" +
                "title='" + title + "'\n" +
                ", artist='" + artist + "'\n" +
                ", genre='" + genre + "'\n" +
                ", year=" + year +
                '}';
    }
}

The following XML is the content of our records.xml file.

<?xml version="1.0"?>
<root>
    <records>
        <record>
            <title>Brand New Eyes</title>
            <artist>Paramore</artist>
            <genre>Punk Rock</genre>
            <year>2011</year>
        </record>
        <record>
            <title>Rock Beatles</title>
            <artist>Various Artist</artist>
            <genre>Rock</genre>
            <year>2010</year>
        </record>
    </records>
</root>

When we run this example will get the following output:

record = Record{title='Brand New Eyes'
, artist='Paramore'
, genre='Punk Rock'
, year=2011}
record = Record{title='Rock Beatles'
, artist='Various Artist'
, genre='Rock'
, year=2010}

How do I parse an XML file using SAX?

This example show you how to read / parse an xml file using the SAX (Simple API for XML) parser. In the main class (SAXDemo) we create the instance of SAXParserFactory and the SAXParser. The SAXParser.parse() method will parse the given InputStream and handle the xml document using the SAXHandler class that we created.

package org.kodejava.xml;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.InputStream;

public class SAXDemo {
    public static void main(String[] args) throws Exception {
        // Creates a new instance of SAXParserFactory that in turn
        // creates a SAXParser.
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();

        // The handler that will listen to the SAX event during
        // the xml traversal.
        SAXHandler handler = new SAXHandler();
        InputStream data = SAXDemo.class.getResourceAsStream("/person.xml");
        parser.parse(data, handler);
    }
}

The SAXHandler class extended from the org.xml.sax.helpers.DefaultHandler class. The handler will listen to the event triggered by the SAXParser. This handler methods is defined by the interfaces such as the ContentHandler, ErrorHandler, DTDHandler, and EntityResolver.

For example to read the content of the XML file there are methods to listen to events such as startDocument, endDocument, startElement, endElement, etc, which defined by the ContentHandler interface.

package org.kodejava.xml;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SAXHandler extends DefaultHandler {
    @Override
    public void startDocument() throws SAXException {
        System.out.println("startDocument");
    }

    @Override
    public void endDocument() throws SAXException {
        System.out.println("endDocument");
    }

    @Override
    public void startElement(String uri, String localName,
                             String qName, Attributes attributes)
            throws SAXException {
        System.out.println("startElement: " + qName);
    }

    @Override
    public void endElement(String uri, String localName,
                           String qName) throws SAXException {
        System.out.println("endElement");
    }

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        System.out.println("characters  : " + new String(ch, start, length));
    }
}

Here an example of the xml file will be read by our program:

<root>
    <persons>
        <person>
            <name>Foo</name>
        </person>
        <person>
            <name>Bar</name>
        </person>
    </persons>
</root>

Our program will print the following output:

startDocument
startElement: root
characters  : 

startElement: persons
characters  : 

startElement: person
characters  : 

startElement: name
characters  : Foo
endElement
characters  : 

endElement
characters  : 

startElement: person
characters  : 

startElement: name
characters  : Bar
endElement
characters  : 

endElement
characters  : 

endElement
characters  : 

endElement
endDocument