11.4. Aside: Parsing XML with SAX 2.0

The validate method of TagLibraryValidator gives you a PageData object from which you can obtain an InputStream that is associated with the XML version of the JSP page. You are unlikely to want to read directly from that stream to try to validate proper usage of your custom tags: the input streams and readers in the java.io package are too low level to be effective for this usage. Instead, you will probably want to use an XML parser to do the low-level work for you. The validators of Section 11.3 used the SAX 2.0 API, so I’ll summarize its use here. More detail on SAX can be found at http://www.saxproject.org/. For information on DOM and other XML-related APIs, see http://www.w3.org/XML/, one of the many XML and Java texts such as Java & XML 2nd Edition (O’Reilly 2001), or the SAX, DOM, and XSLT summary in Chapter 23 of Core Web Programming 2nd Edition (Prentice Hall and Sun Microsystems Press 2001).

SAX processing is a lot like writing custom tag handlers: you write methods to handle the start tag, end tag, and tag body. The major difference is that SAX handlers are not associated with specific tags—the same handler fires for all tags. So, with SAX you have to repeatedly check which tag you are working with. Of course, this capability is exactly what makes SAX so useful for checking that different tags are interacting properly.

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.

1.
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. I 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.

2.
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/.

3.
Tell your development environment and the server about the SAX classes. In the case of Apache Xerces, the SAX classes are in xerces_install_dir/ xerces.jar. So, for example, to set up your development environment on Windows 98, you would do

set CLASSPATH=xerces_install_dirxerces.jar;%CLASSPATH% 

To tell the server about the SAX classes, you would either copy the JAR file to the Web application’s lib directory, unpack the JAR file (using jar -xvf) into the server’s classes directory, or put the JAR file in a shared location (if your server supports such a capability—see Section 4.4, “ Recording Dependencies on Server Libraries ”).

4.
Set your CLASSPATH to include the JAXP classes. These classes are in jaxp_install_dir/jaxp.jar. For example, to set up your development environment on Unix/Linux with the C shell, you would do

setenv CLASSPATH jaxp_install_dir/jaxp.jar:$CLASSPATH 

To tell the server about the JAXP classes, see the preceding step.

5.
Bookmark the SAX API. You can browse the official API at http://www.saxproject.org/apidoc/index.html, 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.saxproject.org/.

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.

1.
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 deployers to specify the parser in the server startup script with the -D option to java, and uses the Apache Xerces parser otherwise.

String jaxpPropertyName = 
  "javax.xml.parsers.SAXParserFactory"; 
if (System.getProperty(jaxpPropertyName) == null) {
  String apacheXercesPropertyValue = 
    "org.apache.xerces.jaxp.SAXParserFactoryImpl"; 
  System.setProperty(jaxpPropertyName, 
                     apacheXercesPropertyValue); 
} 
... 

2.
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.

3.
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-white-space data is always reported to the characters method. White space is always reported to the ignoreableWhitespace method when the parser is run in validating mode but can be reported to either method otherwise.

4.
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. Note that InputSource has a simple constructor that accepts an InputStream. Use this constructor to turn the InputStream of the TagLibraryValidator validate method into an InputSource.

parser.parse(new InputSource(validatorStream), handler); 

The content handler does the rest.

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

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