WAS v8.5 > Develop applications > XML applications > Use the XML API to perform operations > Use external variables and functions > Use external functions > Use external functions with XSLT

Use stylesheet-declared external functions with XSLT

As an alternative to binding Java methods to functions in a stylesheet using the API, Java external functions can be declared directly within a stylesheet. The only additional configuration required is for bound Java classes to exist on the classpath during stylesheet execution.

Using the java-extension element, we can bind a prefix to a Java class.

<xltxe:java-extension
prefix = string
class = string /> 

Any prefix name can be used for the java-extension element as long as it is bound to the http://www.ibm.com/xmlns/prod/xltxe-j namespace.

After binding a prefix to a Java class, methods within the bound class can be invoked by specifying the prefix and method name separated by a colon:


Example

Invoking Static Methods

When preparing an XSLT stylesheet that uses stylesheet-declared external functions, declare the prefix to Java class binding:

<xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:xltxe="http://www.ibm.com/xmlns/prod/xltxe-j"
     xmlns:calc="http://com.example/myApp/calculator"
     xmlns:sf="http://com.example/myApp/standardFormat">  
<xltxe:java-extension prefix="calc" class="org.company.Calculator"/> <xltxe:java-extension prefix="sf" class="org.standards.Formatter"/>  
<xsl:template match="/">      <xsl:value-of select="sf:format(calc:sqrt(64), 'ISO-42.7')"/> </xsl:template> 
</xsl:stylesheet>

Assuming that this stylesheet is available through the xsltSource Source object, the following code prepares the stylesheet:

// Create the factory
XFactory factory = XFactory.newInstance();

// Create an XSLT executable for the stylesheet
XSLTExecutable executable = factory.prepareXSLT(xsltSource);

The following code executes the stylesheet that was prepared in the example:

// Create the xml input
String xml = "<doc/>";

// Create a result object to store the transformation result Result result = new StreamResult(System.out);

// Execute the XSLT executable
executable.execute(new StreamSource(new ByteArrayInputStream(xml.getBytes())), result);

The example stylesheet provided assumes the org.company.Calculator class contains a static method sqrt() that takes one parameter and the org.standards.Formatter class contains a static method format() that takes two parameters. At prepare time, the classes are not required on the classpath; but they are required during execution of the stylesheet.

The following are example implementations of the org.company.Calculator and org.standards.Formatter classes:

package org.company;

public class Calculator {
    public static int sqrt(int val) {
        return (int)Math.sqrt(val);
    }}
package org.standards;

public class Formatter {
    public static String format(int val, String pattern) {
        return "Formatting " + val + " using pattern " + pattern;
    }}

Invoking Instance Methods

Invoking instance methods from a class is slightly different from invoking static methods because of the requirement for an instance object. To obtain an instance object from a Java class within a stylesheet, you must invoke its new constructor:

We can then store the result in an xsl:variable element as demonstrated by the following stylesheet:

<xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:xltxe="http://www.ibm.com/xmlns/prod/xltxe-j"
     xmlns:car="http://com.example/myApp/car">  
<xltxe:java-extension prefix="car" class="org.automobile.Car"/> 
<xsl:variable name="var" select="car:new(3)"/>  
<xsl:template match="/">      <xsl:value-of select="car:getDoors($var)"/> </xsl:template> 
</xsl:stylesheet>

Assuming that this stylesheet is available through the xsltSource Source object, the following code prepares the stylesheet.

// Create the factory
XFactory factory = XFactory.newInstance();

// Create an XSLT executable for the stylesheet
XSLTExecutable executable = factory.prepareXSLT(xsltSource);

The following code executes the stylesheet prepared in the example:

// Create the xml input
String xml = "<doc/>";

// Create a result object to store the transformation result Result result = new StreamResult(System.out);

// Execute the XSLT executable
executable.execute(new StreamSource(new ByteArrayInputStream(xml.getBytes())), result);

The example stylesheet assumes the org.automobile.Car class contains a constructor that takes an argument of type int. In addition, the org.automobile.Car class also contains an instance method getDoors() that takes no arguments. The syntax for invoking instance methods from stylesheet-declared external functions require the created instance object be passed in as the first argument.

The following is an example implementation of the org.automobile.Car class:

package org.automobile;

public class Car {
    private int doors;
 
    public Car (int doors) {
        this.doors = doors;
    }
 
    public int getDoors() {
        return doors;
    }}

Inheritance with instance methods is also supported. If the org.automobile.Car class has a subclass org.automobile.Sedan, we can create an instance of the org.automobile.Sedan class and use it to call methods in org.automobile.Car. This is demonstrated by the following stylesheet:

<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:xltxe="http://www.ibm.com/xmlns/prod/xltxe-j"
     xmlns:sedan="http://com.example/myApp/sedan"
     xmlns:car="http://com.example/myApp/car">  
<xltxe:java-extension prefix="sedan" class="org.automobile.Sedan"/> <xltxe:java-extension prefix="car" class="org.automobile.Car"/> 
<xsl:variable name="var" select="sedan:new(5)"/>  
<xsl:template match="/">      <xsl:value-of select="car:getDoors($var)"/> </xsl:template> 
</xsl:stylesheet>

The following is an example implementation for org.automobile.Sedan:

package org.automobile;

public class Sedan extends Car {
    public Sedan (int doors) {
        super(doors);
    }}

Limitation: The mechanism used for resolving methods in a Java class requires that only one method exists, matching in name and arity. If multiple methods exist with the same name and different arity, an error is thrown.


Related


Use external functions with XSLT


+

Search Tips   |   Advanced Search