Call Java instance methods in XSLT

30,865

Solution 1

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.

Solution 2

This is thoroughly explained here:

http://www.saxonica.com/html/documentation/extensibility/functions/

A short example:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:date="java:java.util.Date" exclude-result-prefixes="date">

<xsl:template match="/">
  <html>
    <xsl:if test="function-available('date:to-string') and
                          function-available('date:new')">
      <p><xsl:value-of select="date:to-string(date:new())"/></p>
    </xsl:if>
  </html>
</xsl:template>

</xsl:stylesheet>

when applied on any XML document (not used) produces the wanted, correct result:

<html>
   <p>Sat Oct 06 11:41:30 PDT 2012</p>
</html>

Solution 3

I've done this long time ago using Xalan. First, you need to add the following to your xslt (I don't think you need all the other attributes you put)

<xsl:param name="test" />

and then, to call the method, you can do

<xsl:value-of select="test:getValue()"/>
Share:
30,865
Zyga
Author by

Zyga

Updated on July 21, 2021

Comments

  • Zyga
    Zyga almost 3 years

    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?

  • Zyga
    Zyga over 11 years
    Its not working with Saxon (says Undeclared namespace prefix {test}). I will install Xalan and try it there though. Saxon preferred as it supports xslt2. Thanks
  • Daniel Haley
    Daniel Haley over 11 years
    +1 and a note to the OP: You can also add extension-element-prefixes="date" to xsl:stylesheet so you don't get the xmlns:date="java:java.util.Date" in the output.
  • Michael Kay
    Michael Kay over 11 years
    While extension-element-prefixes will have that effect, it's the wrong tool for the job: the correct attribute to use is exclude-result-prefixes.
  • Grief
    Grief over 6 years
    The question was about instance method, not static methods
  • Grief
    Grief over 6 years
    I tried to do that with Xalan, but it says 'Namespace prefix 'test' is undeclared.'