91

我不太了解 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>

谁能告诉我它有什么问题?

4

6 回答 6

157

replace不适用于 XSLT 1.0。

Codesling 有一个用于字符串替换的模板,您可以将其用作该函数的替代品:

<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原始代码中相同的操作。

于 2010-06-18T03:58:48.003 回答
40

这是 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>

您也可以参考以下网址了解详情。

于 2012-05-10T06:58:25.697 回答
14

注意:如果您希望在需要替换源字符串中的大量实例(例如长文本中的新行)的情况下使用已经提到的算法,那么您很可能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>
于 2012-09-11T07:37:32.510 回答
7

当您的处理器在 .NET Framework 上运行(.NET Core 或 .NET 5 不支持)或使用 MSXML(相对于基于 Java 或其他本机处理器)时,您可以使用以下代码。它使用msxsl:script.

确保将命名空间添加xmlns:msxsl="urn:schemas-microsoft-com:xslt"到您的根xsl:stylesheetxsl: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')" />
于 2013-03-28T00:35:59.967 回答
7

我一直在打这个答案。但是它们都没有列出 xsltproc 最简单的解决方案(可能是大多数 XSLT 1.0 处理器):

  1. 将 exslt 字符串名称添加到样式表中,即:
<xsl:stylesheet
  version="1.0"
  xmlns:str="http://exslt.org/strings"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  1. 然后像这样使用它:
<xsl:value-of select="str:replace(., ' ', '')"/>
于 2020-01-19T22:45:56.687 回答
0

常规非常好,但是它导致我的应用程序挂起,所以我需要添加案例:

  <xsl:when test="$text = '' or $replace = ''or not($replace)" >
    <xsl:value-of select="$text" />
    <!-- Prevent thsi routine from hanging -->
  </xsl:when>

在函数被递归调用之前。

我从这里得到了答案: 当测试挂在无限循环中时

谢谢!

于 2016-01-08T20:15:27.550 回答