Xalan 2.7 中缺少字符串函数,改用 java.lang.String 吗?

Posted

技术标签:

【中文标题】Xalan 2.7 中缺少字符串函数,改用 java.lang.String 吗?【英文标题】:String functions missing in Xalan 2.7, java.lang.String used instead? 【发布时间】:2011-04-08 09:54:54 【问题描述】:

我正在使用 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)

现在这很奇怪!为什么 Xalan 会在 java.lang.String 上寻找 stringLength 函数?我测试了<xsl:value-of select="fn:substring('foobar', 2, 3)"/>,确实:结果是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 为什么要这样做?我该如何解决?

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

更新

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

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

这里出了点问题,显然不是关于 XPath 1.0 与 2.0...

【问题讨论】:

好问题 (+1)。请参阅我的答案以获得解释。 您为前缀 fn: 使用什么命名空间?当您使用<xsl:value-of select="string-length('foobar')"/>(即string-length() 上没有命名空间前缀)时,它是否仍然给出NoSuchMethodException? LarsH: 命名空间是w3.org/2005/02/xpath-functions,但正如 Alejandro 在下面写的,我必须省略 fn: 前缀。谢谢! @Jens-Bannmann、@LarsH、@Alejandro、@Mads-Hansen:有人对@Mads-Hansen 和我的答案投了反对票——这两个答案都是正确的?!?让我们至少解释一下投票失败的原因。如果 OP 一夜之间在他最初的问题中添加了新问题,我们应该醒来发现我们的正确答案被否决了吗? @Dimitre:+1 唤醒评论!奇怪的事情发生在 SO... 至少我们将 XSL 标记保持为 XSLT 标记的同义词。 【参考方案1】:

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

你可以用template like this from @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 模式用于“查找”表达式。

【讨论】:

【参考方案2】:

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

<xsl:value-of 
   select="java:replaceAll(java:java.lang.String.new(ContactInfo/telephone/text()),'[^0-9]','')"/>

【讨论】:

【参考方案3】:

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

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

如果 FunctionCall 中的 FunctionName 表达式不是 NCName(即,如果 它包含一个冒号),那么它是 被视为对分机的呼叫 功能。 FunctionName 展开 使用命名空间的名称 评估声明 上下文。

【讨论】:

【参考方案4】:

现在这很奇怪!为什么Xalan看起来 对于 stringLength 函数 java.lang.String?我测试过 ,而且确实:结果是 o,所以 参数被用作 startIndex, endIndex(如 java.lang.String.substring()) 代替 XPath 的 fn:substring(string, start, 长度)函数。

所以我认为 Xalan 在某种程度上 缺少它的 XPath 函数库和 使用常规 String 类 反而。我通过致电确认了这一点 不存在的功能 fn:index-of('foobar', 'bar') 其中 工作正常并映射到 java.lang.String.indexOf(str).

Xalan 为什么要这样做?我怎么能 修好吗?

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

    我该如何解决它?通过使用 XSLT 2.0 处理器,如 Saxon 9.xAltovaXML2010。或者编写一个命名的递归 &lt;xsl:template&gt; 在 XSLT 1.0 中进行简单的替换。

【讨论】:

以上是关于Xalan 2.7 中缺少字符串函数,改用 java.lang.String 吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何防止具有 META-INF\services\javax.xml.transform.TransformerFactory 的 xalan.jar 接管 Xalan 实现中内置的 JDK 1.6?

将 Xalan 与 Saxon 一起使用

如何将字符串中的数字转换为 python 2.7 中的完整函数?

Python 2.7 fnmatch 不编辑文本

寻找 xalan TransformerFactoryImpl 的选项

Java 中是不是有比 Xalan/Xerces 更快的 XML 解析器 [关闭]