Making client-side XSLT practical with JSP taglibs

Inigo Surguy

Browser support for client-side XSLT

Using XML and XSLT to style content makes a lot of sense, for all the usual reasons - separation of content from presentation, easier repurposing of content, etc. Sending the XML and XSLT to the browser makes a lot of sense too - it reduces download time, reduces bandwidth costs, and reduces the load on the server.

Unfortunately, browser support for XSLT is wildly variable. The latest browsers, IE 6, Netscape 6+ and Mozilla, support XSLT 1.0 almost completely, but IE 5 and IE 5.5 support an early draft of the XSLT spec, and Netscape 4 and IE 4 have no support at all. Even many modern browsers like Opera 6, Konqueror and Omniweb don't support XSLT.

This might seem to limit client-side XSLT usage to only those situations where the audience is using the latest browsers, but server-side browser detection means that we can avoid this problem. In this article, I will show how it is both possible and easy to use a server-side Java taglib to apply XSLT either on the server or on the client, depending on the browser.

Using a Java taglib for client or server styling of XML

To send the appropriate content to the client requires that some server-side browser detection is done, and that the content is styled on the server if necessary. This is done with a Java taglib called clientsidexsl. A tag is added wrapping the XML content, as shown in the following example:

< %@ taglib uri="/clientsidexsl" prefix="csxsl" %>
< csxsl:xml-stylesheet stylesheet="animals.xsl" stylesheetWD="animals.xsl">
<animals>
    <animal>
	<name>Platypus</name>
	<nationality>Australian</nationality>
	<strangeness>9</strangeness>
    </animal>
    <animal>
	<name>Demon duck of doom</name>
	<nationality>Australian</nationality>
	<strangeness>8</strangeness>
    </animal>
</animals>
< /csxsl:xml-stylesheet>		

		

The differences from a standard XML document intended for client side display are the first two lines, and the last.

The first line references the clientsidexsl JSP taglib, and makes its tags available within the page within the csxsl namespace.

The second and last lines are a replacement for the usual:

< ?xml-stylesheet type="text/xsl" href="example.xsl" ?>

directive to reference the stylesheet. The new tag checks what the browser requesting the page is (using the user-agent header), and will either send the XML and XSLT to the client, or will perform the transformation on the server using a TRAX-compatible XSLT processor.

If the stylesheetWD attribute is specified, then a browser using XSL-WD (that is, IE 5 and IE 5.5) will be sent that stylesheet. Otherwise, browsers that do not support XSLT 1.0 will be sent the processed results.

Using the clientsidexsl taglib in an XSLT document

When the XSLT is simple, it's often possible to use the same stylesheet for old XSL-WD browsers as for the more recent XSLT 1.0 browsers. The only problem is that whereas recent browsers require a root element like:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

... the older browsers require one that looks like:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">

So, to make a stylesheet that works with both IE 5 and IE 6/Mozilla, then we need to do the same sort of server-side browser sniffing as above.

In the clientsidexsl taglib, this is done with the stylesheet tag. It outputs the appropriate namespace for the browser requesting it. An example XSLT file using the tag looks like:


< %@taglib uri="/clientsidexsl" prefix="csxsl" %>
< csxsl:stylesheet>
    <!-- Required for IE 5 XSL-WD support -->
    <xsl:template match="/">
	    <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="animals">
	<html>
	<head><title>List of animals</title></head>
	<body>
	    <h2>List of animals</h2>
	    <xsl:apply-templates />
	</body>
	</html>
    </xsl:template>

    <xsl:template match="animal">
	<h2><xsl:value-of select="name"/></h2>
	<p>The <xsl:value-of select="name"/> is 
	<xsl:value-of select="nationality"/> and has strangeness 
	factor <xsl:value-of select="strangeness"/>.</p>
    </xsl:template>
< /csxsl:stylesheet>
		

Downloading the clientsidexsl taglib

The taglib and its sourcecode are Free Software - you can download the taglib here.

It is covered by the GNU General Public Licence.

Setting up your servlet container

If you're using a Servlet 2.3 and JSP 1.2 compliant server, such as Tomcat 4, then it should be very simple to set up and install the taglib. Just download the JAR file, and drop it into the WEB-INF/lib directory of your webapp.

Then, to make the servlet container interpret JSP taglibs in XML and XSL files, add the following to the web.xml file:

<servlet-mapping>
    	<servlet-name>jsp</servlet-name>
	<url-pattern>*.xml</url-pattern>
</servlet-mapping>

<servlet-mapping>
	<servlet-name>jsp</servlet-name>
	<url-pattern>*.xsl</url-pattern>
</servlet-mapping>

In practice, I've found that this doesn't always work. It may be necessary to extract the TLD from the JAR, and reference it directly in the JSP with a line something like:

< % @taglib uri="clientsidexsl.tld" prefix="csxsl" %>

You may also need to add a TRAX XSLT processor to your servlet engine's classpath, if there isn't one there already.

Speeding everything up with OSCache

The XSL tags work, but they're not exactly fast when they have to apply the stylesheet server-side. This is by design - I didn't want to complicate the code with caching logic.

Instead, I recommend using the OSCache library from OpenSymphony.

Update

I'm now using a servlet filter, rather than JSP tags, to convert the outgoing XML. This has the advantage that the source files don't need any editing - the raw Docbook XML can just be dumped in the right directory on the server (for example, with WebDAV).

About this document

This document is written in Simplified Docbook XML, and styled with XSLT either client-side or server-side, depending on your browser. The stylesheet is simpledocbook.xsl.

Return to index

Return to the index page.