我不太了解 XSL,但我需要修复此代码,我已对其进行了简化以使其更简单。我收到此错误
无效的 XSLT/XPath 函数
在这条线上
<xsl:variable name="text" select="replace($text,'a','b')"/>
这是 XSL
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:inm="http://www.inmagic.com/webpublisher/query" version="1.0">
<xsl:output method="text" encoding="UTF-8" />
<xsl:preserve-space elements="*" />
<xsl:template match="text()" />
<xsl:template match="mos">
<xsl:apply-templates />
<xsl:for-each select="mosObj">
'Notes or subject'
<xsl:call-template
name="rem-html">
<xsl:with-param name="text" select="SBS_ABSTRACT" />
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="rem-html">
<xsl:param name="text" />
<xsl:variable name="text" select="replace($text, 'a', 'b')" />
</xsl:template>
</xsl:stylesheet>
谁能告诉我它有什么问题?
replace()
函数从 XPath 2.0(因此 XSLT 2.0)开始可用,并且支持正则表达式替换。
replace
不适用于 XSLT 1.0。
Codesling 有一个 template for string-replace,您可以使用它来替代该函数:
<xsl:template name="string-replace-all">
<xsl:param name="text" />
<xsl:param name="replace" />
<xsl:param name="by" />
<xsl:choose>
<xsl:when test="$text = '' or $replace = ''or not($replace)" >
<!-- Prevent this routine from hanging -->
<xsl:value-of select="$text" />
</xsl:when>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text,$replace)" />
<xsl:value-of select="$by" />
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="substring-after($text,$replace)" />
<xsl:with-param name="replace" select="$replace" />
<xsl:with-param name="by" select="$by" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
调用为:
<xsl:variable name="newtext">
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="$text" />
<xsl:with-param name="replace" select="a" />
<xsl:with-param name="by" select="b" />
</xsl:call-template>
</xsl:variable>
另一方面,如果您实际上只需要用另一个字符替换一个字符,则可以调用具有相似签名的 translate
。这样的事情应该可以正常工作:
<xsl:variable name="newtext" select="translate($text,'a','b')"/>
另外,请注意,在此示例中,我将变量名称更改为“newtext”,在 XSLT 中变量是不可变的,因此您不能像在原始代码中那样执行 $foo = $foo
的等效操作。
这是 XSLT 函数,其工作方式类似于 C# 的 String.Replace() 函数。
该模板具有以下 3 个参数
text :- 你的主要字符串
replace :- 要替换的字符串
by :- 将由新字符串回复的字符串
下面是模板
<xsl:template name="string-replace-all">
<xsl:param name="text" />
<xsl:param name="replace" />
<xsl:param name="by" />
<xsl:choose>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text,$replace)" />
<xsl:value-of select="$by" />
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="substring-after($text,$replace)" />
<xsl:with-param name="replace" select="$replace" />
<xsl:with-param name="by" select="$by" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
下面的示例显示了如何调用它
<xsl:variable name="myVariable ">
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="'This is a {old} text'" />
<xsl:with-param name="replace" select="'{old}'" />
<xsl:with-param name="by" select="'New'" />
</xsl:call-template>
</xsl:variable>
您也可以参考 below URL 了解详细信息。
注意:如果您希望在需要替换源字符串中大量实例(例如长文本中的新行)的情况下使用已经提到的算法,则 high< /em> 由于递归调用,您最终会得到 StackOverflowException
的可能性。
我解决了这个问题,这要归功于 Xalan(在 Saxon 中没有看到如何做)内置的 Java 类型嵌入:
<xsl:stylesheet version="1.0" exclude-result-prefixes="xalan str"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xalan="http://xml.apache.org/xalan"
xmlns:str="xalan://java.lang.String"
>
...
<xsl:value-of select="str:replaceAll(
str:new(text()),
$search_string,
$replace_string)"/>
...
</xsl:stylesheet>
Cannot find a script or an extension object associated with namespace 'xalan://java.lang.String'.
<msxsl:script>
块将它与 .NET 一起使用,该块可以调用任何 .NET 方法、库等。虽然 .NET 也支持 EXSLT 扩展功能,所以您不需要。
我一直在打这个答案。但是它们都没有列出 xsltproc 最简单的解决方案(可能是大多数 XSLT 1.0 处理器):
将 exslt 字符串名称添加到样式表中,即:
<xsl:stylesheet
version="1.0"
xmlns:str="http://exslt.org/strings"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
然后像这样使用它:
<xsl:value-of select="str:replace(., ' ', '')"/>
str:replace()
功能。其他任何主要的 XSLT 1.0 处理器(Xalan、Saxon 6.5 和 Microsoft)也没有。
当您的处理器在 .NET Framework (.NET Core 或 .NET 5 上不支持) 或使用 MSXML(相对于基于 Java 或其他本机处理器)上运行时,您可以使用以下代码。它使用 msxsl:script
。
确保将命名空间 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
添加到您的根 xsl:stylesheet
或 xsl:transform
元素。
此外,将 outlet
绑定到您喜欢的任何命名空间,例如 xmlns:outlet = "http://my.functions"
。
<msxsl:script implements-prefix="outlet" language="javascript">
function replace_str(str_text,str_replace,str_by)
{
return str_text.replace(str_replace,str_by);
}
</msxsl:script>
<xsl:variable name="newtext" select="outlet:replace_str(string(@oldstring),'me','you')" />
prefix outlet is not defined
或 'xsl:script' cannot be a child of the 'xsl:stylesheet' element.
。我猜这是微软特有的 XSLT 魔法?
xsl:script
,而是 msxsl:script
,并且它具有不同的命名空间(我已经更新了 John 的答案)。
常规非常好,但是它导致我的应用程序挂起,所以我需要添加案例:
<xsl:when test="$text = '' or $replace = ''or not($replace)" >
<xsl:value-of select="$text" />
<!-- Prevent thsi routine from hanging -->
</xsl:when>
在函数被递归调用之前。
我从这里得到了答案:When test hanging in an infinite loop
谢谢!
translate
,而不是replace
。 XPath 2.0 中的replace
函数将其第二个参数视为 正则表达式,并将该表达式的所有匹配项替换为指定的替换字符串(其中可能包括$n
对正则表达式中捕获组的引用) .translate
函数(在 1.0 和 2.0 中)是执行单字符替换单字符的函数。<xsl:with-param name="replace" select="'a'" />
并在 a 周围加上引号吗?