在XML DTD中 - 在定义元素时,我们使用#PCDATA来表示此元素可以包含任何可解析的文本。在定义属性时,我们使用CDATA来表示其值可以是任何字符数据。
XML中使用的CDATA是XML解析器未解析的(多字符转义序列)。一致地,当我们使用CDATA定义属性时;解析器不应该解析它。但是,确实如此!
那么,为什么不能使用PCDATA代替CDATA来定义属性?
更新 - 这一直保持与SGML向后兼容。 SGML中这种命名背后的原因是什么?
答案 0 :(得分:2)
在属性的声明值中使用 CDATA是指属性(字符数据)的实际值,而不是解析它的上下文。另一方面,在解析元素时,我们需要区分character-data-with-no-markup(CDATA)和parsed-character-data-where-delimiters-expected(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;">
,则将在可替换字符数据(LIT识别模式)的上下文中解析实体引用&foo;
,从而产生<elem attr=bar>
。将attr
声明为CDATA,NAME或其他任何内容都无关紧要。
<强>更新强>
没有必要说必须解析属性中的实体,因为所有属性类型都具有相同的解析规则:如果属性值以引号(LIT)开头,则识别实体(可替换的字符数据)当找到匹配的结束引用时,该值结束。
此处CDATA表示有效属性在扩展实体后必须包含任意字符数据。 如果该属性已声明为NUMBER,则需要包含数字字符(或扩展为数字字符的实体)。
在上面的示例中,值"&foo;"
的CDATA属性等同于"bar"
,与值"0"
的NUMBER属性相当于"0"
的方式相同(即使序列"0"
包含除数字之外的字符)。
答案 1 :(得分:0)
CDATA section就像您在元素中使用的那样,与CDATA attribute type不同。
您最有可能观察到的解析(例如正在解析的实体引用)来自attribute-value normalization。