在 XML DTD 中——当定义一个元素时,我们使用#PCDATA 表示这个元素可以包含任何可解析的文本。在定义一个属性时,我们用CDATA表示它的值可以是任何字符数据。
XML 中使用的 CDATA 是不被 XML 解析器解析的东西(多字符转义序列)。一致地,当我们使用 CDATA 来定义属性时;解析器不应该解析它。但是,确实如此!
那么,为什么不能用 PCDATA 代替 CDATA 来定义属性呢?
更新 - 一直保持这种方式以与 SGML 向后兼容。 SGML 中这种命名背后的原因是什么?
最佳答案
当用于属性的声明值时,CDATA 指的是属性的实际值(字符数据),而不是解析它的上下文。另一方面,在解析元素时,我们需要区分无标记字符数据 (CDATA) 和预期的已解析字符数据(PCDATA)。
乍一看这似乎是任意的,但事实并非如此(参见 here 和 here)。
在 SGML 中,属性值规范可以被引用(属性值文字)或不被引用(属性值)。
attribute value specification = attribute value literal | attribute value
当属性未被引用时,只允许使用 NAME 字符,并且对于某些声明的值(例如 NUMBER)可能会进一步限制。
另一方面,属性值文字的内容是一系列可替换字符数据,由 LIT/LITA 定界符(分别为双引号和单引号)包围, 在引用具体语法中)。
attribute value literal =
( LIT , replaceable character data *, LIT) |
( LITA , replaceable character data *, LITA)
可替换字符数据“类似于 CDATA,除了可以识别实体引用和字符引用”(Goldfarb,SGML 手册)。
由此可见,属性值文字中实体引用的替换不依赖于属性的声明值。因此,如果你有 <!ENTITY foo "bar">
和 <elem attr="&foo;">
实体引用 &foo;
将在可替换字符数据(LIT 识别模式)的上下文中进行解析,产生 <elem attr=bar>
. attr
没关系声明为 CDATA、NAME 或其他。
更新
不必说属性中的实体必须解析,因为所有属性类型都有相同的解析规则:如果属性值以引号(LIT)开头,则实体被识别(可替换字符数据)当找到匹配的结束引号时,该值结束。
这里的CDATA是指一个有效的属性必须包含展开实体后的任意字符数据。 如果将属性声明为 NUMBER,则需要包含数字字符(或扩展为数字字符的实体)。
在上面的示例中,值为 "&foo;"
的 CDATA 属性相当于"bar"
,与值为 "0"
的 NUMBER 属性相同相当于"0"
(即使序列 "0"
包含数字以外的字符)。
关于xml - XML DTD 中的 PCDATA 与 CDATA,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20474113/