Extension Interfaces and SAX - Extension Interfaces
(Page 2 of 4 )
Unfortunately, most parsers don’t support these extensions, so any sort of detailed coverage of them is infeasible. Icould show you how they behave under lesser-used parsers that support them, but that’s hardly helpful when you move to more main stream parsers like Apache Xerces. If you are interested in these extensions, check out the SAX Javadoc at http://www.saxproject.org/apidoc/org/xml/sax/ext/package-summary.html, and hope that by the next revision of this book, these will be more commonly supported (and then I’ll spend some time on them!).
For those who want the fullest in SAX features, you should check out AElfred2 and the GNU JAXP project, online at http://www.gnu.org/ software/classpathx/jaxp. I prefer to use Xerces for production work, but your mileage may vary.
Filters and Writers
At this point, Iwant to diverge from the beaten path. There are a lot of additional features in SAX that can really turn you into a power developer, and take you beyond the confines of “standard” SAX. In this section, I’ll introduce you to two of these: SAX filters and writers. Using classes both in the standard SAX distribution and available separately from the SAX web site (http://www.saxproject.org), you can add some fairly advanced behavior to your SAX applications. This will also get you in the mindset of using SAX as a pipeline of events, rather than a single layer of processing.
XMLFilters
First on the list is the org.xml.sax.XMLFilter class that comes in the basic SAX download, and should be included with any parser distribution supporting SAX 2. This class extends the XMLReader interface, and adds two new methods to that class, as shown in Figure 4-8.

Figure 4-8. Extra methods defined by the XMLFilter interface
It might not seem like there is much to say here; what’s the big deal, right? Well, by allowing a hierarchy of XMLReader s through this filtering mechanism, you can build up a processing chain, or pipeline, of events. To understand what I mean by a pipeline, you first need to understand the normal flow of a SAX parse:
- Events in an XML document are passed to the SAX reader.
- The SAX reader and registered handlers pass events and data to an application.
What developers started realizing, though, is that it is simple to insert one or more additional links into this chain:
- Events in an XML document are passed to the SAX reader.
- The SAX reader performs some processing and passes information to another SAX reader.
- Repeat until all SAX processing is done.
- Finally, the SAX reader and registered handlers pass events and data to an application.
It’s the middle two steps that create a pipeline, where one reader that performed specific processing passes its information on to another reader, repeatedly, instead of having to lump all code into one reader. When this pipeline is set up with multiple readers, modular and efficient programming results. And that’s what the XMLFilter class allows for: chaining of XMLReader implementations through filtering. Enhancing this even further is the class org.xml.sax.helpers.XMLFilterImpl , which provides a simple implementation of XMLFilter . It is the convergence of an XMLFilter and the DefaultHandler class: the XMLFilterImpl class implements XMLFilter , ContentHandler , ErrorHandler , EntityResolver , and DTDHandler , providing pass-through versions of each method of each handler. In other words, it sets up a pipeline for all SAX events, allowing your code to override any methods that need to insert processing into the pipeline.
Again, it’s best to see these in action. Example 4-2 is a working, ready-to-use filter. You’re past the basics, so I’m going to move through this rapidly.
Example 4-2. This simple filter allows for wholesale replacement of a namespace URI with a new URI
package javaxml3;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLFilterImpl;
public class NamespaceFilter extends XMLFilterImpl {
/** The old URI, to replace * /
private String oldURI;
/** The new URI, to replace the old URI with */
private String newURI;
public NamespaceFilter(XMLReader reader,
String oldURI, String newURI) {
super(reader);
this.oldURI = oldURI;
this.newURI = newURI;
}
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
// Change URI, if needed
if (uri.equals(oldURI)) {
super.startPrefixMapping(prefix, newURI);
} else {
super.startPrefixMapping(prefix, uri);
}
}
public void startElement(String uri, String localName,
String qName, Attributes attributes)
throws SAXException {
// Change URI, if needed
if (uri.equals(oldURI)) {
super.startElement(newURI, localName, qName, attributes);
} else {
super.startElement(uri, localName, qName, attributes);
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
// Change URI, if needed
if (uri.equals(oldURI)) {
super.endElement(newURI, localName, qName);
} else {
super.endElement(uri, localName, qName);
}
}
}
Start out by extending XMLFilterImpl , so you don’t have to worry about any events that you don’t want to deal with (like DefaultHandler , you’ll get no-op methods “for free”); the XMLFilterImpl class takes care of them by passing on all events unchanged unless a method is overridden. All that’s left, in this example, is to change a namespace URI from an old one, to a new one.
If this example seems trivial, don’t underestimate its usefulness. Many times in the last several years, the URI of a namespace for a specifica tion (such as XML Schema or XSLT) has changed. Rather than having to hand-edit all of my XML documents or write code for XML that I receive, this NamespaceFilter takes care of the problem for me.
Next: XMLFilters continued >>
More Java Articles
More By O'Reilly Media
|
This article is excerpted from chapter four of the book Java and XML, Third Edition, written by Brett McLaughlin and Justin Edelson (O'Reilly, 2006; ISBN: 059610149X). Check it out today at your favorite bookstore. Buy this book now.
|
|