Monday, September 10, 2007

Part II: Struts 2 XML experiments using XSLTResult

In my last blog entry I described how Struts 2 outputs XML using XSLTResult. In this entry I will answer the second part of the query that I sent to the Struts mailing list and introduce a new XSLTResult, one which handles XSLT 2.0.

Imagine you want to use an XSLT 2.0 stylesheet with Struts 2. The default XSLTResult expects you to use the Xalan XSLT processor by default. However, occasionally it is easier for me to use XSLT 2.0. So I downloaded the Saxon XSLT 2.0 processor libraries (freeware versions - not schema-aware). For what I am about to produce you will need saxon8.jar and saxon8-dom.jar.

Usually, if you want to change XSLT processor you need to do so for the entire JVM using the javax.xml.transform.TransformerFactory system property. This means you will use Saxon for all XSLT I didn't want to do this. I only want to use XSLT 2.0 occasionally and use Xalan the rest of the time. So I took a copy of XSLTResult and tweaked it in places to make specific reference to using Saxon for XSLT transformations which should allow me to use Saxon and Xalan in parallel.

Here is my XSLT2Result code, a tweaked version of XSLTResult which uses Saxon rather than Xalan (nothing else particularly special here!).

Now I added my new ResultType to my Struts configuration.


<result-types>
<result-type name="xslt2" class="bristol.XSLT2Result"/>
</result-types>

To prove that the XSLT 2.0 processor is being utilised I used the following XSL which ignores the incoming XML and prints the details of the active XSLT processor.


<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xslprocessor>
<vendor><xsl:value-of select="system-property('xsl:vendor')"/></vendor>
<vendor-url><xsl:value-of select="system-property('xsl:vendor-url')"/></vendor-url>
<xslt-version><xsl:value-of select="system-property('xsl:version')"/></xslt-version>
</xslprocessor>
</xsl:template>
</xsl:stylesheet>

Now I configured two Struts actions, one using the normal XSLTResult and one using my new XSLT2Result class. I then setup a page with links to my two new actions (XML1.action and XML2.action).


<action name="XML1" class="example.Example">
<result type="xslt">
<param name="location">/WEB-INF/identify.xsl</param>
<param name="exposedValue">{bookmarks,months}</param>
</result>
</action>

<action name="XML2" class="example.Example">
<result type="xslt2">
<param name="location">/WEB-INF/identify.xsl</param>
<param name="exposedValue">{bookmarks,months}</param>
</result>
</action>

XML1 should use Xalan and the result reported that it did.


<xslprocessor>
<vendor>Apache Software Foundation (Xalan XSLTC)</vendor>
<vendor-url>http://xml.apache.org/xalan-j</vendor-url>
<xslt-version>1.0</xslt-version>
</xslprocessor>

All being well XML2 should use Saxon and the result reported that it did.


<xslprocessor>
<vendor>SAXON 8.9 from Saxonica</vendor>
<vendor-url>http://www.saxonica.com/</vendor-url>
<xslt-version>2.0</xslt-version>
</xslprocessor>

There we have it. A modified XSLTResult which uses Saxon and is therefore able to process XSLT 2.0. I am now able to create Struts 2 apps mixing XSLT 1.0 and XSLT 2.0 stylesheets when the need arises.