Specifying Extension Functions in Stylesheets

You can write XSLT extension functions in Java and invoke them in XPath expressions in stylesheets. This section provides instructions for implementing and invoking extension functions from your stylesheet. The syntax supported is a subset of that supported by LotusXSL/Apache Xalan.

This section covers the following topics:

Using an Extension Function in Stylus Studio

The process of using an extension function in Stylus Studio involves three main steps:

1. First, you need to write a Java class that can be used from within a stylesheet. In this example, the SystemDate() method returns the system date and time as a string:
import java.util.Date; 
               
public class SystemUtils 
               
{ 
               

              
public Object SystemDate() 
                   
{ 
                   
Date d = new Date(); 
                   
String s = d.toString(); 
                   
return s; 
                   
} 
                   

                
}
2. Second, compile your class and register it on the Stylus Studio host by copying the .class file to a location defined in the host's CLASSPATH environment variable.
3. Finally, specify information in the stylesheet so that Stylus Studo can use your class. You do this with a namespace reference in the xsl:stylesheet tag. For example, define a namespace as xmlns:Ext where Ext is the prefix to use when calling the class methods. ( Ext is not a predefined keyword; it can be replaced by any other legal string.) The namespace reference then takes the class name as a value. In this example, the whole reference looks like the following:
xmlns:Ext="SystemUtils" 
               

            

The class is now available from within the stylesheet and can be used in a template such as the following:

<xsl:template match="NODE"> 
               

              
<p><xsl:value-of select="Ext:SystemDate()"/></p> 
                   

                
</xsl:template>

The XSLT stylesheet might look like the following:

<?xml version="1.0" encoding="ISO-10646-UCS-2"?> 
               
<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform" 
               

              
xmlns:Ext="SystemUtils"> 
                   
<xsl:param name="param">test</xsl:param> 
                   
<xsl:template match="*|/">
                   
<xsl:apply-templates/>
                   
</xsl:template> 
                   
<xsl:template match="text()|@*">
                   
<xsl:value-of select="."/>
                   
</xsl:template> 
                   
<xsl:template match="NODE"> 
                   
<p><xsl:value-of select="Ext:SystemDate()"/></p> 
                   
</xsl:template> 
                   

                
</xsl:stylesheet>

Basic Data Types

XPath and XSLT data types map to Java data types according to Table 30:

XPath/XSLT Type
Java Type
Node Set
org.w3c.dom.NodeList
String
java.lang.String
Boolean
boolean or Boolean
Number
double or Double
Result Tree Fragment
org.w3c.dom.DocumentFragment
Table 30. XPath/XSLT and Java Type Mappings

Declaring an XSLT Extension Function

Extension functions must have one of the following signatures:

public Object FxnName()
       
public Object FxnName(Type1 var1, Type2 var2,...)
       
public static Object FxnName()
       
public static Object FxnName(Type1 var1, Type2 var2,...)
       

    

A class that contains an extension function might look like the following:

import org.w3c.dom.*;
               
public class NumberUtils
               
{ 
               

              
public Object Average(NodeList nl)
                   
{
                   
double nSum = 0;
                   

                
for (int i = nl.getLength() - 1; i >= 0; i--)
{
                   
	nSum += 
                   
	Double.valueOf(nl.item(i).
                   
	getNodeValue()).doubleValue();
                   
}
                   
return new Double(nSum / nl.getLength());
                   
}
                   

                
}

Working with XPath Data Types

The XPath types Boolean and Number can map either to the corresponding Java primitive types or to the corresponding Java object types. If the XPath processor is looking for a function that accepts XPath parameters 3.2 and true, it looks first for a function that accepts (double, boolean) and then (Double, Boolean). Functions that accept some combination of primitive types and object types are not recognized by the XPath processor.

The XPath processor determines the actual return type of a function at run time. For example, the XPath processor treats the return type of the function in the preceding section as an XPath Number because the object it returns is an instance of the Java class Double. You must declare all functions to return type Object, regardless of the actual type of the return value.

Declaring an Extension Function Namespace

In conformance with the XSLT specification, extension functions are accessed through a unique namespace. The namespace declaration can be in any of the following locations:

  • xsl:stylesheet tag
  • Element that contains the XPath expression that invokes the extension function
  • Ancestor of the element that contains the XPath expression that invokes the extension function

The XPath processor treats the namespace URI as a fully qualified class name. If the class name is preceded by class:, all calls are to static methods only. Otherwise, an instance of the class is created on first use and released when stylesheet processing is complete. Performance is better when you use a static method because creation and deletion of an instance of the class is not required.

You can separate package names with either a dot ( .) or a forward slash ( /). An sample namespace declaration might look like the following:

<xsl:stylesheet xmlns:Ext="NumberUtils">
       

    

The XPath processor resolves namespace prefixes in names of extension functions relative to the namespace declarations in the stylesheet.

Invoking Extension Functions

You use XSLT extension functions just like built-in XPath functions. For example:

<xsl:value-of select="Ext:Average(portfolio/stocks/last)"/>
               

            

Finding Classes and Finding Java

The XPath processor looks for extension classes by using the CLASSPATH environment variable. Ensure that your CLASSPATH references any directories or .jar files that contain extension classes.

The XPath processor tries to load the Sun Java Runtime Environment (JRE) 1.4.x or later. If the XPath processor cannot find a suitable JRE, invoking Java extension functions causes an error during stylesheet processing.

In Stylus Studio, classes are reloaded each time you refresh the preview output, so changes in a class are reflected in subsequent preview output.

Debugging Stylesheets That Contain Extension Functions

 

Support for extensions debugging is available only in Stylus Studio XML Professional Edition.

You can use Stylus Studio backmapping and debugging features on stylesheets tht invoke extension functions. You must process the stylesheet with one of the following processors:

  • Built-in Stylus Studio XSLT processor
  • Xalan-J XSLT processor
  • Saxon processor

The Xalan-J and Saxon processors do not allow you to step into JavaScript extensions. You can step into Java extensions, however.

 
Free Stylus Studio XML Training: