输入:
<Data>
<info>the %text ^with *special chars asxbajx @ fagfa ~</info>
</Data>
输出:
<Data>
<info> the ++text ++with ++special chars asxbajx ++ fagfa ++</info>
</Data>
要求:
搜索一些特定的字符集,并将其替换为文本"++"。如果遇到问题,需要向用户显示消息。
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: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" select="document('')/*/my:pNames"/>
<xsl:value-of select="
translate(
.,
$testvar,
'+'
)
"/>
</xsl:template>
</xsl:stylesheet>
我没有得到确切的输出。
有人能帮我吗?
您遇到的第一个问题是translate函数只会将一个字符"翻译"为另一个字符。因此,不能使用它将单字符%
替换为双字符串++
。此外,第二个和第三个参数通常具有相同长度的
translate(., '%^*@~', '+++++')
这是因为"from"字符被"to"字符串中相应位置的字符替换。如果你只翻译(.,'%^*@~','+'),那么字符^*@~
将被替换为零!
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函数将所有出现的有趣字符替换为相同的字符
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>