CIS 97YT Index > Extensions to XSLT

Extensions to XSLT (a very short introduction)

You may use Java to write functions that can be called from an XSLT transformation. (We are using Java because Xalan is written in Java. Other XSLT processors may have different rules or require different languages.)

In this example, we have a weather report that has timestamps in number of seconds since 1 January 1970 (the TStamp attribute:

<Reports TStamp="997568716">
<SYN Title='AAXX' TStamp='997573600' LatLon='37.567, 126.967' BId='471080'
SName='RKSL, SEOUL' Elev='86'>
<SYID>47108</SYID>
<SYG T='22.5' TD='14.1' P='1004.1' P0='1014.1' Pd='0 0.1' Vis='22000'
Ceiling='INF' Wind='30-70, 1.5' WX='NOSIG' Prec=' ' Clouds='44070'>
32972 40703 10225 20141 30041 40141 50001 84070
</SYG></SYN>
</Reports>

The first step is to write a Java class that has functions that take the timestamp string and return the full date (as a String) and the hours and minutes (as a Double). We put these in a file named TimeStampUtils.java and compile it.

import java.util.Calendar;
import java.util.Date;
import java.text.DateFormat;

public class TimeStampUtils
{
    public static String getDate(String timeStampString)
    {
        DateFormat d = DateFormat.getDateInstance();
        long milliseconds = Long.parseLong( timeStampString ) * 1000;
        return 
            d.format(new Date(milliseconds));
    }
    
    public static Double getHour(String timeStampString)
    {
        long milliseconds = Long.parseLong( timeStampString ) * 1000;
        Calendar c = Calendar.getInstance();
        c.setTime( new Date( milliseconds ) );
        return new Double( c.get( Calendar.HOUR_OF_DAY ) );
    }
    
    public static Double getMinute(String timeStampString)
    {
        long milliseconds = Long.parseLong( timeStampString ) * 1000;
        Calendar c = Calendar.getInstance();
        c.setTime( new Date( milliseconds ) );
        return new Double( c.get( Calendar.MINUTE ) );
    }
}

Now we write the stylesheet (line numbers have been added for reference).

 1 <xsl:stylesheet version="1.0"
 2    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 3    xmlns:java="http://xml.apache.org/xslt/java"
 4    exclude-result-prefixes="java">
 5
 6 <xsl:output method="html"/>
 7 <xsl:template match="Reports">
 8 <html>
 9 <head>
10 <title>OMF Weather Status Report</title>
11 </head>
12
13 <body>
14 <h1>OMF Weather Status Report</h1>
15 <xsl:apply-templates select="SYN"/>
16 </body>
17 </html>
18 </xsl:template>
19
20 <xsl:template match="SYN">
21 <dl>
22 <dt>Station</dt>
23 <dd><xsl:value-of select="@SName"/></dd>
24
25 <dt>Latitude/Longitude</dt>
26 <dd><xsl:value-of select="@LatLon"/></dd>
27
28 <dt>Date</dt>
29 <dd><xsl:value-of select="java:TimeStampUtils.getDate( @TStamp )"/></dd>
30
31 <dt>Time:</dt>
32 <dd><xsl:value-of
33    select="java:TimeStampUtils.getHour( @TStamp )"/> hr
34    <xsl:value-of
35    select="java:TimeStampUtils.getMinute( @TStamp )"/> min</dd>
36 </dl>
37 </xsl:template>
38
39 </xsl:stylesheet>
Line 3
Establishes the java namespace for use with extensions.
Line 4
Tells the processor not to put a namespace prefix on any elements that are output from java.
Lines 29, 33, 35
This is where we make the calls to the Java functions. The arguments can be any XPath expression; it will be converted to a string and passed to the function, whose value will be returned.

To run this transformation, you will (to make your life easier) want to put the original XML file, the XSLT file, the compiled class file, and the transform.bat file into the same folder. Modify the transform.bat file to include the current directory in your classpath. Notice the .; at the beginning of the classpath.


echo off
java -cp .;f:\xmljar\xalan-j_2_3_0\bin\xml-apis.jar;f:\xmljar\xalan-j_2_3_0\bin\xercesImpl.jar;f:\xmljar\xalan-j_2_3_0\bin\xalan.jar org.apache.xalan.xslt.Process -IN %1 -XSL %2 -OUT %3 %4 %5 %6 %7 %8 %9