XSLT translate函数误删字符求助:仅替换&为&
解决XSLT中字符串替换误删字符的问题
嘿,问题根源很明确:你用错函数啦!translate()是单个字符的映射替换工具,不是用来做完整字符串替换的,这才导致文本里的a、m、p被误删。
为啥你的代码会出问题?
translate()的逻辑是:把第一个参数里的每个字符,在第二个参数的字符序列里找对应位置,替换成第三个参数对应位置的字符;如果第二个参数的字符在第三个参数里没有对应位置,会直接删掉这个字符。
看你的代码:
<xsl:when test="contains(//column[@name="Description"]/text(), "&amp;amp;")"> <xsl:value-of select="translate(//column[@name="Description"]/text(),'&amp;amp;','&amp; ')" disable-output-escaping="no"/> </xsl:when>
把参数展开成实际字符后:
- 要替换的字符序列是:
&, a, m, p, a, m, p(也就是&amp;amp;拆出来的单个字符) - 替换后的字符序列是:
&, a, m, p,(也就是&拆出来的)
这就导致:
- 文本中单独的
a会匹配第二个序列里的第5个a,被替换成空格; - 单独的
m、p因为在第三个序列里没有对应位置,直接被删除;
所以你的and变成了nd,amptestamp变成了test。
正确的解决办法
如果你用的是XSLT 2.0及以上(推荐,简单粗暴)
直接用replace()函数,它专门做完整字符串替换,不会碰单个字符:
<xsl:when test="contains(//column[@name="Description"]/text(), "&amp;amp;")"> <xsl:value-of select="replace(//column[@name="Description"]/text(), '&amp;amp;', '&amp;')" disable-output-escaping="no"/> </xsl:when>
这个函数的逻辑完全符合你的需求:找到所有&amp;amp;,替换成&amp;,其他字符完全不动。
如果你只能用XSLT 1.0(没有内置replace,得自己写)
XSLT 1.0没有自带的字符串替换功能,我们写个递归模板来实现:
<!-- 先定义一个递归替换的模板 --> <xsl:template name="replace-full-string"> <xsl:param name="input-text"/> <xsl:param name="find"/> <xsl:param name="replace-with"/> <xsl:choose> <xsl:when test="contains($input-text, $find)"> <!-- 输出匹配字符串之前的内容 --> <xsl:value-of select="substring-before($input-text, $find)"/> <!-- 输出替换后的内容 --> <xsl:value-of select="$replace-with"/> <!-- 递归处理剩下的文本 --> <xsl:call-template name="replace-full-string"> <xsl:with-param name="input-text" select="substring-after($input-text, $find)"/> <xsl:with-param name="find" select="$find"/> <xsl:with-param name="replace-with" select="$replace-with"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <!-- 没有匹配的话直接输出原文本 --> <xsl:value-of select="$input-text"/> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- 然后在你的逻辑里调用这个模板 --> <xsl:when test="contains(//column[@name="Description"]/text(), "&amp;amp;")"> <xsl:call-template name="replace-full-string"> <xsl:with-param name="input-text" select="//column[@name="Description"]/text()"/> <xsl:with-param name="find" select="'&amp;amp;'"/> <xsl:with-param name="replace-with" select="'&amp;'"/> </xsl:call-template> </xsl:when>
这个模板会递归查找所有完整的&amp;amp;字符串并替换,完全不会影响单独的a、m、p。
测试结果
用你的输入&amp;amp;wUS &amp;amp;and amptestamp,不管用哪个方案,都会得到你想要的输出:&amp;wUS &amp;and amptestamp
内容的提问来源于stack exchange,提问作者Tatavarthy Suresh
相关产品推荐
相关产品推荐

