Using Java Xalan extensions with XSLT
November 03, 2010 20:52:49 Last update: November 23, 2011 08:54:44
My problem is simple: in my XML data, a timestamp is provided as a long integer (number of milliseconds since the "the epoch"). When I do XSLT, I want to display it as a readable string, such as "Mon Nov 01 18:08:48 CDT 2010".
After hours of struggle, I found:
Below is a list of what worked and what didn't.
None of the above allowed me to set the time. So I created a utility class:
I think there's a pattern, but nothing makes much sense!
After hours of struggle, I found:
- It's not so easy to get the job done with JDK 1.6
- There are tons of garbage on the web in this space (suggestions, code snippets that simply don't work)
- Simple Xalan extension functions was the only resource that's somewhat informative. Even there some of the examples don't work.
Below is a list of what worked and what didn't.
- This works:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:java="http://xml.apache.org/xslt/java"> <xsl:template match="/"> <xsl:value-of select="java:java.util.Date.new()"/> </xsl:template> </xsl:stylesheet>
- This does not (providing long value to Date constructor):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:java="http://xml.apache.org/xslt/java"> <xsl:template match="/"> <xsl:value-of select="java:java.util.Date.new(1288652928119)"/> </xsl:template> </xsl:stylesheet>
The transform throws exception:Exception in thread "main" java.lang.VerifyError: (class: time, method: template$dot$0 signature: (Lcom/sun/org/apache/xalan/internal/xsltc/DOM;Lcom/sun/org/apache/xml/internal/dtm/DTMAxisIterator;Lcom/sun/org/apache/xml/internal/serializer /SerializationHandler;I)V) Expecting to find double on stack at java.lang.Class.getDeclaredConstructors0(Native Method) at java.lang.Class.privateGetDeclaredConstructors(Class.java:2389) at java.lang.Class.getConstructor0(Class.java:2699) at java.lang.Class.newInstance0(Class.java:326) at java.lang.Class.newInstance(Class.java:308) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getTransletInstance(TemplatesImpl.java:353) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer(TemplatesImpl.java:382) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTransformer(TransformerFactoryImpl.java:618)
- This works:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:date="xalan://java.util.Date" extension-element-prefixes="date"> <xsl:template match="/" > <xsl:value-of select="date:new()"/> </xsl:template> </xsl:stylesheet>
- This does not (error is the same as before):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:date="xalan://java.util.Date" extension-element-prefixes="date"> <xsl:template match="/" > <xsl:value-of select="date:new(1288652928119)"/> </xsl:template> </xsl:stylesheet>
None of the above allowed me to set the time. So I created a utility class:
import java.util.Date; public class DateUtil { public static Date getDate(long time) { return new Date(time); } }
- This works:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:java="http://xml.apache.org/xslt/java"> <xsl:template match="/" > <xsl:value-of select="java:DateUtil.getDate(1288652928119)"/> </xsl:template> </xsl:stylesheet>
- So does this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:date="xalan://DateUtil" extension-element-prefixes="date"> <xsl:template match="/" > <xsl:value-of select="date:getDate(1288652928119)"/> </xsl:template> </xsl:stylesheet>
I think there's a pattern, but nothing makes much sense!