当用于属性的声明值时,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",就像值为"&#48;" 的NUMBER 属性等价于"0"(即使序列"&#48;"包含数字以外的字符)。