【问题标题】:Call Java instance methods in XSLT在 XSLT 中调用 Java 实例方法
【发布时间】:2012-09-27 12:35:02
【问题描述】:

我正在使用 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?
  • “完全正确”在这里很关键。例如,Saxon-B 9.1 的答案与 Saxon-HE 9.4 的答案不同。

标签: java xslt saxon


【解决方案1】:

您应该能够以您描述的方式调用作为参数传入的“外部对象”的实例方法。如果$object是这样一个对象,com.package.MyClass是它的类,并且你想在这个对象上调用getColor()方法,那么

(a) 你需要声明一个命名空间,比如xmlns:MyClass="java:com.package.MyClass"

(b) 你把方法称为MyClass:getColor($object)

这种调用 Java 的机制在 Saxon 中称为“自反扩展函数”。 Saxon Home Edition 不支持它。您将需要 Saxon Professional Edition 或旧的开源 Saxon-B 产品。 Saxon-HE 中还有一种称为“集成扩展函数”的机制,但它需要在 Java 端进行更多编码来声明参数和结果的类型。

您需要注意,对于自反扩展函数,Saxon 对如何将 Java 类型映射到 XPath 类型做出了最好的猜测,而且它并不总是按照您想要的方式进行映射,尤其是在使用集合时类型。

尽量避免使用有副作用的方法,例如 setter 方法。在 Saxon 中没有绝对可靠的方法可以确保此类调用以任何特定顺序执行,有时 Saxon 优化器会找到一种组织查询的方法,从而完全避免调用。如果您必须进行此类调用,请将它们视为调用返回结果(例如空序列)并以这样的方式使用调用:如果确实返回结果,结果将出现在您的样式表输出中。

【讨论】:

    【解决方案2】:

    这里详细解释了

    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"
    • 虽然 extension-element-prefixes 会产生这种效果,但它是错误的工作工具:要使用的正确属性是 exclude-result-prefixes。
    【解决方案3】:

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

    <xsl:param name="test" />
    

    然后,要调用该方法,您可以这样做

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

    【讨论】:

    • 它不适用于撒克逊语(如未声明的命名空间前缀 {test})。我将安装 Xalan 并在那里尝试。 Saxon 首选,因为它支持 xslt2。谢谢
    • 我尝试使用 Xalan 执行此操作,但它显示“未声明命名空间前缀 'test'。”
    【解决方案4】:

    我发帖为时已晚,但对其他人可能会有所帮助。

    借助 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 中使用的静态方法

    第 4 步:在您的 xslt 中使用它

    <xsl:value-of select="uuid:methodName(string(xpath))" />
    

    它可以是字符串或数字..取决于你的方法参数

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

    【讨论】:

    • 问题是关于实例方法,而不是静态方法
    猜你喜欢
    • 1970-01-01
    • 2013-10-01
    • 1970-01-01
    • 2021-08-03
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多