您遇到的第一个问题是translate函数仅将单个字符“翻译”为另一个单个字符。所以不能用%
双字符串替换单字符++
。此外,您通常具有相同长度的第二个和第三个参数
translate(., '%^*@~', '+++++')
这是因为 'from' 字符被 'to' 字符串中相应位置的字符替换。如果你只做 translate(., '%^*@~', '+') 那么字符^*@~
将被替换为空!
XSLT1.0 没有替换功能(虽然 XSTL2.0 中存在替换功能),所以首先您需要找到一个递归模板来完成这项工作。这是一个!
<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>
与其依次为每个参数调用它,不如先使用 translate 函数将所有有趣的字符替换为一个有趣的字符(例如,%
)
首先定义一个变量来保存你的第一个字符参数
<xsl:variable name="firstchar" select="document('')/*/my:pNames/n[1]" />
然后像这样定义两个变量
<xsl:variable name="testvar">
<xsl:apply-templates select="document('')/*/my:pNames/n" mode="replace"/>
</xsl:variable>
<xsl:variable name="replace">
<xsl:apply-templates select="document('')/*/my:pNames/n" mode="by"/>
</xsl:variable>
相应的模板如下所示
<xsl:template match="my:pNames/n" mode="replace">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="my:pNames/n" mode="by">
<xsl:value-of select="$firstchar"/>
</xsl:template>
这意味着testvar变量将设置为%^*@~
,并且replace将设置为+++++
。然后,您可以使用翻译功能将所有出现的有趣字符替换为相同的字符
translate(., $testvar, $replace)
这意味着您只需要调用一次替换模板
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="translate(., $testvar, $replace)" />
<xsl:with-param name="replace" select="$firstchar" />
<xsl:with-param name="by" select="'++'" />
</xsl:call-template>
这是完整的 XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="aaa">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<my:pNames>
<n>%</n>
<n>^</n>
<n>*</n>
<n>@</n>
<n>~</n>
</my:pNames>
<xsl:variable name="firstchar" select="document('')/*/my:pNames/n[1]" />
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<xsl:param name="pText" select="."/>
<xsl:for-each select="document('')/*/my:pNames/n">
<xsl:variable name="testvar1" select="."/>
<xsl:if test="contains($pText,$testvar1)">
<xsl:message terminate="no">
<xsl:value-of select="$pText"/>
</xsl:message>
</xsl:if>
</xsl:for-each>
<xsl:variable name="testvar">
<xsl:apply-templates select="document('')/*/my:pNames/n" mode="replace"/>
</xsl:variable>
<xsl:variable name="replace">
<xsl:apply-templates select="document('')/*/my:pNames/n" mode="by"/>
</xsl:variable>
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="translate(., $testvar, $replace)" />
<xsl:with-param name="replace" select="$firstchar" />
<xsl:with-param name="by" select="'++'" />
</xsl:call-template>
</xsl:template>
<xsl:template match="my:pNames/n" mode="replace">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="my:pNames/n" mode="by">
<xsl:value-of select="$firstchar"/>
</xsl:template>
<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:stylesheet>
当应用于您的输入 XML 时,将输出以下内容
<Data>
<info>the ++text ++with ++special chars asxbajx ++ fagfa ++</info>
</Data>