Xalan 2.7中缺少字符串函数,而是使用了java.lang.String?

时间:2010-09-05 08:44:51

标签: function xpath xalan xslt

我正在使用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在stringLength上寻找java.lang.String函数?我测试了<xsl:value-of select="fn:substring('foobar', 2, 3)"/>,确实:结果是o,因此参数用作startIndex, endIndex(如java.lang.String.substring())而不是XPath的fn:substring(string, start, length)函数。< / p>

所以我认为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的子字符串方法是巧合吗?

当我使用fn:string-length函数时,为什么会出现NoSuchMethodError?

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

4 个答案:

答案 0 :(得分:7)

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模式作为“find”表达式。

答案 1 :(得分:4)

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

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

答案 2 :(得分:3)

substring('foobar', 2, 3)请注意:无名称空间)的结果应为oob

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

  

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

答案 3 :(得分:1)

  

现在这很奇怪!为什么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会这样做?我怎么能   解决它?

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

  2. 我该如何解决??使用XSLT 2.0处理器,如 Saxon 9.x AltovaXML2010 。或者编写一个命名的递归<xsl:template>来在XSLT 1.0中进行简单的替换。