Call Java instance methods in XSLT

Zyga picture Zyga · Oct 6, 2012 · Viewed 28.9k times · Source

I am using Saxon (I could use Xalan if necessary) XSLT processor to do some transformation. I want to pass the instance of below object to the XSLT template as parameter.

public class Test {
   private String value;

   public Test(String v) {
       value = v;
   }
   //getters, setters etc.
}

So I create this object, ie.

Test test = new Test("test");
transformer.setParameter("test", test);

In XSLT file I declare the param as:

<xsl:param name="test" required="yes" as="jt:com.whatever.package.Test" xmlns:jt="http://saxon.sf.net/java-type"/>

Now my question is how can I call any instance method (ie. getValue() ) on this object within XSLT? Is it even possible? I know i can call static methods of different Java classes but thats not exactly what Im looking for.

Also, is it possible to populate Java objects within XSLT, ie. call setter methods for instance of an object and then use this object with new values in Java code after the transformation is completed?

Answer

Michael Kay picture Michael Kay · Oct 7, 2012

You should be able to call instance methods of an "external object" passed in as a parameter in the way you describe. If $object is such an object, and com.package.MyClass is its class, and you want to call the method getColor on this object, then

(a) you need to declare a namespace, such as xmlns:MyClass="java:com.package.MyClass"

(b) you call the method as MyClass:getColor($object)

This mechanism for calling out to Java is referred to in Saxon as "reflexive extension functions". It's not supported in the Saxon Home Edition. You will need either the Saxon Professional Edition, or the old open-source Saxon-B product. There's another mechanism in Saxon-HE called "integrated extension functions", but it requires a bit more coding on the Java side to declare the types of the arguments and result.

You need to be aware that with reflexive extension functions, Saxon is making best guesses as to how to map Java types to XPath types, and it doesn't always do the mapping in the way you would want, especially when using collection types.

Try to avoid using methods with side-effects, such as setter methods. There's no absolutely reliable way of ensuring in Saxon that such calls are executed in any particular order, and sometimes the Saxon optimizer will find a way of organizing the query that avoids making the call at all. If you must make such calls, treat them as if the call were returning a result (such as an empty sequence) and use the call in such a way that if it did return a result, the result would appear in your stylesheet output.