Extension Interfaces and SAX - XMLFilters continued
(Page 3 of 4 )
Passing an XMLReader instance to the constructor sets that reader as its parent, so the parent reader receives any events passed on from the filter (which is all events, by virtue of the XMLFilterImpl class, unless the NamespaceFilter class overrides that behavior). By supplying two URIs—the URI to be replaced, and the URI to replace that old one with—your filter is ready to use. The three overridden methods handle any needed interchanging of that URI. Once you have a filter like this in place, you supply a reader to it, and then operate upon the filter, not the reader. For example, suppose that the SAXTreeViewer application is used to display XML versions of O’Reilly books, and the O’Reilly namespace URI for these books is universally being changed from http://www.oreilly.com to http://safari.oreilly.com . In that case, you could use the filter like this:
public void buildTree(DefaultTreeModel treeModel ,
DefaultMutableTreeNode base, String xmlURI)
throws IOException, SAXException {
String featureURI = "";
XMLReader reader = null;
try {
// Create instances needed for parsing
reader = XMLReaderFactory.createXMLReader();
JTreeHandler jTreeHandler =
new JTreeHandler(treeModel, base);
NamespaceFilter filter = new NamespaceFilter(reader,
"http://www.oreilly.com",
"http://safari.oreilly.com");
// Register content handler
filter.setContentHandler(jTreeHandler);
// Register error handler
filter.setErrorHandler(jTreeHandler);
// Register entity resolver
filter.setEntityResolver(new SimpleEntityResolver());
// Register lexical handler
filter.setProperty("http://xml.org/sax/properties/lexical-handler",
jTreeHandler);
// Turn on validation
featureURI = "http://xml.org/sax/features/validation";
filter.setFeature(featureURI, true);
// Turn on schema validation, as well
featureURI = "http://apache.org/xml/features/validation/ schema";
filter.setFeature(featureURI, true);
// Parse
InputSource inputSource = new InputSource(xmlURI);
filter.parse(inputSource);
} catch (SAXNotRecognizedException e) {
System.err.println("The parser class " + reader.getClass().getName() +
" does not recognize the feature URI '" + featureURI + "'");
System.exit(-1);
} catch (SAXNotSupportedException e) {
System.err.println("The parser class " + reader.getClass().getName() +
" does not support the feature URI '" + featureURI + "'");
System.exit(-1);
}
}
Of course, you can chain these filters together as well, and use them as standard libraries. When I’m dealing with older XML documents, I often create several of these with old XSL and XML Schema URIs and put them in place so I don’t have to worry about incorrect URIs:
XMLReader reader = XMLReaderFactory.createXMLReader(vendorParserClass);
NamespaceFilter xslFilter = new NamespaceFilter(reader,
"http://www.w3.org/TR/XSL",
"http://www.w3.org/1999/XSL/Transform");
NamespaceFilter xsdFilter = new NamespaceFilter(xslFilter,
"http://www.w3.org/TR/XMLSchema",
"http://www.w3.org/2001/XMLSchema");
Here, I’m building a longer pipeline to ensure that no old namespace URIs sneak by and cause my applications any trouble.
Be careful not to build too long a pipeline; each new link in the chain adds some processing time. All the same, this is a great way to build reusable components for SAX.
Next: XMLWriter >>
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.
|
|