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

时间:2015-04-16 05:34:09

标签: xslt xslt-1.0

我正在使用XSLT 1.0。

假设我有一个类似于“apple-mango%also | there”的字符串

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

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

但它不起作用。 问题在于外部翻译。

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

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

但是外部翻译只用空格替换第二个参数字符串的第一个字符,并用空字符串替换rest。

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

例如:

我的内心翻译将返回-%|。这是正确的。

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

返回apple mangoalsothere

如果没有这样的话,怎么办呢?

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

2 个答案:

答案 0 :(得分:3)

你可以看到这个的另一种方法是使用“内部翻译”的结果 - 即包含所有不需要的字符的字符串 - 作为命名递归模板中的一个参数,逐个替换它们,通过空间:

<强> 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>

答案 1 :(得分:1)

这样做的一种方法是创建一个递归模板来创建一个除了给定长度的空格之外的任何字符串

<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