如何用空格替换字符串中的所有特殊字符?

How to replace all special characters in a string with spaces?

我正在使用 XSLT 1.0。

假设我有一个类似于 "apple-mango%also|there"

的字符串

我正在尝试用 space 替换所有非字母数字字符。 我试过了

<xsl:value-of select="translate(., translate(., '0123456789abcdefghijklmnopqrstuvwxysABCDEFGHIJKLMNOPQRSTUVWXYZ', ''), ' ')"/>

但是没用。 问题出在外部翻译上。

据我了解,在 translate() 中,第三个字符串的长度应与第二个字符串的长度相同,否则缺失的字符将被替换为空字符串 ('').

内部翻译工作正常,因为无论如何我都想删除所有带有空字符串的字符。

但是外部翻译只用 space 替换第二个参数字符串的第一个字符,并将其余的替换为空字符串。

由于我在外部翻译的第二个参数中的非字母数字字符列表是动态的,所以我无法对第三个参数进行预编码。

例如:

我的内在翻译会 return -%|。哪个是正确的。

现在我的外部翻译是 translate(., '-%|', ' ')

哪个 returns apple mangoalsothere.

怎么能不写这样的东西呢:

translate(., '`~!@#$%^&*()-_=+[]{}\|;:'",<.>/?', '                                  ')

实现此目的的一种方法是创建一个递归模板来创建给定长度的仅由空格组成的字符串

<xsl:template name="AllSpaces">
    <xsl:param name="spaces" />
    <xsl:if test="$spaces > 0">
        <xsl:text> </xsl:text>
        <xsl:call-template name="AllSpaces">
            <xsl:with-param name="spaces" select="$spaces - 1" />
        </xsl:call-template>
    </xsl:if>
</xsl:template>

然后,您可以生成一个字符串,其空格数等于您正在使用的字符串的长度。

    <xsl:variable name="specialchars" select="translate(., '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', '')" />
    <xsl:variable name="spaces">
        <xsl:call-template name="AllSpaces">
            <xsl:with-param name="spaces" select="string-length($specialchars)" />
        </xsl:call-template>
    </xsl:variable>

然后您可以在翻译中使用这个 spaces 变量。例如,试试这个 XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text" />

    <xsl:template match="data">
        <xsl:variable name="specialchars" select="translate(., '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', '')" />
        <xsl:variable name="spaces">
            <xsl:call-template name="AllSpaces">
                <xsl:with-param name="spaces" select="string-length($specialchars)" />
            </xsl:call-template>
        </xsl:variable>
        <xsl:value-of select="translate(., $specialchars, $spaces)"/>
    </xsl:template>

    <xsl:template name="AllSpaces">
        <xsl:param name="spaces" />
        <xsl:if test="$spaces > 0">
            <xsl:text> </xsl:text>
            <xsl:call-template name="AllSpaces">
                <xsl:with-param name="spaces" select="$spaces - 1" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

现在,如果您想在 XML 中替换多个字符串,您可以通过为 spaces 设置一个等于最长字符串长度的全局变量来稍微改进一下.这会为您提供比您需要更多的空间,但这不是问题。

也试试这个 XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text" />

    <xsl:variable name="spaces">
        <xsl:for-each select="//data">
            <xsl:sort select="string-length(.)" order="descending" />
            <xsl:if test="position() = 1">
                <xsl:call-template name="AllSpaces">
                    <xsl:with-param name="spaces" select="string-length(.)" />
                </xsl:call-template>
            </xsl:if>
        </xsl:for-each>
    </xsl:variable>

    <xsl:template match="data">
        <xsl:value-of select="translate(., translate(., '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ''), $spaces)"/>
    </xsl:template>

    <xsl:template name="AllSpaces">
        <xsl:param name="spaces" />
        <xsl:if test="$spaces > 0">
            <xsl:text> </xsl:text>
            <xsl:call-template name="AllSpaces">
                <xsl:with-param name="spaces" select="$spaces - 1" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

应用于此XML

<test>
    <data>apple-mango%also|there</data>
    <data>apple-mango%also|there!test</data>
</test>

下面是输出

apple mango also there
apple mango also there test

您可以查看的另一种方法是使用 "inner translate" 的结果——即包含所有不需要的字符的字符串——作为命名递归模板中的参数,该模板将逐个替换它们-一个,来自 space:

XML

<input>alpha-bravo/charlie#delta...echo?foxtrot%golf|hotel india-juliet</input>

XSLT 1.0

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:template match="/">
    <output>
        <xsl:call-template name="tokenize">
            <xsl:with-param name="string" select="input"/>
            <xsl:with-param name="delimiters" select="translate(input, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', '')"/>
        </xsl:call-template>
    </output>
</xsl:template>

<xsl:template name="tokenize">
    <xsl:param name="string"/>
    <xsl:param name="delimiters"/>
    <xsl:choose>
        <xsl:when test="$delimiters">
            <xsl:variable name="delimiter" select="substring($delimiters, 1, 1)" /> 
            <xsl:value-of select="substring-before($string, $delimiter)" />
            <xsl:text> </xsl:text>
            <!-- recursive call -->
            <xsl:call-template name="tokenize">
                <xsl:with-param name="string" select="substring-after($string, $delimiter)"/>
                <xsl:with-param name="delimiters" select="substring($delimiters, 2)"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$string"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

结果

<?xml version="1.0" encoding="utf-8"?>
<output>alpha bravo charlie delta   echo foxtrot golf hotel india juliet</output>