这个
<catalog>
<country><![CDATA[ WIN8 <b>X</b> Mac OS ]]></country>
</catalog>
等价于
<catalog>
<country> WIN8 <b>X</b> Mac OS </country>
</catalog>
这正是你使用时得到的结果
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<xsl:template match="country/text()">
<xsl:value-of select="." disable-output-escaping="yes" />
</xsl:template>
</xsl:stylesheet>
关键是disable-output-escaping (DOE) 对落入cdata-section-elements (CSE) 的元素没有影响。那是因为这两个指令都禁用了输出转义。
文本值" WIN8 <b>X</b> Mac OS "变为:
正常序列化时:WIN8 &lt;b&gt;X&lt;/b&gt; Mac OS
使用 CSE 序列化时:<![CDATA[ WIN8 <b>X</b> Mac OS ]]>
使用 DOE 序列化时:WIN8 <b>X</b> Mac OS
注意最后两个渲染是完全相同的,除了封闭的<![CDATA[ ... ]]>。
CDATA 禁用元素的文本节点子节点的输出转义,作为交换将它们括在 <![CDATA[ ... ]]> 标记中以弥补丢失的转义级别。
如果您在 <xsl:value-of> 上另外设置 DOE,该 <xsl:value-of> 将文本输出到已设置 CSE 的元素中,则不会发生任何事情。输出转义已被禁用。
因此
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:output cdata-section-elements="country" />
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<xsl:template match="country/text()">
<xsl:value-of select="." disable-output-escaping="yes" />
</xsl:template>
</xsl:stylesheet>
会准确地告诉你你的输入是什么。
这就是为什么您无法摆脱双重转义并在同一转换期间拥有CDATA 。如果您肯定必须在结果文档中包含 CDATA,则可以使用两步方法(第一步禁用输出转义,第二步添加回 CDATA)——但我个人认为这不值得。