我正在使用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 ......
答案 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会这样做?我怎么能 解决它?
为什么Xalan会这样做?因为Xalan是XSLT 1.0处理器,任何兼容的XSLT 1.0处理器只支持XPath 1.0。 replace()
是XPath 2.0的标准功能,必须在任何兼容的XSLT 2.0处理器中实现。
我该如何解决??使用XSLT 2.0处理器,如 Saxon 9.x 或 AltovaXML2010 。或者编写一个命名的递归<xsl:template>
来在XSLT 1.0中进行简单的替换。