Usando funções externas declaradas na folha de estilo com XSLT

Como alternativa para ligar métodos Java™ a funções em uma folha de estilo usando a API, as funções externas Java podem ser declaradas diretamente dentro de uma folha de estilo. A única configuração adicional necessária é que classes Java ligadas existam no caminho de classe durante a execução da folha de estilo.

Procedimento

Usando o elemento java-extension, é possível ligar um prefixo a uma classe Java.
<xltxe:java-extension
prefix = string
class = string /> 
Nota: Qualquer nome de prefixo pode ser usado para o elemento java-extension, desde que ele esteja ligado ao namespace http://www.ibm.com/xmlns/prod/xltxe-j .
Após ligar um prefixo a uma classe Java, os métodos dentro da classe de limite podem ser chamados especificando o prefixo e o nome do método separados por dois pontos:
prefix:methodName(Params*)

Exemplo

Chamando métodos estáticos

Ao preparar uma folha de estilo XSLT que usa funções externas declaradas pela folha de estilo, declare o prefixo para a ligação de classe Java:
<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>
Supondo que essa folha de estilo esteja disponível por meio do objeto xsltSource Source, o código a seguir prepara a folha de estilo:
// Create the factory
XFactory factory = XFactory.newInstance();

// Create an XSLT executable for the stylesheet
XSLTExecutable executable = factory.prepareXSLT(xsltSource);
O código a seguir executa a folha de estilo que foi preparada no exemplo:
// 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);

A folha de estilo de exemplo fornecida supõe que a classe org.company.Calculator contém um método estático sqrt() que leva um parâmetro e a classe org.standards.Formatter contém um método estático format() que leva dois parâmetros. No momento do preparo, as classes não são necessárias no caminho de classe, mas são necessárias durante a execução da folha de estilo.

A seguir estão exemplos de implementações das classes org.company.Calculator e org.standards.Formatter:
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

Chamar métodos de instância de uma classe é um pouco diferente de chamar métodos estáticos devido a necessidade de um objeto de instância. Para obter um objeto de instância de uma classe Java dentro de uma folha de estilo, você deve chamar seu novo construtor:
prefix:new(Params*)
Em seguida, é possível armazenar o resultado em um elemento xsl:variable conforme demonstrado pela folha de estilo a seguir:
<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>
Supondo que essa folha de estilo esteja disponível por meio do objeto xsltSource Source, o código a seguir prepara a folha de estilo.
// Create the factory
XFactory factory = XFactory.newInstance();

// Create an XSLT executable for the stylesheet
XSLTExecutable executable = factory.prepareXSLT(xsltSource);
O código a seguir executa a folha de estilo preparada no exemplo:
// 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);

A folha de estilo de exemplo supõe que a classe org.automobile.Car contém uma construtora que leva um argumento do tipo int. Além disso, a classe org.automobile.Car também contém um método de instância getDoors() que não aceita argumentos. A sintaxe para chamar métodos de instância por meio de funções externas declaradas na folha de estilo requer que o objeto de instância criado seja transmitido como o primeiro argumento.

A seguir está um exemplo de implementação da classe org.automobile.Car:
package org.automobile;

public class Car {
    private int doors;
	
    public Car (int doors) {
        this.doors = doors;
    }
	
    public int getDoors() {
        return doors;
    }
}
Herança com métodos de instância também é suportada. Se a classe org.automobile.Car possui uma subclasse org.automobile.Sedan, é possível criar uma instância da classe org.automobile.Sedan e usá-la para chamar métodos em org.automobile.Car. Isto é demonstrado pela folha de estilo a seguir:
<?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>
A seguir está um exemplo de implementação para org.automobile.Sedan:
package org.automobile;

public class Sedan extends Car {
    public Sedan (int doors) {
        super(doors);
    }
}
Limitação: O mecanismo usado para resolver métodos em uma classe Java requer que exista apenas um método, correspondente em nome e aridade. Se houver vários métodos com o mesmo nome e aridade diferente, um erro será lançado.