CDSL内部的XSL unescape HTML

时间:2013-12-10 08:35:05

标签: xml xslt cdata html-escape-characters

我正在尝试转换XML:

 <catalog>
            <country><![CDATA[ WIN8 &lt;b&gt;X&lt;/b&gt; Mac OS ]]></country>
    </catalog>

<catalog>
        <country><![CDATA[  WIN8 <b>X</b> Mac OS ]]></country>        
</catalog>

使用XSL转换。

我知道使用disable-output-escaping =“yes”或cdata-section-elements我可以将转义字符转换为非转义字符并放入CDATA内部,但如果字符已经在CDATA中,则无效。

有一个简单的方法吗? 感谢。

2 个答案:

答案 0 :(得分:4)

<catalog>
  <country><![CDATA[  WIN8 <b>X</b> Mac OS ]]></country>        
</catalog>

相当于

<catalog>
  <country> WIN8 &lt;b&gt;X&lt;/b&gt; 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,将文本输出到已设置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 - 但我个人认为这不值得。

答案 1 :(得分:1)

这是另一个解决方案,在xsl:text中使用CDATA with disable-output-escaping =&#34; yes&#34;:

<xsl:template match="/" >
    <xsl:text disable-output-escaping="yes"><![CDATA[
    <script>
    var thisTextIsNotEscaped = "<b>this text is normally escaped, but not in this case</b>";
    </script>
    ]]>
</xsl:text>
</xsl:template>