5

我正在使用 Xalan 2.7.0(与 Apache FOP 1.0 捆绑在一起)并且在使用字符串函数时遇到问题。

该行<xsl:value-of select="fn:replace('test', 't', '*')"/>导致此异常:

javax.xml.transform.TransformerException: java.lang.IllegalArgumentException: argument type mismatch
    at org.apache.fop.cli.InputHandler.transformTo(InputHandler.java:302)

<xsl:value-of select="fn:string-length('foobar')"/>结果是:

javax.xml.transform.TransformerException: java.lang.NoSuchMethodException: For extension function, could not find method java.lang.String.stringLength([ExpressionContext,] ).
    at org.apache.fop.cli.InputHandler.transformTo(InputHandler.java:302)

现在这很奇怪!为什么 XalanstringLength在 上寻找函数java.lang.String?我测试<xsl:value-of select="fn:substring('foobar', 2, 3)"/>了 ,确实:结果是o,所以参数被用作startIndex, endIndex(like java.lang.String.substring()) 而不是 XPath 的函数fn:substring(string, start, length)

所以我认为 Xalan 不知何故缺少它的 XPath 函数库,而是使用常规的 String 类。我通过调用不存在的函数来确认这一点,该函数fn:index-of('foobar', 'bar')可以正常工作并映射到java.lang.String.indexOf(str).

为什么 Xalan 会这样做?我该如何解决?

系统信息:Xalan 使用标准的 Mac OS X 10.6.4 Java 版本,1.6.0_20。

更新

好的,暂时先搁置该replace()功能。作为 XSLT 1.0 处理器的 Xalan 不应该实现XPath 1.0 函数子字符串 (string, startIndex, length)而不是(string, startIndex, endIndex)我在过期时看到的函数吗?这个 startIndex、endIndex 函数看起来像 的 substring 方法是巧合java.lang.String吗?

为什么我在使用该fn:string-length函数时会收到 NoSuchMethodError?

这里出了点问题,显然与 XPath 1.0 与 2.0 无关……

4

4 回答 4

8

replace()是一个XSLT 2.0函数。 Xalan是一个XSLT 1.0处理器。

您可以使用来自 @Ektron Doug D的模板模拟 replace() 函数:

<xsl:template name="replace-substring">
<xsl:param name="original"/>
<xsl:param name="substring"/>
<xsl:param name="replacement" select="''"/>
<xsl:choose>
    <xsl:when test="contains($original, $substring)">
        <xsl:value-of select="substring-before($original, $substring)"/>
        <xsl:copy-of select="$replacement"/>
        <xsl:call-template name="replace-substring">
            <xsl:with-param name="original" select="substring-after($original, $substring)"/>
            <xsl:with-param name="substring" select="$substring"/>
            <xsl:with-param name="replacement" select="$replacement"/>
        </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="$original"/>
    </xsl:otherwise>
</xsl:choose>
</xsl:template>

请记住,这个 XSLT 1.0 解决方案是一个非常简单的查找/替换。XSLT 2.0 函数 replace() 可以将 REGEX 模式用于“查找”表达式。

于 2010-09-05T12:57:04.673 回答
4

当老 Xalan 是唯一的选择时,这个对我有用:

<xsl:value-of 
   select="java:replaceAll(java:java.lang.String.new(ContactInfo/telephone/text()),'[^0-9]','')"/>
于 2012-05-10T19:14:47.370 回答
3

substring('foobar', 2, 3)请注意:没有命名空间)的结果应该是oob.

在 XSLT 1.0 中,任何带有前缀的函数调用都将被解释为扩展调用。来自http://www.w3.org/TR/xslt#section-Extension-Functions

如果 FunctionCall 表达式中的 FunctionName 不是 NCName(即如果它包含冒号),则将其视为对扩展函数的调用。使用来自评估上下文的命名空间声明将 FunctionName 扩展为一个名称。

于 2010-09-05T21:32:07.460 回答
1

现在这很奇怪!为什么 Xalan 在 java.lang.String 上寻找 stringLength 函数?我测试了,确实:结果是 o,所以参数被用作 startIndex、endIndex(如 java.lang.String.substring())而不是 XPath 的 fn:substring(string, start, length) 函数。

所以我认为 Xalan 不知何故缺少它的 XPath 函数库,而是使用常规的 String 类。我通过调用不存在的函数 fn:index-of('foobar', 'bar') 确认了这一点,该函数工作正常并映射到 java.lang.String.indexOf(str)。

为什么 Xalan 会这样做?我该如何解决?

  1. 为什么 Xalan 这样做?因为 Xalan 是 XSLT 1.0 处理器,而任何兼容的 XSLT 1.0 处理器都只支持 XPath 1.0。replace()是 XPath 2.0 的标准功能,必须在任何兼容的 XSLT 2.0 处理器中实现。

  2. 我该如何解决?通过使用像Saxon 9.xAltovaXML2010这样的 XSLT 2.0 处理器。或者在 XSLT 1.0 中编写一个命名的递归<xsl:template>来做简单的替换。

于 2010-09-06T16:43:22.357 回答