在XSLT中调用Java实例方法

8

我正在使用Saxon(如果需要,也可以使用Xalan)XSLT处理器进行一些转换。 我想将下面的对象实例作为参数传递给XSLT模板。

public class Test {
   private String value;

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

所以我创建了这个对象,即。
Test test = new Test("test");
transformer.setParameter("test", test);

在XSLT文件中,我将参数声明为:
<xsl:param name="test" required="yes" as="jt:com.whatever.package.Test" xmlns:jt="http://saxon.sf.net/java-type"/>

现在我的问题是如何在XSLT中调用任何实例方法(即getValue())来操作这个对象?这是否可能?我知道我可以调用不同Java类的静态方法,但那并不是我要找的。

另外,在XSLT中是否有可能填充Java对象,即调用对象实例的setter方法,然后在转换完成后在Java代码中使用具有新值的此对象?


你使用的Saxon版本是哪个? - Martin Honnen
这里的“确切”非常关键。例如,Saxon-B 9.1和Saxon-HE 9.4的答案是不同的。 - Michael Kay
4个回答

7
您应该能够按照您描述的方式调用作为参数传递的“外部对象”的实例方法。如果$object是这样的一个对象,com.package.MyClass是它的类,并且您想要在此对象上调用getColor()方法,则需要:
(a)声明命名空间,例如xmlns:MyClass="java:com.package.MyClass" (b)将方法调用为MyClass:getColor($object) 在Saxon中,称之为“反射扩展函数”的调用Java机制不受Saxon Home Edition支持。您需要使用Saxon Professional Edition或旧版的开源Saxon-B产品。Saxon-HE还有另一种称为“集成扩展函数”的机制,但需要在Java方面编写更多代码来声明参数和结果的类型。
您需要知道的是,在反射扩展函数中,Saxon正在尽力猜测如何将Java类型映射到XPath类型,并且它并不总是以您希望的方式进行映射,特别是在使用集合类型时。
尽量避免使用具有副作用的方法,例如setter方法。在Saxon中,没有绝对可靠的方法可以确保此类调用按任何特定顺序执行,有时Saxon优化器会找到一种组织查询的方法,避免完全进行调用。如果必须进行此类调用,请将其视为调用返回结果(例如空序列)并以这种方式使用调用,如果它确实返回结果,则结果将出现在您的样式表输出中。

3

这里有详细的解释:

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

一个简短的例子:

<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>

应用于任何XML文档(未使用)时,会产生所需的正确结果:
<html>
   <p>Sat Oct 06 11:41:30 PDT 2012</p>
</html>

+1并附注给OP:您还可以将extension-element-prefixes="date"添加到xsl:stylesheet中,这样就不会在输出中得到xmlns:date="java:java.util.Date" - Daniel Haley
1
虽然"extension-element-prefixes"会产生那种效果,但它并不是正确的工具:应该使用的正确属性是"exclude-result-prefixes"。 - Michael Kay

2

我很久以前使用Xalan完成了这个。首先,您需要将以下内容添加到您的xslt中(我认为您不需要放置所有其他属性)。

<xsl:param name="test" />

然后,要调用该方法,您可以执行以下操作

<xsl:value-of select="test:getValue()"/>

它在Saxon上无法工作(显示Undeclared namespace prefix {test})。我会安装Xalan并尝试在那里运行。虽然Saxon支持xslt2,但我仍然更喜欢使用它。谢谢。 - Zyga
我尝试使用Xalan来实现,但它显示“命名空间前缀'test'未声明”。 - Grief

0

虽然我现在才回复,但对其他人可能会有帮助。

你可以通过使用Xalan处理器轻松实现这一点:

步骤1:包含Xalan依赖项或相关的适当jar文件

<!-- https://mvnrepository.com/artifact/xalan/xalan -->
 <dependency>
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
<version>2.7.1</version>
</dependency>

步骤2. 在与Java集成时选择此处理器

TransformerFactory factory = TransformerFactory.newInstance("org.apache.xalan.processor.TransformerFactoryImpl",null);

步骤3. 在您的XSL中,将信息输入样式表

xmlns:uuid="xalan://PackageName.className"

请注意,这个类应该有一个静态方法,你将在xslt中使用它。
第四步:在你的xslt中使用它。
<xsl:value-of select="uuid:methodName(string(xpath))" />

它可以是字符串或数字,具体取决于您的方法参数。

来源:http://www.cafeconleche.org/books/xmljava/chapters/ch17s03.html


问题是关于实例方法,而不是静态方法。 - Grief

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接