A Program That Uses a SAX Parser

This section walks through a code example of a SAX parser. Because we have already covered much of the background, it will seem shorter than the DOM example. Don't be fooled. The general skeleton of the code is as follows.

// import statements: see below

public class MySAXEcho extends DefaultSAXHandler {

    main(String[] args) {
      // get a Parser
      // register my callbacks, and parse the file
    }

    // my routines that get called back
    public void startDocument() { /*code...*/}
    public void startElement( /*code...*/
    public void characters ( /*code...*/
    public void endElement(
  /*code...*/
}

The first part of the program, the import statements, looks like this:

import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;

That shows the JAXP and I/O packages our program will use. The next part of the program is the fancy footwork to obtain an instance of a parser without mentioning the actual class name of the concrete parser we are going to use. As a reminder, it will be explained before the end of the chapter. For now, take it for granted that we end up with a SAX parser instance.

The next part of the program is critical. It shows how we register our routines for the callbacks. Rather than register each individual routine, the way we do with basic event handling in Swing, we make our class extend the class org.xml.sax.helpers.DefaultHandler.

That class has 20 or so methods and is the default base class for SAX2 event handlers. When we extend that class, we can provide new implementations for any of the methods. Where we provide a new implementation, our version will be called when the corresponding SAX event occurs.

For those familiar with Swing, this is exactly the way the various Adapter classes, e.g., MouseAdapter, work.

public class MySAXEcho extends org.xml.sax.helpers.DefaultHandler {

    public static void main(String argv[]) {
        // Get a SAX Factory
        SAXParserFactory factory = SAXParserFactory.newInstance();

        // Use an instance of ourselves as the SAX event handler
        DefaultHandler me = new MySAXEcho();

        try {
            SAXParser sp  = factory.newSAXParser();

            // Parse the input
            sp.parse( new File(argv[0]), me);

        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    static private PrintStream  o = System.out;

The two lines in bold show where we create an instance of our class and then pass it as an argument to the parse routine, along with the XML file. At that point, our routines will start to be invoked by the SAX parser.

The routines we have provided in this case are shown in the following example.

 //===========================================================
    // SAX DocumentHandler methods
    //===========================================================

    public void startDocument()
    throws SAXException
    {
        o.println("In startDocument");
    }

    public void startElement(String namespaceURI,
                             String sName, // simple name (localName)
                             String qName, // qualified name
                             Attributes attrs)
    throws SAXException
    {
        o.print( "got elem <"+sName);
        if (attrs != null) {
            for (int i = 0; i < attrs.getLength(); i++) {

o.println(attrs.getLocalName(i)+"=""+attrs.getValue(i)+""");
            }
        }
        o.println("");
    }

    public void characters (char buf[], int offset, int len)
            throws SAXException {
        String s = new String(buf, offset, len);
        o.print(s);
    }

    public void endElement(String namespaceURI,
                           String sName, // simple name
                           String qName  // qualified name
                          )
    throws SAXException
    {
        o.println("</"+sName+"");
    }

}

And that's our complete SAX parser. In this case, we have provided the routines to get callbacks for the start of the document and each element, for the character data inside each element, and for the end of each element. A review of the DefaultHandler class will show all the possibilities. You should download, compile and run the program.

A sample data file of a CD, complete with DTD, looks like this:

<?xml version="1.0"?>
<!DOCTYPE inventory  [
<!ELEMENT inventory (cd)* >
    <!ELEMENT cd (title, artist, price, qty)>
        <!ELEMENT title (#PCDATA)>
        <!ELEMENT artist (#PCDATA)>
        <!ELEMENT price (#PCDATA)>
        <!ELEMENT qty (#PCDATA)>
]>

<inventory>
  <cd> <title>Some Girls</title>   <artist>Rolling Stones</artist>
       <price>25</price>  <qty>5</qty>  </cd>
</inventory>

Compile and execute the program, giving the name of the data file on the command line:

javac SAXEcho.java
java SAXEcho  cd.xml

You will see output from the echo part of the code like this:

In startDocument
Some Girls</>
got elt <
>
Rolling Stones</>
got elt <
>
25</>

One of the exercises at the end of the chapter is to update the program to provide more readable output about the elements it finds.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.197.95