Home > Articles > Programming > Java

  • Print
  • + Share This
From the author of

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. Thus, in this example, two separate style sheets are used to process the XML file perennials.xml (Listing 4), and, depending on which client browser accesses the JavaServer Page, Daylilies.jsp (Listing 6), the correct style sheet is applied. The first XSL document, perennials-ie.xsl (Listing 7) 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 8) formats the daylilies in a basic table suitable for Netscape.

Listing 6—Daylilies.jsp. A JavaServer Page that invokes a custom tag to transform an XML document based on the browser type. The XML document and corresponding style sheets for Internet Explorer and Netscape are specified as tag attributes.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
 <TITLE>Daylilies</TITLE>
</HEAD>
<BODY>
<%@ taglib uri="/WEB-INF/tlds/xsltransform.tld" prefix="cwp" %>

<H1 ALIGN="CENTER">Katie's Favorite Daylilies</H1>
<P>
<cwp:xslt xml='/xml/perennials.xml'
     xslie='/xsl/perennials-ie.xsl'
     xslns='/xsl/perennials-ns.xsl' />

</BODY>
</HTML>

Listing 7—perennials-ie.xsl. Style sheet to use with Internet Explorer. Assumes support for THEAD, TBODY, and TFOOT elements in an HTML table.

<?xml version="1.0"?>
<!-- Style sheet using THEAD, TBODY, and TFOOT elements. -->
<!-- Suitable for Internet Explorer 4.x and later.    -->
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <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 8—perennials-ns.xsl. Style sheet to use for Netscape clients.

<?xml version="1.0"?>
<!-- Style sheet using 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>

The Tag Library Descriptor (TLD) for the custom JSP tag, xsltransform, used in Daylilies.jsp, is presented in xsltransform.tld (Listing 9). The tag class for this custom tag is 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.

Listing 9—xsltransform.tld. Tab Library Descriptor for XSLT custom tag.

<?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>
 <info>
  A tag library from Core Web Programming,
  http://www.corewebprogramming.com/.
 </info>

 <tag>
  <name>xslt</name>
  <tagclass>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>

The tag class, XslTransformTag, is shown in Listing 10. 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 1) and the result is sent to the JspWriter.

Listing 10—XslTransformTag.java. Performs an XSL transformation, writing the resultant document to the JspWriter. The XML and style sheets should be located in a location relative to the application context (ROOT).

package 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 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 {
  ServletContext context = pageContext.getServletContext();
  String path = context.getRealPath("/");

  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);
 }
}

This example requires numerous files that must be located in the proper directories on the server to run correctly. Figure 4 shows where to place the files on a Tomcat server.

Figure 4 Directory structure on Tomcat for custom tag example.

The result of Daylilies.jsp for Internet Explorer 5.0 on Windows 2000 is shown in Figure 5 and the result for Netscape 4.7 on Windows 98 is shown in Figure 6.

Figure 5 Transformation of perennials.xml through a custom JSP tag for Internet Explorer 5.0.

Figure 6 Transformation of perennials.xml through a custom JSP tag for Netscape 4.7.

The custom tag presented illustrates the ease in which the XslTransformer class given in Listing 1 can be used to accept different input streams for XML and XSL documents and transform the result to HTML. An improvement would be to incorporate a custom tag to perform JDBC queries and convert the query to an XML string document. Then the XML document could be provided as an input attribute to the XSLT custom tag. Another improvement would incorporate caching of the style sheets so that they're not read from disk for every client request.

For additional information on processing XML documents and using JavaServer Pages, please read Core Web Programming by Marty Hall and Larry Brown (Prentice Hall PTR, 2001, ISBN 0-13-089793-0).

  • + Share This
  • 🔖 Save To Your Account