- Parsing XML Documents with DOM Level 2
- DOM Example: Representing an XML Document as a JTree
- Parsing XML Documents with SAX 2.0
- SAX Example 1: Printing the Outline of an XML Document
- SAX Example 2: Counting Book Orders
- Transforming XML with XSLT
- XSLT Example 1: XSLT Document Editor
- XSLT Example 2: Custom JSP Tag
- Summary
23.3 Parsing XML Documents with SAX 2.0
DOM processing is relatively straightforward since the DOM classes do all the "real" parsingyou just have to look through the parsed result for the data you want. However, DOM can be quite wasteful if you only care about a small part of the document. For example, suppose that you want to extract the first word from an XML document representing an entire dictionary. DOM would require you to parse and store the entire XML document (which could be huge in this case). With SAX, you need only store the parts you care about and can stop parsing whenever you want. On the other hand, SAX is a bit more work. The idea is that the system tells you when certain parsing events such as finding a start tag (<language rating="good">), an end tag (</language>), or a tag body (e.g., Java between the aforementioned start and end tags). You have to decide what to do when these events occur. Are you a JSP programmer? Does this process sound familiar? It shouldSAX processing is very similar to the way you go about defining custom JSP tag libraries (Section 20.7).
Installation and Setup
SAX is not a standard part of either Java 2 Standard Edition or the servlet and JSP APIs. So, your first step is to download the appropriate classes and configure them for use in your programs. Here is a summary of what is required.
-
Download a SAX-compliant parser. The parser provides the Java classes that follow the SAX 2 API as specified by the WWW Consortium. You can obtain a list of XML parsers in Java at http://www.xml.com/ pub/rg/Java_Parsers. We use the Apache Xerces-J parser in this book. See http://xml.apache.org/xerces-j/. This parser comes with the complete SAX API in Javadoc format.
-
Download the Java API for XML Processing (JAXP). This API provides a small layer on top of SAX that lets you plug in different vendor's parsers without making any changes to your basic code. See http://java.sun.com/xml/.
Set your CLASSPATH to include the SAX classes. In the case of Apache Xerces, you need to include xerces_install_dir\ xerces.jar. For example, on Windows you would do
set CLASSPATH=xerces_install_dir\xerces.jar;%CLASSPATH%
If you wanted to use DOM from servlets and JSP, you would copy the appropriate JAR file to the server's lib directory (if supported), unpack the JAR file (using jar -xvf) into the server's classes directory, or explicitly change the server's CLASSPATH, usually by modifying the server startup script.
Set your CLASSPATH to include the JAXP classes. These classes are in jaxp_install_dir/jaxp.jar. For example, on Unix/Linux and the C shell, you would do
setenv CLASSPATH jaxp_install_dir/jaxp.jar:$CLASSPATH
For use from servlets and JSP, see the preceding step.
Bookmark the SAX 2 and JAXP APIs. You can browse the official API at http://www.megginson.com/SAX/Java/ javadoc/, but the API that comes with Apache Xerces is easier to use because it is on your local system and is integrated with the DOM and JAXP APIs. More information on SAX can be found at http://www.megginson.com/SAX/.
Parsing
With SAX processing, there are two high-level tasks: creating a content handler and invoking the parser with the designated content handler. The following list summarizes the detailed steps needed to accomplish these tasks.
Tell the system which parser you want to use. This can be done in a number of ways: through the javax.xml.parsers.SAXParserFactory system property, through jre_dir/lib/ jaxp.properties, through the J2EE Services API and the class specified in META-INF/services/javax.xml.parsers.SAXParserFactory, or with a system-dependent default parser. The system property is the easiest method. For example, the following code permits users to specify the parser on the command line with the -D option to java, and uses the Apache Xerces parser otherwise.
public static void main(String[] args) { String jaxpPropertyName = "javax.xml.parsers.SAXParserFactory"; if (System.getProperty(jaxpPropertyName) == null) { String apacheXercesPropertyValue = "org.apache.xerces.jaxp.SAXParserFactoryImpl"; System.setProperty(jaxpPropertyName, apacheXercesPropertyValue); } ... }
Create a parser instance. First make an instance of a parser factory, then use that to create a parser object.
SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser();
Note that you can use the setNamespaceAware and setValidating methods on the SAXParserFactory to make the parser namespace aware and validating, respectively.
Create a content handler to respond to parsing events. This handler is typically a subclass of DefaultHandler. You override any or all of the following placeholders
startDocument, endDocument
Use these methods to respond to the start and end of the document; they take no arguments.
startElement, endElement
Use these methods to respond to the start and end tags of an element. The startElement method takes four arguments: the namespace URI (a String; empty if no namespace), the namespace or prefix (a String; empty if no namespace), the fully qualified element name (a String; i.e., "prefix:mainName" if there is a namespace; "mainName" otherwise), and an Attributes object representing the attributes of the start tag. The endElement method takes the same arguments except for the attributes (since end tags are not permitted attributes).
characters, ignoreableWhitespace
Use these methods to respond to the tag body. They take three arguments: a char array, a start index, and an end index. A common approach is to turn the relevant part of the character array into a String by passing all three arguments to the String constructor. Non-whitespace data is always reported to the characters method. Whitespace is always reported to the ignoreableWhitespace method a parser is run in validating mode, but can be reported to either method otherwise.
Invoke the parser with the designated content handler. You invoke the parser by calling the parse method, supplying an input stream, URI (represented as a string), or org.xml.sax.InputSource along with the content handler.
parser.parse(filename, handler);
The content handler does the rest.