翻译|其它|编辑:郝浩|2005-04-01 11:52:00.000|阅读 1969 次
概述:
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
3. 逻辑结构
[定义:每个 XML
文件包含一个或多个元素,它们的边界用起始标签和结束标签分隔,或者,对于空元素,用一个空元素标签分隔。每一个元素有一个用名字标识的类型,有时称之为它的"通用标识符(generic
identifier)"(GI),同时它可以有一个属性值说明(attribute specification)集。] 每一个属性值说明有一个名字和一个值。
元素
[39] element ::= EmptyElemTag
| STag content ETag [WFC: 元素类型匹配]
[VC: 元素有效性]
除了那些开头匹配(('X'|'x')('M'|'m')('L'|'l'))的名字保留用于本规范的此版本和后继版本的标准化外,本规范不对元素类型和属性的语义,用法和名字(语法之外)作出限制。
3.1 起始标签,结束标签和空元素标签
[定义:每一个非空 XML 元素以一个起始标签作为开始的标记。]
起始标签
[40] STag ::= '<' Name (S Attribute)* S? '>' [WFC: 唯一的属性值说明]
[41] Attribute ::= Name Eq AttValue [VC: 属性值类型]
[WFC: 无外部实体引用]
[WFC: 在属性值中没有<]
起始标签和结束标签中的 Name 给出了元素的类型。[定义:Name-AttValue 对被统称为元素的属性值说明],[定义:其中每一对中的 Name 被称为属性名],[定义:AttValue 的内容(在'或"定界符间的文本)被称为属性值]。注意,在起始标签和空元素标签中各个属性值声明的次序没有意义。
起始标签的一个例子:
<termdef id="dt-dog" term="dog"> |
[定义:由一个起始标签开始的每一个元素必须用一个结束标签标记其结束,结束标签中的名字必须与起始标签中给出的元素类型相同:]
结束标签
[42] ETag ::= '</' Name S? '>'
结束标签的一个例子:
</termdef> |
[定义:在起始标签和结束标签中的文本被称为元素的内容:]
元素的内容
[43] content ::= CharData? ((element | Reference | CDSect | PI | Comment)
CharData?)* /* */
[定义:称没有内容的元素其内容为空。] 空元素可以用一个起始标签紧跟一个结束标签的方式或空元素标签来表示。[定义:空元素标签有一种特殊的形式:]
空元素标签
[44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>' [WFC: 唯一的属性值说明]
不论元素是否用关键字 EMPTY 声明,空元素标签都可以用于任何没有内容的元素。出于互操作性考虑,空元素应该用于,且只应用于声明为 EMPTY 的元素。
空元素的例子:
<IMG align="left" src="http://www.w3.org/Icons/WWW/w3c_home" /> <br></br> <br/> |
3.2 元素类型声明
出于验证的目的,可以用元素类型和属性表声明限制 XML 文件中元素的结构。元素类型声明限制了元素的内容。
元素类型声明通常限制了子元素的类型。由使用者选择,当声明提到的元素类型没有相应的声明时,XML 处理器可以给出警告,但这不是一个错误。
[定义:元素类型声明的形式如下:]
元素类型声明
[45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>' [VC:
唯一的元素类型声明]
[46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
其中 Name 给出了所声明的元素类型。
有效性约束: 唯一的元素类型声明
元素类型只能声明一次。
元素类型声明的例子:
<!ELEMENT br EMPTY> <!ELEMENT p (#PCDATA|emph)* > <!ELEMENT %name.para; %content.para; > <!ELEMENT container ANY> |
3.2.1 元素型内容
[定义:当某一类型的元素只能包含用可选空白(匹配非终结符 S)分隔的子元素(无字符数据)时,称此元素类型具有元素型内容。]
[定义:在这种情况下,有内容模型作为类型限制之一,内容模型是决定子元素类型和子元素出现顺序的一种简单文法。] 此文法用内容粒子( cp
)构建,内容粒子由名字,内容粒子的选择表(choice list)或内容粒子的序列表(sequence list)组成:
元素型内容的模型
[47] children ::= (choice | seq) ('?' | '*' | '+')?
[48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
[49] choice ::= '(' S? cp ( S? '|' S? cp )+ S? ')' /* */
/* */
[VC: 严格的组/参数实体嵌套]
[50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')' /* */
[VC: 严格的组/参数实体嵌套]
其中每一个 Name
是可以作为子元素的元素的类型。选择表中出现的任意内容粒子在元素型内容中允许出现的位置对应于选择表在文法中的位置。序列表中出现的所有内容粒子必须以相同的顺序出现在元素型内容中。在名字或表之后的可选字符(optional
character)决定了表中元素或内容粒子可以出现一次或多次(+),还是零次或多次(*),或是零次或一次(?)。没有这样一个操作符意味着元素或内容粒子必须恰好出现一次。这种语法和意义和本规范中的产生式中所使用的相同。
当且仅当一个元素的内容可以通过满足内容模型中的选择,序列和重复操作符得到,并且内容中的每一个元素与内容模型中的一种元素类型相匹配时,称此元素的内容与该内容模型相匹配。出于兼容性考虑,
如果文件的某个元素可以和内容模型中的一种元素类型多次匹配,这是一个错误。 更详细的信息参见"E. 确定型内容模型".
有效性约束: 严格的组/参数实体嵌套
参数实体的置换文本必须由括号括起的组严格嵌套。即,如果 choice,seq 或 Mixed
语法成分的开始或结束括号出现在某个参数实体的置换文本中,两者必须同在此置换文本中。
出于互操作性考虑,如果一个参数实体引用出现在choice,seq或Mixed语法成分中时,它的置换文本至少应该包含一个非空字符,同时其置换文本的第一个和最后一个非空字符都不应为一个连接符(|
或 ,)。
元素型内容的模型举例:
<!ELEMENT spec (front, body, back?)> <!ELEMENT div1 (head, (p | list | note)*, div2*)> <!ELEMENT dictionary-body (%div.mix; | %dict.mix;)*> |
3.2.2 混合型内容(Mixed Content)
[定义:当某元素类型可以包含字符数据,其间可以随意穿插子元素时,称此元素类型具有混合型内容。]
在这种情况下,对子元素的类型可能有所限制,但对它们的次序和出现次数没有限制:
混合型内容声明
[51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*'
| '(' S? '#PCDATA' S? ')' [VC: 严格的组/参数实体嵌套]
[VC: 无重复类型]
其中 Name 给出了子元素的元素的类型。关键字 #PCDATA 来自术语"已析字符数据(parsed character data)"而来
有效性约束: 无重复类型
同一名字在单个混合型内容声明中只能出现一次。
混合内容声明的例子:
<!ELEMENT p (#PCDATA|a|ul|b|i|em)*> <!ELEMENT p (#PCDATA | %font; | %phrase; | %special; | %form;)* > <!ELEMENT b (#PCDATA)> |
3.3 属性表声明
属性用于关联名字-值对和元素。属性值说明只能在起始标签和空元素标签中出现; 因此,用于识别它们的产生式出现在"3.1
起始标签,结束标签和空元素标签"中。属性表声明可以用于:
定义与一给定元素类型有关的属性集。
确定这些属性的类型限制。
提供属性的缺省值。
[定义:属性表声明详细说明了与给定元素类型相关联的每一个属性的名字,数据类型和缺省值(如果有的话):]
属性表声明
[52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
[53] AttDef ::= S Name S AttType S DefaultDecl
AttlistDecl 规则中 Name 是元素的类型。由使用者选择,当属性声明相关的元素类型没有被声明时,XML
处理器可以给出一个警告,但这不是一个错误。AttDef 规则中的 Name 是属性的名字。
当与某个给定元素类型相关的 AttlistDecl
超过一个时,这些声明中的内容被合并在一起。当给定元素类型的某个属性的定义超过一个时,绑定第一个定义,其余定义被忽略。出于互操作性考虑,DTD
的作者可以这样做:一个给定的元素类型至多有一个属性表声明,一个属性表中一个给定的属性名至多有一个属性定义,每个属性表声明至少有一个属性定义。出于互操作性考虑,当一个给定元素有超过一个的属性表声明或一个给定属性有超过一个的属性定义时,XML
处理器可以,由使用者选择,给出警告,但这不是一个错误。
3.3.1 属性类型
XML 属性有三种类型:字符串类型,一组记号化类型和枚举类型。字符串类型可以以任意常量字符串为值;
各个记号化类型有不同的词法和语义约束。文法中指出的有效性约束适用于属性值已按 3.3 节 3.3 属性表声明中所述规范化了之后的情况。
属性类型
[54] AttType ::= StringType | TokenizedType | EnumeratedType
[55] StringType ::= 'CDATA'
[56] TokenizedType ::= 'ID' [VC: ID]
[VC: 每种元素类型一个 ID]
[VC: ID 属性的缺省值]
| 'IDREF' [VC: IDREF]
| 'IDREFS' [VC: IDREF]
| 'ENTITY' [VC: 实体名]
| 'ENTITIES' [VC: 实体名]
| 'NMTOKEN' [VC: 名字记号]
| 'NMTOKENS' [VC: 名字记号]
[定义:枚举类型的属性可以在声明中提供的取值表中取值。] 有两种枚举类型:
枚举属性类型
[57] EnumeratedType ::= NotationType | Enumeration
[58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
[VC: 记法属性]
[VC: 每种属性类型一种记法]
[VC: 空元素没有记法]
[59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')' [VC: 枚举]
一个 NOTATION 类型的属性标识了一种用于解释与此属性相关的元素的记法,此记法中用系统或公共标识符在 DTD 中声明。
出于互操作性考虑,同一 Nmtoken 只能在单个元素类型的枚举属性类型中出现一次。
3.3.2 属性缺省值
属性声明提供的信息指明了某属性是否必须出现,同时指明了在被声明的属性不是必须出现而文件中没有出现此属性的情况下,XML 处理器应如何处理。
属性缺省值
[60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED'
| (('#FIXED' S)? AttValue) [VC: 必须的属性]
[VC: 合法的属性缺省值]
[WFC: 在属性值中无 < ]
[VC: 固定的属性缺省值]
在一个属性声明中,#REQUIRED 表示必须总是提供此属性,#IMPLIED 表示不提供缺省值。如果声明既不是 #REQUIRED,也不是 #IMPLIED,那么 AttValue 值包含了所声明的缺省值;关键字 #FIXED 规定此属性必须总是有缺省值。如果声明了一个缺省值,当 XML 处理器遇到一个被省略的属性时,它将当成此属性以缺省值出现:
属性表声明的例子:
<!ATTLIST termdef id ID #REQUIRED name CDATA #IMPLIED> <!ATTLIST list type (bullets|ordered|glossary) "ordered"> <!ATTLIST form method CDATA #FIXED "POST"> |
3.3.3 属性-值对的规范化(Attribute-Value Normalization)
如果属性值的类型不是 CDATA,那么 XML
处理器必须继续处理规范化之后的值,去掉其前导和尾随空格(#x20)字符,并将空格(#x20)字符序列替换成单个空格(#x20)字符。
注意,如果未经规范化的属性值中包含对空格字符(#x20)以外的空白字符的引用,那么规范化之后的值包含被引用的字符本身(#xD, #xA or
#x9),而不是空格(#x20)。这与未经规范化的属性值中包含空白字符(不是引用)的情况不同,在那种情况下空白字符被置换成空格字符(#x20)。同时这也与未经规范化的属性值中所包含的实体引用的置换文本中包含空白字符的的情况不同,在那种情况下,实体引用的置换文本被递归处理,空白字符被置换成空格字符(#x20)。
不进行验证的处理器应该将所有尚未读到其声明的属性当成声明为 CDATA 处理。
以下是属性规范化的例子。有如下声明:
<!ENTITY d "
"> <!ENTITY a "
"> <!ENTITY da "
"> |
下表中左边一列中的属性值说明在 a 声明为 NMTOKENS 的情况下规范化为中间一列的字符序列,在 a 声明为 CDATA 的情况下规范化为右边一列中的字符序列。
属性值说明 | a 声明为 NMTOKENS | a 声明为 CDATA |
a=" xyz" |
x y z |
#x20 #x20 x y z |
a="&d;&d;A&a;&a;B&da;" | A #x20 B | #x20 #x20 A #x20 #x20 B #x20 #x20 |
a="

A

B
" | #xD #xD A #xA #xA B #xD #xA | #xD #xD A #xA #xA B #xD #xD |
注意,在 a 声明为 NMTOKENS 类型的情况下,最后一个例子不是有效的(但是是格式正确的)。
3.4 条件段(Conditional Sections)
[定义:条件段是文件类型声明外部子集的一部分,取决于相应的关键字,它们或被包含在 DTD 逻辑结构之内,或被排除在 DTD 逻辑结构之外。]
条件段
[61] conditionalSect ::= includeSect | ignoreSect
[62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>' /* */
[VC: 严格的条件段/参数实体嵌套]
[63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>' /*
*/
[VC: 严格的条件段/参数实体嵌套]
[64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>'
Ignore)*
[65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
有效性约束: 严格的条件段/参数实体嵌套
如果一个条件段的 "<![","[" 或 "]]>" 中的任意一个包含在一个参数实体中的置换文本中,它们必须全部在此同一置换文本中。
同内部或外部 DTD 子集一样,条件段可以包含一个或多个完整的声明,注释,处理指令,或嵌套的条件段,其间可以夹杂空白。
如果条件段的关键字是 INCLUDE,那么条件段的内容是 DTD 的一部分,如果条件段的关键字是 IGNORE,那么条件段的内容逻辑上不是 DTD
的一部分。如果一个关键字为 INCLUDE 的条件段出现在更大的关键字为 IGNORE
的条件段中,内外两个条件段都被忽略。在对被忽略的条件段的内容进行语法分析时,从紧随关键字的 "[" 之后开始,除了条件段的开始 "<![" 和结尾 "]]>"
以外的所有字符都被忽略,直到找到相匹配的条件段结尾。在此过程中参数实体不被识别。
如果条件段的关键字是一个参数实体引用,处理器在决定是否包含或忽略此条件段前,必须先将该参数实体置换成其内容。
一个例子:
<!ENTITY % draft 'INCLUDE' > <!ENTITY % final 'IGNORE' > <![%draft;[ <!ELEMENT book (comments*, title, body, supplements?)> ]]> <![%final;[ <!ELEMENT book (title, body, supplements?)> ]]> |
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com