XML中的<![CDATA[]]>是什么意思?

1254

我经常在XML文件中发现这个奇怪的CDATA标记:

<![CDATA[some stuff]]>

我注意到这个CDATA标签总是出现在开头,然后跟着一些东西。

但有时会用到它,有时不会。我想这是为了标记some stuff是在此之后将要插入的"data"。但是some stuff是什么样的数据呢?我在XML标签中写的任何内容不都是某种类型的数据吗?

13个回答

1206

CDATA代表字符数据,它意味着在这些字符串之间的数据包括可能被解释为XML标记的数据,但不应该。

CDATA和注释之间的关键区别是:

  • Richard所指出,CDATA仍然是文档的一部分,而注释不是。
  • 在CDATA中,您不能包含字符串]]>CDEnd),而在注释中--无效
  • 参数实体引用在注释内部不被识别。

这意味着在一个格式良好的文档中,给定这四个XML片段:

<!ENTITY MyParamEntity "Has been expanded">

<!--
Within this comment I can use ]]>
and other reserved characters like <
&, ', and ", but %MyParamEntity; will not be expanded
(if I retrieve the text of this node it will contain
%MyParamEntity; and not "Has been expanded")
and I can't place two dashes next to each other.
-->

<![CDATA[
Within this Character Data block I can
use double dashes as much as I want (along with <, &, ', and ")
*and* %MyParamEntity; will be expanded to the text
"Has been expanded" ... however, I can't use
the CEND sequence. If I need to use CEND I must escape one of the
brackets or the greater-than sign using concatenated CDATA sections.
]]>

<description>An example of escaped CENDs</description>
<!-- This text contains a CEND ]]> -->
<!-- In this first case we put the ]] at the end of the first CDATA block
     and the > in the second CDATA block -->
<data><![CDATA[This text contains a CEND ]]]]><![CDATA[>]]></data>
<!-- In this second case we put a ] at the end of the first CDATA block
     and the ]> in the second CDATA block -->
<alternative><![CDATA[This text contains a CEND ]]]><![CDATA[]>]]></alternative>

42
如何转义CEND序列中的字符? - Thomas Weller
32
你需要有两个 CDATA 部分来连接 ]]> - 详见这个答案关于如何和为什么这样做的解释。 - Sean Vieira
2
CDATA开始标记和原始数据之间必须有换行符吗? - Ben Sewards
2
不,没有 @BenSewards - Sean Vieira
7
这段类C代码不容易放入CDATA节段中:if (a[b[c]]>10) { } - Anders Marzi Tornblad
显示剩余3条评论

369

一个CDATA段是"被标记为仅字符数据而不是标记的元素内容部分。"

从语法上讲,它的行为类似于注释:

<exampleOfAComment>
<!--
    Since this is a comment
    I can use all sorts of reserved characters
    like > < " and &
    or write things like
    <foo></bar>
    but my document is still well-formed!
-->
</exampleOfAComment>

...但它仍然是文档的一部分:

<exampleOfACDATA>
<![CDATA[
    Since this is a CDATA section
    I can use all sorts of reserved characters
    like > < " and &
    or write things like
    <foo></bar>
    but my document is still well formed!
]]>
</exampleOfACDATA>

尝试将以下内容保存为.xhtml文件(不是.html),并使用FireFox(而不是Internet Explorer)打开,以查看注释和CDATA部分之间的区别;当您在浏览器中查看文档时,注释将不会出现,而CDATA部分将会出现:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" >
<head>
<title>CDATA Example</title>
</head>
<body>

<h2>Using a Comment</h2>
<div id="commentExample">
<!--
You won't see this in the document
and can use reserved characters like
< > & "
-->
</div>

<h2>Using a CDATA Section</h2>
<div id="cdataExample">
<![CDATA[
You will see this in the document
and can use reserved characters like
< > & "
]]>
</div>

</body>
</html>

注意CDATA部分没有编码,因此无法在其中包含字符串]]>。任何包含]]>的字符数据都必须是文本节点,据我所知。同样,从DOM操作的角度来看,您不能创建包含]]>的CDATA部分。
var myEl = xmlDoc.getElementById("cdata-wrapper");
myEl.appendChild(xmlDoc.createCDATASection("This section cannot contain ]]>"));

这段DOM操作代码会在Firefox中抛出异常,或者生成结构不良的XML文档:http://jsfiddle.net/9NNHA/


