- Parsing XML Documents with DOM Level 2
- DOM Example: Representing an XML Document as a JTree
- Parsing XML Documents with SAX 2.0
- SAX Example 1: Printing the Outline of an XML Document
- SAX Example 2: Counting Book Orders
- Transforming XML with XSLT
- XSLT Example 1: XSLT Document Editor
- XSLT Example 2: Custom JSP Tag
- Summary
23.8 XSLT Example 2: Custom JSP Tag
In this example, a custom JSP tag is used along with XSLT to output a listing of Stout Medal daylilies in an HTML table, formatted specifically for the client's browser type. Netscape 4.7 and earlier do not support the HTML 4.0 elements: THEAD, TBODY, and TFOOT. However, these three elements are supported by Internet Explorer 4.x and later (see Section 2.4, "Tables," for details on these elements). Thus, in this example, two separate style sheets are used to process the XML file, peren_nials.xml (Listing 23.4), and depending on which client browser accesses the JavaServer Page, Daylil_ies.jsp (Listing 23.18), the correct style sheet is applied. The first XSL document, peren_nials-ie.xsl (Listing 23.16) formats the daylilies in a table suitable for Internet Explorer by using THEAD, TBODY, and TFOOT elements, and the second XSL document, perennials-ns.xsl (Listing 23.17) formats the daylilies in a basic table suitable for Netscape.
The Tag Library Descriptor (TLD) for the custom JSP tag, xsltransform, used in Daylil_ies.jsp, is presented in xsltransform.tld (Listing 23.19). The tag class for this custom tag is cwp.tags.XslTransformTag. Three attributes are defined for the tag: xml, the source XML file (required), xslie, the XSL style sheet targeting Internet Explorer, and xslns (required), the XSL style sheet targeting Netscape. The xslns style sheet is required because this is the default style sheet applied if the client browser is not Internet Explorer. For additional information on custom tags, see Section 20.7 (Defining Custom JSP Tags).
The tag class, XslTransformTag, is shown in Listing 23.20. The doStartTag method builds the File objects for the XML and XSL document, where the XSL document applied for the style sheet is determined by the User-Agent header in the HTTP request. After the source files are determined, the XSLT transform is performed with XslTransformer (Listing 23.12) and the result is sent to the JspWriter.
This example requires numerous files that must be located in the proper directories on the server to run correctly. In Figure 2310, we illustrate where to place the files on a Tomcat server. If the DTD, perennials.dtd, is not accessible on-line from http://www.corewebprogramming.com/dtds/, then place the DTD file in a dtds subdirectory as illustrated and modify the DOCTYPE to
<!DOCTYPE perennials SYSTEM "dtds/perennials.dtd">
The result for Internet Explorer 5.0 on Windows 2000 is shown in Figure 2311 and the result for Netscape 4.7 on Windows 98 is shown in Figure 2312.
Figure 2310 Location of files for custom JSP tag example on Tomcat.
Listing 23.16 perennials-ie.xsl
<?xml version="1.0"?> <!-- Style sheet using THEAD, TBODY, and TFOOT elements. --> <!-- Suitable for Internet Explorer 4.x and later. --> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html"/> <xsl:template match="/"> <TABLE CELLPADDING="3" RULES="GROUPS" ALIGN="CENTER"> <CAPTION>Stout Medal Award</CAPTION> <COLGROUP> <COL ALIGN="CENTER"/> <COL ALIGN="LEFT"/> <COL ALIGN="CENTER"/> </COLGROUP> <COLGROUP ALIGN="RIGHT"/> <THEAD> <TR> <TH>Year</TH> <TH>Cultivar</TH> <TH>Bloom Season</TH> <TH>Cost</TH> </TR> </THEAD> <TBODY> <!-- Select daylilies awarded Stout Medal. --> <xsl:apply-templates select="/perennials/daylily[award/name='Stout Medal']"/> </TBODY> <TFOOT> <TR> <TD COLSPAN="4">E-early M-midseason L-late</TD> </TR> </TFOOT> </TABLE> </xsl:template> <xsl:template match="daylily"> <TR> <TD><xsl:value-of select="award/year"/></TD> <TD><xsl:value-of select="cultivar"/></TD> <!-- Select the bloom code. --> <TD><xsl:value-of select="bloom/@code"/></TD> <TD><xsl:value-of select="cost"/></TD> </TR> </xsl:template> </xsl:stylesheet>
Listing 23.17 perennials-ns.xsl
<?xml version="1.0"?> <!-- Style sheet using a basic TABLE elements. --> <!-- Suitable for Netscape. --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html"/> <xsl:template match="/"> <TABLE CELLPADDING="3" BORDER="1" ALIGN="CENTER"> <CAPTION>Stout Medal Award</CAPTION> <TR> <TH>Year</TH> <TH>Cultivar</TH> <TH>Bloom Season</TH> <TH>Cost</TH> </TR> <!-- Select daylilies awarded Stout Medal. --> <xsl:apply-templates select="/perennials/daylily[award/name='Stout Medal']"/> <TR> <TD COLSPAN="4" ALIGN="CENTER"> E-early M-midseason L-late</TD> </TR> </TABLE> </xsl:template> <xsl:template match="daylily"> <TR> <TD><xsl:value-of select="award/year"/></TD> <TD><xsl:value-of select="cultivar"/></TD> <!-- Select the bloom code. --> <TD ALIGN="CENTER"><xsl:value-of select="bloom/@code"/></TD> <TD ALIGN="RIGHT"><xsl:value-of select="cost"/></TD> </TR> </xsl:template> </xsl:stylesheet>
Listing 23.18 Daylilies.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Daylilies</title> </head> <body> <%@ taglib uri="cwp-tags/xsltransform.tld" prefix="cwp" %> <H1 ALIGN="CENTER">Katie's Favorite Daylilies <p> <cwp:xsltransform xml='perennials.xml' xslie='perennials-ie.xsl' xslns='perennials-ns.xsl' /> </body> </html>
Listing 23.19 xsltransform.tld
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd"> <taglib> <tlibversion>1.0</tlibversion> <jspversion>1.1</jspversion> <shortname>cwp</shortname> <urn></urn> <info> A tag library from Core Web Programming, http://www.corewebprogramming.com/. </info> <tag> <name>xsltransform</name> <tagclass>cwp.tags.XslTransformTag</tagclass> <info>Applies xslt transform based on browser type.</info> <attribute> <name>xml</name> <required>yes</required> </attribute> <attribute> <name>xslie</name> <required>false</required> </attribute> <attribute> <name>xslns</name> <required>true</required> </attribute> </tag> </taglib>
Listing 23.20 XslTransformTag.java
package cwp.tags; import java.io.*; import javax.servlet.*; import javax.servlet.jsp.*; import javax.servlet.http.*; import javax.servlet.jsp.tagext.*; import javax.xml.transform.*; import cwp.XslTransformer; /** A tag that translates an XML document to HTML using XSLT. * Depending on the client browser type, either an XSL style * targeting Internet Explorer or Netscape (default) is * applied. */ public class XslTransformTag extends TagSupport { private static final String FS = System.getProperty("file.separator"); private static final int IE = 1; private static final int NS = 2; private String xml, xslie, xslns; public void setXml(String xml) { this.xml = xml; } public String getXml() { return(xml); } public void setXslie(String xslie) { this.xslie = xslie; } public String getXslie() { return(xslie); } public void setXslns(String xslns) { this.xslns = xslns; } public String getXslns() { return(xslns); } public int doStartTag() throws JspException { // Determine the path to XML and XSL source files. // The path of SERVLET_HOME/WEB-INF/classes/cwp/ is // assumed for the location of the source files. String FS = System.getProperty("file.separator"); ServletContext context = pageContext.getServletContext(); String path = context.getRealPath(FS) + "WEB-INF" + FS + "classes" + FS + "cwp" + FS; HttpServletRequest request = (HttpServletRequest)pageContext.getRequest(); // Use either IE or NS style sheet depending on // browser type. File xslFile = null; if ((browserType(request) == IE) && (getXslie() != null)) { xslFile = new File(path + getXslie()); } else { xslFile = new File(path + getXslns()); } File xmlFile = new File(path + getXml()); try { JspWriter out = pageContext.getOut(); XslTransformer transformer = new XslTransformer(); transformer.process(xmlFile, xslFile, out); } catch(TransformerException tx) { context.log("XslTransformTag: " + tx.getMessage()); } return(SKIP_BODY); } // Determine the browser type based on the User-Agent // HTTP request header. private int browserType(HttpServletRequest request) { int type = NS; String userAgent = request.getHeader("User-Agent"); if ((userAgent != null) && (userAgent.indexOf("IE") >=0)) { type = IE; } return(type); } }
Figure 2311 Transformation of perennials.xml through a custom JSP tag for Internet Explorer 5.0 on Windows 2000.
Figure 2312 Transformation of perennials.xml through a custom JSP tag on Netscape 4.7 on Windows 98.