What's with the Space Before Your End Slash, Brett?
3.1 Getting Prepared
3.2.1 Instantiating a Reader
SAX provides an interface all SAX-compliant XML parsers should implement. This allows SAX to know exactly what methods are available for callback and use within an application. For example, the Xerces main SAX parser class,
org.apache.xerces.parsers.SAXParser, implements the
org.xml.sax.XMLReader interface. If you have access to the source of your parser, you should see the same interface implemented in your parser's main SAX parser class. Each XML parser must have one class (and sometimes has more than one) that implements this interface, and that is the class you need to instantiate to allow for parsing XML:
// Instantiate a Reader XMLReader reader =
new org.xml.sax.SAXParser( ); // Do something with the parser reader.parse(uri);
With that in mind, it's worth looking at a more realistic example. Example 3-1 is the skeleton for the SAXTreeViewer class I was just referring to, which allows viewing of an XML document as a graphical tree. This also gives you a chance to look at each of the SAX events and associated callback methods that can be used to perform action within the parsing of an XML document.
Example 3-1. The SAXTreeViewer skeleton package javaxml2;
import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map;
import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.XMLReaderFactory;
// This is an XML book - no need for explicit Swing imports import java.awt.*;
import javax.swing.*; import javax.swing.tree.*;
public class SAXTreeViewer extends JFrame { /** Default parser to use */
private String vendorParserClass =
"org.apache.xerces.parsers.SAXParser"; /** The base tree to render */
private JTree jTree; /** Tree model to use */
DefaultTreeModel defaultTreeModel; public SAXTreeViewer( ) {
// Handle Swing setup super("SAX Tree Viewer"); setSize(600, 450);
}
public void init(String xmlURI) throws IOException, SAXException { DefaultMutableTreeNode base =
new DefaultMutableTreeNode("XML Document: " + xmlURI);
// Build the tree model
defaultTreeModel = new DefaultTreeModel(base); jTree = new JTree(defaultTreeModel);
// Construct the tree hierarchy
buildTree(defaultTreeModel, base, xmlURI); // Display the results
getContentPane( ).add(new JScrollPane(jTree), BorderLayout.CENTER);
}
public void buildTree(DefaultTreeModel treeModel,
DefaultMutableTreeNode base, String xmlURI) throws IOException, SAXException {
// Create instances needed for parsing XMLReader reader =
// Register content handler // Register error handler // Parse
}
public static void main(String[] args) { try {
if (args.length != 1) { System.out.println(
"Usage: java javaxml2.SAXTreeViewer " + "[XML Document URI]");
System.exit(0); }
SAXTreeViewer viewer = new SAXTreeViewer( ); viewer.init(args[0]); viewer.setVisible(true); } catch (Exception e) { e.printStackTrace( ); } } }
This should all be fairly straightforward.[1] Other than setting up the visual properties for Swing, this code takes in the URI of an XML document (our contents.xml from the last chapter). In the init( ) method, a JTree is created for displaying the contents of the URI. These objects (the tree and URI) are then passed to the method that is worth focusing on, the buildTree( ) method. This is where parsing will take place, and the visual representation of the XML document supplied will be created. Additionally, the skeleton takes care of creating a base node for the graphical tree, with the path to the supplied XML document as that node's text.
[1] Don't be concerned if you are not familiar with the Swing concepts involved here; to be honest, I had
to look most of them up myself! For a good reference on Swing, pick up a copy of Java Swing by Robert Eckstein, Marc Loy, and Dave Wood (O'Reilly).
U-R-What?
I've just breezed by what URIs are both here and in the last chapter. In short, a URI is a uniform resource indicator. As the name suggests, it provides a standard means of identifying (and thereby locating, in most cases) a specific resource; this resource is almost always some
sort of XML document, for the purposes of this book. URIs are related to URLs, uniform resource locators. In fact, a URL is always a URI (although the reverse is not true). So in the
examples in this and other chapters, you could specify a filename or a URL, like http://www.newInstance.com/javaxml2/copyright.xml, and either would be accepted.
You should be able to load and compile this program if you made the preparations talked about earlier to ensure that an XML parser and the SAX classes are in your class path. If you have a parser other than Apache Xerces, you can replace the value of the
vendorParserClass variable to match your parser's XMLReader implementation class, and leave the rest of the code as is. This simple program doesn't do much yet; in fact, if you run it and supply a legitimate filename as an argument, it should happily grind away and show you an empty tree, with the document's filename as the base node. That's because you have only instantiated a reader, not requested that the XML document be parsed.
If you have trouble compiling this source file, you most likely have problems with your IDE or system's class path. First, make sure you
obtained the Apache Xerces parser (or your vendor's parser). For Xerces, this involves downloading azipped or gzipped file. This archive can then be extracted, and will contain a xerces.jar file; it is this jar file that contains the compiled class files for the program. Add this archive to your class path. You should then be able to compile the source file listing.