本文摘自: http://lightning.prohosting.com/~qqiu 译者:裘强 (
[email protected])
3. 逻辑结构 3.1 起始标签,结束标签和空元素标签 3.2 元素类型声明 3.2.1 元素型内容 3.2.2 混合型内容 3.3 属性表声明 3.3.1 属性类型 3.3.2 属性的缺省值 3.3.3 属性-值对的规范化 3.4 条件段
[定义:每个 XML 文件包含一个或多个元素,它们的边界用起始标签和结束标签分隔,或者,对于空元素,用一个空元素标签分隔。每一个元素有一个用名字标识的类型,有时称之为它的""通用标识符(generic identifier)""(GI),同时它可以有一个属性值说明(attribute specification)集。] 每一个属性值说明有一个名字和一个值。
元素
[39] element ::= EmptyElemTag
| STag content ETag [WFC: 元素类型匹配]
[VC: 元素有效性]
除了那些开头匹配((''X''|''x'')(''M''|''m'')(''L''|''l''))的名字保留用于本规范的此版本和后继版本的标准化外,本规范不对元素类型和属性的语义,用法和名字(语法之外)作出限制。
格式正确性约束: 元素类型匹配 元素结束标签中的 Name 必须和起始标签中的元素类型相匹配。
有效性约束: 元素有效性 如果有一个与 elementdecl 相匹配的声明的 Name 与元素类型相匹配,且下述之一成立时,称此元素是有效的:
此声明与 EMPTY 相匹配,同时此元素没有内容。
此声明与 children 相匹配,同时子元素的序列属于内容模型中的正则表达式所产生的语言,在起始标签和第一个子元素之间,子元素之间以及最后一个子元素和结束标签之间允许有空白(匹配非终结符 S 的字符)。注意,仅包括空白的 CDATA 段不匹配非终结符 S,因此不能在这些位置出现。
此声明与 Mixed 相匹配,同时内容由其类型匹配内容模型中的名字的字符数据和子元素组成。
此声明与 ANY 相匹配,同时每个子元素的类型均已声明。
3.1 起始标签,结束标签和空元素标签
[定义:每一个非空 XML 元素以一个起始标签作为开始的标记。]
起始标签
[40] STag ::= ''<'' Name (S Attribute)* S? ''>'' [WFC: 唯一的属性值说明]
[41] Attribute ::= Name Eq AttValue [VC: 属性值类型]
[WFC: 无外部实体引用]
[WFC: 在属性值中没有<]
起始标签和结束标签中的 Name 给出了元素的类型。[定义:Name-AttValue 对被统称为元素的属性值说明],[定义:其中每一对中的 Name 被称为属性名],[定义:AttValue 的内容(在''或""定界符间的文本)被称为属性值]。注意,在起始标签和空元素标签中各个属性值声明的次序没有意义。
格式正确性约束: 唯一的属性值说明 一个属性名只能在同一个起始标签或空元素标签中出现一次。
有效性约束: 属性值类型 属性必须被声明,其值必须具有所声明的类型。(属性类型参见""3.3 属性表声明""。)
格式正确性约束: 无外部实体引用 属性值不能包含对外部实体直接或间接的实体引用。
格式正确性约束: 在属性值中没有 < 在一个属性值中直接或间接引用的实体的置换文本不能包含 < 。
起始标签的一个例子:
[定义:由一个起始标签开始的每一个元素必须用一个结束标签标记其结束,结束标签中的名字必须与起始标签中给出的元素类型相同:]
结束标签
[42] ETag ::= ''Name S? ''>''
结束标签的一个例子:
[定义:在起始标签和结束标签中的文本被称为元素的内容:]
元素的内容
[43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)* /* */
[定义:称没有内容的元素其内容为空。] 空元素可以用一个起始标签紧跟一个结束标签的方式或空元素标签来表示。[定义:空元素标签有一种特殊的形式:]
空元素标签
[44] EmptyElemTag ::= ''<'' Name (S Attribute)* S? ''/>'' [WFC: 唯一的属性值说明]
不论元素是否用关键字 EMPTY 声明,空元素标签都可以用于任何没有内容的元素。出于互操作性考虑,空元素应该用于,且只应用于声明为 EMPTY 的元素。
空元素的例子:
3.2 元素类型声明
出于验证的目的,可以用元素类型和属性表声明限制 XML 文件中元素的结构。元素类型声明限制了元素的内容。
元素类型声明通常限制了子元素的类型。由使用者选择,当声明提到的元素类型没有相应的声明时,XML 处理器可以给出警告,但这不是一个错误。
[定义:元素类型声明的形式如下:]
元素类型声明
[45] elementdecl ::= ''S Name S contentspec S? ''>'' [VC: 唯一的元素类型声明]
[46] contentspec ::= ''EMPTY'' | ''ANY'' | Mixed | children
其中 Name 给出了所声明的元素类型。
有效性约束: 唯一的元素类型声明 元素类型只能声明一次。
元素类型声明的例子:
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语法成分中时,它的置换文本至少应该包含一个非空字符,同时其置换文本的第一个和最后一个非空字符都不应为一个连接符(| 或 ,)。
元素型内容的模型举例:
:]ode>
3.2.2 混合型内容(Mixed Content)
[定义:当某元素类型可以包含字符数据,其间可以随意穿插子元素时,称此元素类型具有混合型内容。] 在这种情况下,对子元素的类型可能有所限制,但对它们的次序和出现次数没有限制:
混合型内容声明
[51] Mixed ::= ''('' S? ''#PCDATA'' (S? ''|'' S? Name)* S? '')*''
| ''('' S? ''#PCDATA'' S? '')'' [VC: 严格的组/参数实体嵌套]
[VC: 无重复类型]
其中 Name 给出了子元素的元素的类型。关键字 #PCDATA 来自术语""已析字符数据(parsed character data)""而来
有效性约束: 无重复类型 同一名字在单个混合型内容声明中只能出现一次。
混合内容声明的例子:
3.3 属性表声明
属性用于关联名字-值对和元素。属性值说明只能在起始标签和空元素标签中出现; 因此,用于识别它们的产生式出现在""3.1 起始标签,结束标签和空元素标签""中。属性表声明可以用于:
定义与一给定元素类型有关的属性集。
确定这些属性的类型限制。
提供属性的缺省值。
[定义:属性表声明详细说明了与给定元素类型相关联的每一个属性的名字,数据类型和缺省值(如果有的话):]
属性表声明
[52] AttlistDecl ::= ''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: 名字记号]
有效性约束: ID ID 类型的值必须匹配 Name 产生式。作为此类型值的名字只能在 XML 文件中出现一次;即,ID 类型的值必须能唯一标识元素。
有效性约束: 每种属性类型一个ID 每种属性类型只能有一个 ID 属性。
有效性约束: ID 属性的缺省值 ID 属性必须有一个声明为 #IMPLIED 或 #REQUIRED 的缺省值。
有效性约束: IDREF IDREF 类型的值必须匹配 Name 产生式,IDREFS 类型的值必须匹配 Names 产生式;每一个 Name 必须匹配 XML 文件中某些元素 ID 属性的值;也就是说,IDREF 类型的值必须匹配某些 ID 属性的值。
有效性约束: 实体名 ENTITY 类型的值必须匹配 Name 产生式,ENTITIES 类型的值必须匹配 Names 产生式;每一个 Name 必须匹配 DTD 中声明的未析实体的名字。
有效性约束: 名字记号 NMTOKEN 类型的值必须匹配 Nmtoken 产生式;NMTOKENS 类型的值必须匹配 Nmtokens 产生式。
[定义:枚举类型的属性可以在声明中提供的取值表中取值。] 有两种枚举类型:
枚举属性类型
[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 中声明。
有效性约束: 记法属性 此类型的值必须与声明中所包含的记法名之一相匹配;声明中的所有记法名都必须声明。
有效性约束: 每种属性类型一种记法
每种元素类型的 NOTATION 属性不能多于一个。
有效性约束: 空元素没有记法
出于兼容性考虑,声明为 EMPTY 的元素不能声明类型为 NOTATION 的属性。
有效性约束: 枚举 此类型的值必须与声明中所包含的 Nmtoken 记号之一相匹配。
出于互操作性考虑,同一 Nmtoken 只能在单个元素类型的枚举属性类型中出现一次。
3.3.2 属性缺省值
属性声明提供的信息指明了某属性是否必须出现,同时指明了在被声明的属性不是必须出现而文件中没有出现此属性的情况下,XML 处理器应如何处理。
属性缺省值
[60] DefaultDecl ::= ''#REQUIRED'' | ''#IMPLIED''
| ((''#FIXED'' S)? AttValue) [VC: 必须的属性]
[VC: 合法的属性缺省值]
[WFC: 在属性值中无 < ]
[VC: 固定的属性缺省值]
在一个属性声明中,#REQUIRED 表示必须总是提供此属性,#IMPLIED 表示不提供缺省值。如果声明既不是 #REQUIRED,也不是 #IMPLIED,那么 AttValue 值包含了所声明的缺省值;关键字 #FIXED 规定此属性必须总是有缺省值。如果声明了一个缺省值,当 XML 处理器遇到一个被省略的属性时,它将当成此属性以缺省值出现
有效性约束: 必须的属性 如果缺省值声明是关键字 #REQUIRED,那么属性表声明所指类型的元素中都必须有此属性。
有效性约束: 合法的属性缺省值 被声明的属性缺省值必须满足被声明的属性类型的词法约束。
有效性约束: 固定的属性缺省值 如果某属性的缺省值用关键字 #FIXED 声明,此属性的所有实例必须匹配该缺省值。
属性表声明的例子:
3.3.3 属性-值对的规范化(Attribute-Value Normalization)
在将属性的值传给应用或检验其有效性之前,XML 处理器必须使用下面的算法(或使用其他能使传给应用的值与用此算法得到的值相同的方法)将其规范化。
所有的行尾必须在输入时如 2.11 行尾处理中所述规范成 #xA,本算法的其余部分作用于以此方法规范化之后的文本。
开始时规范化之后的值包含空字符串。
对于未经规范化的属性值中的每个字符,实体引用或字符引用,从第一个开始,直到最后一个,做如下操作:
对于一个字符引用,将其所引用的字符加在规范化之后的值的末尾。
对于一个实体引用,对此实体的置换文本递归地使用本算法的第 3 步。
对于一个空白字符(#x20, #xD, #xA, #x9),在规范化之后的值的末尾加一个空格字符(#x20)。
对于其他字符,将其加在规范化之后的值的末尾。
如果属性值的类型不是 CDATA,那么 XML 处理器必须继续处理规范化之后的值,去掉其前导和尾随空格(#x20)字符,并将空格(#x20)字符序列替换成单个空格(#x20)字符。
注意,如果未经规范化的属性值中包含对空格字符(#x20)以外的空白字符的引用,那么规范化之后的值包含被引用的字符本身(#xD, #xA or #x9),而不是空格(#x20)。这与未经规范化的属性值中包含空白字符(不是引用)的情况不同,在那种情况下空白字符被置换成空格字符(#x20)。同时这也与未经规范化的属性值中所包含的实体引用的置换文本中包含空白字符的的情况不同,在那种情况下,实体引用的置换文本被递归处理,空白字符被置换成空格字符(#x20)。
不进行验证的处理器应该将所有尚未读到其声明的属性当成声明为 CDATA 处理。
以下是属性规范化的例子。有如下声明:
下表中左边一列中的属性值说明在 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 ::= ''extSubsetDecl '']]>'' /* */
[VC: 严格的条件段/参数实体嵌套]
[63] ignoreSect ::= ''ignoreSectContents* '']]>'' /* */
[VC: 严格的条件段/参数实体嵌套]
[64] ignoreSectContents ::= Ignore (''ignoreSectContents '']]>'' Ignore)*
[65] Ignore ::= Char* - (Char* ('''') Char*)
有效性约束: 严格的条件段/参数实体嵌套
如果一个条件段的 """",""["" 或 ""]]>"" 中的任意一个包含在一个参数实体中的置换文本中,它们必须全部在此同一置换文本中。
同内部或外部 DTD 子集一样,条件段可以包含一个或多个完整的声明,注释,处理指令,或嵌套的条件段,其间可以夹杂空白。
如果条件段的关键字是 INCLUDE,那么条件段的内容是 DTD 的一部分,如果条件段的关键字是 IGNORE,那么条件段的内容逻辑上不是 DTD 的一部分。如果一个关键字为 INCLUDE 的条件段出现在更大的关键字为 IGNORE 的条件段中,内外两个条件段都被忽略。在对被忽略的条件段的内容进行语法分析时,从紧随关键字的 ""["" 之后开始,除了条件段的开始 """" 和结尾 ""]]>"" 以外的所有字符都被忽略,直到找到相匹配的条件段结尾。在此过程中参数实体不被识别。
如果条件段的关键字是一个参数实体引用,处理器在决定是否包含或忽略此条件段前,必须先将该参数实体置换成其内容。
一个例子:
]]> ]]>