[定義:每個 XML 文件包含一個或多個元素,它們的邊界用起始標簽和結束標簽分隔,或者,對於空元素,用一個空元素標簽分隔。每一個元素有一個用名字標識的類型,有時稱之為它的"通用標識符(generic identifIEr)"(GI),同時它可以有一個屬性值說明(attribute specification)集。] 每一個屬性值說明有一個名字和一個值。
element
::= EmptyElemTag
| STag content ETag
[WFC: 元素類型匹配] [VC: 元素有效性]
除了那些開頭匹配(('X'|'x')('M'|'m')('L'|'l'))
的名字保留用於本規范的此版本和後繼版本的標准化外,本規范不對元素類型和屬性的語義,用法和名字(語法之外)作出限制。
格式正確性約束: 元素類型匹配 元素結束標簽中的 Name
必須和起始標簽中的元素類型相匹配。
有效性約束: 元素有效性 如果有一個與 elementdecl
相匹配的聲明的 Name
與元素類型相匹配,且下述之一成立時,稱此元素是有效的:
children
相匹配,同時子元素的序列屬於內容模型中的正則表達式所產生的語言,在起始標簽和第一個子元素之間,子元素之間以及最後一個子元素和結束標簽之間允許有空白(匹配非終結符 S
的字符)。注意,僅包括空白的 CDATA 段不匹配非終結符 S
,因此不能在這些位置出現。
Mixed
相匹配,同時內容由其類型匹配內容模型中的名字的字符數據和子元素組成。
[定義:每一個非空 XML 元素以一個起始標簽作為開始的標記。]
STag
::= '<' Name (S Attribute)* S? '>'
[WFC: 唯一的屬性值說明] [41] Attribute
::= Name Eq AttValue
[VC: 屬性值類型] [WFC: 無外部實體引用] [WFC: 在屬性值中沒有<]
起始標簽和結束標簽中的 Name
給出了元素的類型。[定義:Name
-AttValue
對被統稱為元素的屬性值說明],[定義:其中每一對中的 Name
被稱為屬性名],[定義:AttValue
的內容(在'
或"
定界符間的文本)被稱為屬性值]。注意,在起始標簽和空元素標簽中各個屬性值聲明的次序沒有意義。
格式正確性約束: 唯一的屬性值說明 一個屬性名只能在同一個起始標簽或空元素標簽中出現一次。
有效性約束: 屬性值類型 屬性必須被聲明,其值必須具有所聲明的類型。(屬性類型參見"3.3 屬性表聲明"。)
格式正確性約束: 無外部實體引用 屬性值不能包含對外部實體直接或間接的實體引用。
格式正確性約束: 在屬性值中沒有 <
在一個屬性值中直接或間接引用的實體的置換文本不能包含 <
。
起始標簽的一個例子:
[定義:由一個起始標簽開始的每一個元素必須用一個結束標簽標記其結束,結束標簽中的名字必須與起始標簽中給出的元素類型相同:]
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
::= ''
[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>
[定義:當某元素類型可以包含字符數據,其間可以隨意穿插子元素時,稱此元素類型具有混合型內容。] 在這種情況下,對子元素的類型可能有所限制,但對它們的次序和出現次數沒有限制:
[51] Mixed
::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*'
| '(' S? '#PCDATA' S? ')'
[VC: 嚴格的組/參數實體嵌套] [VC: 無重復類型]
其中 Name
給出了子元素的元素的類型。關鍵字 #PCDATA 來自術語"已析字符數據(parsed character data)"而來
有效性約束: 無重復類型 同一名字在單個混合型內容聲明中只能出現一次。
混合內容聲明的例子:
屬性用於關聯名字-值對和元素。屬性值說明只能在起始標簽和空元素標簽中出現; 因此,用於識別它們的產生式出現在"3.1 起始標簽,結束標簽和空元素標簽"中。屬性表聲明可以用於:
[定義:屬性表聲明詳細說明了與給定元素類型相關聯的每一個屬性的名字,數據類型和缺省值(如果有的話):]
[52] AttlistDecl
::= ''
[53] AttDef
::= S Name S AttType S DefaultDecl
AttlistDecl
規則中 Name
是元素的類型。由使用者選擇,當屬性聲明相關的元素類型沒有被聲明時,XML 處理器可以給出一個警告,但這不是一個錯誤。AttDef
規則中的 Name
是屬性的名字。
當與某個給定元素類型相關的 AttlistDecl
超過一個時,這些聲明中的內容被合並在一起。當給定元素類型的某個屬性的定義超過一個時,綁定第一個定義,其余定義被忽略。出於互操作性考慮,DTD 的作者可以這樣做:一個給定的元素類型至多有一個屬性表聲明,一個屬性表中一個給定的屬性名至多有一個屬性定義,每個屬性表聲明至少有一個屬性定義。出於互操作性考慮,當一個給定元素有超過一個的屬性表聲明或一個給定屬性有超過一個的屬性定義時,XML 處理器可以,由使用者選擇,給出警告,但這不是一個錯誤。
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
只能在單個元素類型的枚舉屬性類型中出現一次。
屬性聲明提供的信息指明了某屬性是否必須出現,同時指明了在被聲明的屬性不是必須出現而文件中沒有出現此屬性的情況下,XML 處理器應如何處理。
[60] DefaultDecl
::= '#REQUIRED' | '#IMPLIED'
| (('#FIXED' S)? AttValue)
[VC: 必須的屬性] [VC: 合法的屬性缺省值] [WFC: 在屬性值中無 < ] [VC: 固定的屬性缺省值]
在一個屬性聲明中,#REQUIRED 表示必須總是提供此屬性,#IMPLIED 表示不提供缺省值。如果聲明既不是 #REQUIRED,也不是 #IMPLIED,那麼 AttValue
值包含了所聲明的缺省值;關鍵字 #FIXED 規定此屬性必須總是有缺省值。如果聲明了一個缺省值,當 XML 處理器遇到一個被省略的屬性時,它將當成此屬性以缺省值出現
有效性約束: 必須的屬性 如果缺省值聲明是關鍵字 #REQUIRED,那麼屬性表聲明所指類型的元素中都必須有此屬性。
有效性約束: 合法的屬性缺省值 被聲明的屬性缺省值必須滿足被聲明的屬性類型的詞法約束。
有效性約束: 固定的屬性缺省值 如果某屬性的缺省值用關鍵字 #FIXED 聲明,此屬性的所有實例必須匹配該缺省值。
屬性表聲明的例子:
在將屬性的值傳給應用或檢驗其有效性之前,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 類型的情況下,最後一個例子不是有效的(但是是格式正確的)。
[定義:條件段是文件類型聲明外部子集的一部分,取決於相應的關鍵字,它們或被包含在 DTD 邏輯結構之內,或被排除在 DTD 邏輯結構之外。]
[61] conditionalSect
::= includeSect | ignoreSect
[62] includeSect
::= ''
/* */ [VC: 嚴格的條件段/參數實體嵌套] [63] ignoreSect
::= ''
/* */ [VC: 嚴格的條件段/參數實體嵌套] [64] ignoreSectContents
::= Ignore ('' Ignore)*
[65] Ignore
::= Char* - (Char* ('') Char*)
有效性約束: 嚴格的條件段/參數實體嵌套
如果一個條件段的 "","
[
" 或 "]]>
" 中的任意一個包含在一個參數實體中的置換文本中,它們必須全部在此同一置換文本中。
同內部或外部 DTD 子集一樣,條件段可以包含一個或多個完整的聲明,注釋,處理指令,或嵌套的條件段,其間可以夾雜空白。
如果條件段的關鍵字是 INCLUDE,那麼條件段的內容是 DTD 的一部分,如果條件段的關鍵字是 IGNORE,那麼條件段的內容邏輯上不是 DTD 的一部分。如果一個關鍵字為 INCLUDE 的條件段出現在更大的關鍵字為 IGNORE 的條件段中,內外兩個條件段都被忽略。在對被忽略的條件段的內容進行語法分析時,從緊隨關鍵字的 "[
" 之後開始,除了條件段的開始 "" 和結尾 "
]]>
" 以外的所有字符都被忽略,直到找到相匹配的條件段結尾。在此過程中參數實體不被識別。
如果條件段的關鍵字是一個參數實體引用,處理器在決定是否包含或忽略此條件段前,必須先將該參數實體置換成其內容。
一個例子:
]]> ]]>