10.7 Filtering XMLYou can filter XML documents with a SAX filter.[13] SAX, which stands for Simple API for XML, is a language-independent, event-based API for parsing XML. SAX reports parsing eventssuch as the start and end of elementsthrough callback methods. For example, consider the following simple XML document:
<?xml version='1.0'?> <document> <greeting>Welcome</greeting> </document> SAX represents the preceding XML document as a series of events, like this:
SAX applications handle those events by registering an event handler and implementing methods that correspond to the events listed above. As of SAX 2.0, you can filter XML documents by inserting a filter between the SAX parser and the application that handles SAX events. Using JSTL to filter XML documents with a SAX filter is a simple two-step process:
Figure 10-6 shows a Web application that implements the steps listed above to filter specific elements in an XML document Figure 10-6. Filtering XMLThe Web application shown in Using Transformation Parameters" on page 446, except the former uses a SAX filter to filter elements in XML documents, whereas the latter removes columns from the HTML table with an XSLT stylesheet. The top picture in Figure 10-6 shows the application's welcome page. The middle picture shows the XSLT-generated HTML table with email elements filtered, and the bottom picture shows the HTML table with home phone elements filtered. Listing 10.11 lists the welcome page for the application shown in Figure 10-6. Listing 10.11 index.jsp (Using SAX Filters)<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <l> <head> <title>Using SAX Filters</title> </head> <body> <%@ taglib uri='http://java.sun.com/jstl/core' prefix='c' %> <%@ taglib uri='http://java.sun.com/jstl/xml' prefix='x' %> <%-- Import the XML document and XSLT stylesheet and store the result in session-scoped variables, which are accessed below and in apply_filter.jsp --%> <c:import var='rolodex_xml' scope='session' url='rolodex.xml'/> <c:import var='rolodex_xsl' scope='session' url='rolodex.xsl'/> <%-- Transform the XML document with the XSLT stylesheet --%> <x:transform xml='${rolodex_xml}' xslt='${rolodex_xsl}'/> <%-- Import the form --%> <c:import url='form.jsp'/> </body> <l> The preceding JSP page imports the XML document and XSLT stylesheet and stores the resulting scoped variables in session scope. Subsequently, that JSP page performs an initial transformation and imports the JSP page that creates the form. That JSP pageform.jspis listed in Retaining Values for HTML Option Elements" on page 129 for more information about HTML select elements that retain their values.
The preceding JSP page uses <jsp:useBean> to create a SAX filter. A <c:set> action within the body of the <jsp:useBean> action specifies the type of element that the filter filters with the value of the filterThis request parameter. Subsequently, the JSP page parses the XML document, specifying the filter with the <x:parse> filter attribute. The JSP page then performs the transformation, specifying the name of the filtered element with a transformation parameter. Finally, the JSP page includes form.jsp so the user can subsequently select a different element to filter. Listing 10.12 form.jsp (Creating a Selection Form)<%@ taglib uri='http://java.sun.com/jstl/core' prefix='c' %> <%-- Create a form that lets the user select an inventory column to filter --%> <form action='apply_filter.jsp'> Filter an element: <select name='filterThis'> <option value='NONE' <c:if test='${param.filterThis == "NONE"}'> selected </c:if> >NONE </option> <option value='email' <c:if test='${param.filterThis == "email"}'> selected </c:if> >email </option> <option value='phone@home' <c:if test='${param.filterThis == "phone@home"}'> selected </c:if> >home phone </option> <option value='phone@work' <c:if test='${param.filterThis == "phone@work"}'> selected </c:if> >work phone </option> </select> <p><input type='submit' value='Filter XML'/> </form> SAX filters are straightforward to implement. Although it's not strictly necessary, most SAX filters extend the org.xml.sax.helpers.XMLFilterImpl class, which implements the SAX handler interfaces. That base class simply forwards all handler events to an XML reader; implementing a SAX filter involves extending that class and selectively overriding those handler methods as desired. Listing 10.13 apply_filter.jsp<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <l> <head> <title>Using SAX Filters</title> </head> <body> <%@ taglib uri='http://java.sun.com/jstl/core' prefix='c' %> <%@ taglib uri='http://java.sun.com/jstl/xml' prefix='x' %> <%-- Create a filter -- n ElementFilter instance -- and set the name of the element that the filter filters --%> <jsp:useBean id='filter' class='filters.ElementFilter'> The SAX filter created by the preceding JSP page is listed in Listing 10.14. That filter is a general-purpose filter that filters elements from an XML document. You can specify those elements in two ways: with the name of the element, which filters all elements with that name, or with an element/attribute combination specified with this syntax: element @ attribute. Elements, and optionally attributes, are specified with the filter's setElementToFilter method. The filter overrides the startElement, endElement, and characters methods, which are defined by the org.xml.sax.ContentHandler interface. After the JSP page listed in Listing 10.13 on page 456 parses the Rolodex XML file with the preceding SAX filter, that JSP page performs a transformation that transforms the filtered XML document into an HTML table. The XSLT stylesheet that performs that transformationrolodex.xslis listed in Listing 10.15. Listing 10.14 WEB-INF/classes/filters/ElementFilter.javapackage filters; The preceding stylesheet is passed a transformation parameter that specifies the table column that corresponds to the filtered element. That parameter is used to omit the specified table column. Additionally, the stylesheet creates a table row for each contact element and table data for all of the contact element's child elements. Listing 10.15 rolodex.xsl (Transforming a Filtered XML Document)<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <!-- Declare the filteredColumn parameter--> |