3
为什么 CDATA 中不允许使用字符 "ý"? - bjan
14
你觉得那个字符非法的依据是什么?听起来可能是编码问题。 - Richard JP Le Guen
我在IE中打开了这个文档,同时使用了MSXML解析器,该解析器将其声明为无效字符。我有一个XSD,在其中它被声明为"type =“ xs:string”"。这与编码或XML版本有关吗? - bjan
1
因此,我们可以使用CDATA将一些HTML嵌入XML文档中,以便HTML不会混淆XML文档结构,然后稍后使用XSLT将其提取并吐出到正在输出的HTML文档中。 - Kaz
@RichardJPLeGuen 我现在正在做这件事情,在我正在修补的邮件列表存档程序中。HTML 来自一封电子邮件,因此可能是垃圾,带有损坏的标记等。XSLT 将仅将 CDATA 视为字符串。当 XSLT 将该文本插入输出文档时,您必须禁用转义,否则它将变成转义的 HTML 代码,而不是标记。也就是说,< 将变成 <,依此类推。 - Kaz
显示剩余3条评论

82

一个重要的用例:您的XML包含一个作为数据的程序(例如Java的网页教程)。 在这种情况下,您的数据包括大量字符,包括“&”和“<”,但这些字符并不意味着是XML。

比较:

<example-code>
while (x &lt; len &amp;&amp; !done) {
    print( &quot;Still working, &apos;zzz&apos;.&quot; );
    ++x;
    }
</example-code>

<example-code><![CDATA[
while (x < len && !done) {
    print( "Still working, 'zzzz'." );
    ++x;
    }
]]></example-code>
特别是如果您从文件中复制/粘贴此代码(或在预处理器中包含它),则最好只在xml文件中使用所需的字符,而不是将其与XML标记/属性混淆。正如@paary提到的那样,其他常见用途包括嵌入包含和号的URL时。最后,即使数据仅包含少量特殊字符,但数据非常长(比如一章的文本),也最好在编辑xml文件时无需对这些实体进行编码/解码。
(我怀疑所有与评论的比较都有些误导/无益。)

但是,请避免不加区分地使用 CDATA。 - Peter Krauss

52

我曾经在XML元素需要存储HTML代码时使用过CDATA。类似这样:

<codearea>
  <![CDATA[ 
  <div> <p> my para </p> </div> 
  ]]>
</codearea>

因此,CDATA表示它将忽略任何可能被解释为XML标签的字符,例如<和>等。


2
不是“标签”,而是第一句话中的元素。 - Ludovic Kuty

37

其中包含的数据不会被解析为XML格式,因此不需要是有效的XML或者包含看起来像XML但实际上不是XML的元素。


20

作为其使用的另一个示例:

如果您拥有一个RSS Feed(xml文档)并且想在描述的显示中包含一些基本的HTML编码,您可以使用CData对其进行编码:

<item>
  <title>Title of Feed Item</title>
  <link>/mylink/article1</link>
  <description>
    <![CDATA[      <p>      <a href="/mylink/article1"><img style="float: left; margin-right: 5px;" height="80" src="/mylink/image" alt=""/></a>      Author Names      <br/><em>Date</em>      <br/>Paragraph of text describing the article to be displayed</p>    ]]>
  </description>
</item>

RSS阅读器提取描述并在CDATA中呈现HTML。

注意 - 并非所有HTML标记都有效 - 我认为这取决于您使用的RSS阅读器。


关于为什么此示例使用CData(而不是适当的pubData和dc:creator标记)的解释:这是为了网站显示,使用RSS小部件,我们没有真正的格式控制权。

这使我们能够指定包括图像的高度和位置,正确格式化作者姓名和日期等等,而无需新的小部件。这也意味着我可以通过脚本来实现它,而无需手动添加它们。


18

维基百科解释:

在XML文档或外部解析实体中,CDATA段是一个元素内容片段,被标记为只解释为字符数据而非标记的内容。

http://en.wikipedia.org/wiki/CDATA

因此:CDATA内的文本被解析器看作字符数据,而不是XML节点。


16

它可以转义无法像通常一样传递给XML的字符串:

例如:

The string contains "&" in it.

您不能:

<FL val="Company Name">Dolce & Gabbana</FL>

因此,您必须使用CDATA:

<FL val="Company Name"> <![CDATA["Dolce & Gabbana"]]> </FL>

8
你不必使用MUST,只需将其编码为Dolce &amp; Gabbana即可。这并不是展示CDATA有用的好例子。 - Balázs Varga

12

CDATA代表字符数据。您可以使用它来转义一些否则将被视为常规XML的字符。其中的数据不会被解析。 例如,如果您想传递一个包含&的URL,您可以使用CDATA来实现。否则,您将会得到一个错误,因为它将被解析为常规XML。


7

它用于包含可能被视为xml的数据,因为它包含某些字符。

这样,内部的数据将被显示,但不会被解释。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接