search - XSL 多重搜索替换功能

标签 search xslt replace translate

我正在尝试使用 XSL translate() 函数来创建类似搜索和替换函数的内容,如下所示:

<xsl:template name="create-id">
    <xsl:param name="id" />
    <xsl:call-template name="search-and-replace">
        <xsl:with-param name="str" select="$id" />
        <xsl:with-param name="search">0123456789</xsl:with-param>
        <xsl:with-param name="replace">abcdefghij</xsl:with-param>
    </xsl:call-template>
</xsl:template>

<xsl:template name="search-and-replace">
    <xsl:param name="str" />
    <xsl:param name="search" />
    <xsl:param name="replace" />
    <xsl:variable name="newstr" select="translate($str, $search,
    $replace)" />
    <xsl:choose>
        <xsl:when test="contains($newstr, $search)">
            <xsl:call-template name="search-and-replace">
                <xsl:with-param name="str" select="$newstr" />
                <xsl:with-param name="search" select="$search" />
                <xsl:with-param name="replace" select="$replace" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$newstr" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

但是,我的逻辑在这里有问题,因为它似乎剥离了返回字符串中的最后一个字符。我的猜测是 translate() 只是替换字符串中每个字符的第一个实例,并不是真正的递归。

任何想法或意见将不胜感激。

最佳答案

translate() 函数只能将单个字符替换为另一个单个字符 (或空字符(删除))。因此它不能解决字符串替换的问题。

以下是针对多替换问题 的完整 XSLT 1.0 解决方案:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my">
    <xsl:output omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

    <my:params xml:space="preserve">
        <pattern>
            <old>&#xA;</old>
            <new><br/></new>
        </pattern>
        <pattern>
            <old>quick</old>
            <new>slow</new>
        </pattern>
        <pattern>
            <old>fox</old>
            <new>elephant</new>
        </pattern>
        <pattern>
            <old>brown</old>
            <new>white</new>
        </pattern>
    </my:params>

    <xsl:variable name="vPats"
         select="document('')/*/my:params/*"/>

    <xsl:template match="text()" name="multiReplace">
        <xsl:param name="pText" select="."/>
        <xsl:param name="pPatterns" select="$vPats"/>

        <xsl:if test="string-length($pText) >0">
            <xsl:variable name="vPat" select=
            "$vPats[starts-with($pText, old)][1]"/>

            <xsl:choose>
                <xsl:when test="not($vPat)">
                    <xsl:copy-of select="substring($pText,1,1)"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="$vPat/new/node()"/>
                </xsl:otherwise>
            </xsl:choose>

            <xsl:call-template name="multiReplace">
                <xsl:with-param name="pText" select=
                "substring($pText, 1 + not($vPat) + string-length($vPat/old/node()))"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

当此转换应用于以下 XML 文档时:
<t>The quick
brown fox</t>

生成想要的正确结果 :
The slow<br />white elephant

说明 :
  • 使用递归调用自身的命名模板。
  • 所有多重替换模式 --> 替换对都在单个外部参数中提供,这里为了方便起见,将其内联指定为全局级元素 <my:params>
  • 递归获取源字符串中的每个字符(从左到右),并在字符串中的该位置找到以该字符开头的第一个模式。
  • 替换不仅可以是字符串,也可以是任何节点。在这种特定情况下,我们用 <br/> 元素替换每个 NL 字符。
  • 关于search - XSL 多重搜索替换功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5280079/

    相关文章:

    c# - 换行的正则表达式

    string - 最有效的字符串替换算法?

    javascript - JS : Selecting Numbers Only From Text Field, 加上简单的计算?

    PHP 搜索 MySQL 数据库框架

    perl - XML::LibXSLT 间歇性地抛出样式表编译错误

    java - 如何在类的 ArrayList 中搜索字符串

    ruby - OS X 上的 xslt 2.0 和 Ruby

    javascript - 如何将 &lt;script&gt; 添加到 XSLT [通过转义解决]

    search - 二分查找最坏的情况是什么

    python - 如何在字符串列表中查找组件,注意它来自列表的哪个索引