SAX2 XMLReaders and Filters
SAX2 is built around the XMLReader interface, which is the key to working with filters. All SAX2 parsers implement the XMLReader interface, which allows an application to set and query parser properties as well as register event handlers for document processing.
The XMLFilter interface itself is simple, extending the basic XMLReader interface with two additional methods: setParent and getParent. For example:
public interface XMLFilter extends XMLReader { public abstract void setParent (XMLReader parent); public abstract XMLReader getParent (); }
Developers use the setParent method to set up the structure of a filter chain. Technically, the parent (not to be confused with the use of the term parent to describe a superclass/subclass relationship) holds the content handler that does the filtering. After either modifying the XML stream or taking independent action, it passes control to the next handler in the chain.
SAX2 conveniently provides a utility class, XMLFilterImpl, which simplifies setting up a stage in the filter pipeline. To create a filter, you create a subclass of XMLFilterImpl, and write the filter code in the same way that you write standard handler code.
For example, Listing 1 illustrates a filter handler that reports elements in an XML stream. The handler is implemented by subclassing XMLFilterImpl, and defines a startElement method that does the reporting. When writing a handler that will act as a filter in a chain, the handler code must call the corresponding method (lines 17–18) of the superclass (XMLFilterImpl) to pass control to the next handler in the chain.
Listing 1 A simple filter that displays the element name on the console.
1. import org.xml.sax.helpers.XMLFilterImpl; 2. import org.xml.sax.Attributes; 3. import org.xml.sax.SAXException; 4. 5. 6. 7. public class SaxLoggingFilter extends XMLFilterImpl { 8. 9. public void startElement (String namespaceUri, String localName, 10. String qualifiedName, 11. Attributes attributes) 12. throws SAXException { 13. 14. System.out.println("Found element" + qualifiedName); 15. 16. // passes data to the next stage of the filter chain 17. super.startElement(namespaceUri, localName, 18. qualifiedName, attributes); 19. } 20. }