本文档是 W3C 建议 XML 1.0 第二版(2000 年 10 月 6 日)的简体中文翻译版,其中可能有错误和不妥之处。
英文版是唯一的正式版,位于:
http://www.w3.org/TR/2000/REC-xml-20001006
本文档位于:
http://lightning.prohosting.com/~qqiu/REC-xml-20001006-cn.html
著作权声明位于:http://www.w3.org/Consortium/Legal/copyright-documents.html
Copyright © 1998 W3C® (MIT, INRIA, Keio ), All Rights Reserved. W3C liability, trademark, document use and software licensing rules apply.
本文档完整地描述了可扩展标记语言(Extensible Markup Language,XML),它是标准通用标记语言(Standard Generic Markup Language,SGML)的一个子集。其目的在于使得在 Web 上能以现有超文本标记语言(Hypertext Markup Language,HTML)的使用方式提供,接收和处理通用的 SGML 成为可能。XML 的设计既考虑了实现的方便性,同时也顾及了与 SGML 和 HTML 的互操作性。
本文档已由 W3C 组织成员和其他相关各方审阅,并已被组织理事批准为 W3C 建议。这是一份稳定的文档,可以用作参考材料,也可以作为其他文档的正式参考文献。W3C 在建议制定过程中的作用是吸引对本建议的注意并促进它的广泛使用。这能增强Web的功能和互操作性。
本文档规定了一种用于 World Wide Web 的语法,此语法是通过取一个业已存在并已广泛使用的文本处理国际标准(标准通用标记语言,经增补和更正的 ISO 8879:1986(E))的子集而创建的。它是 W3C XML 行动组(XML Activity)的工作成果,关于 XML 行动组的详细信息可以在 http://www.w3.org/XML 找到。英文版是唯一的正式版。本文档的翻译见 http://www.w3.org/XML/#trans。在 http://www.w3.org/TR 可以找到现有 W3C 建议和其他技术文档的一个列表。
XML 1.0 第二版不是 XML 的一个新版本(1998 年 2 月 10 日首次发表);它只是为了方便读者,并入了第一版勘误表中指出的错误和修改(在 http://www.w3.org/XML/xml-19980210-errata)。 本第二版的勘误表在 http://www.w3.org/XML/xml-V10-2e-errata。
请将本文档中的错误报告给 [email protected]。可以在此找到相关的存档。
注:
C. M. Sperberg-McQueen 在第一版发表之后供职之处已有变化。他现在供职于 W3C,可以通过 [email protected] 和他联系。
1. 绪论
1.1 开发者和开发目标
1.2 术语
2. 文件
2.1 格式正确的 XML 文件
2.2 字符
2.3 通用语法成分
2.4 字符数据和标记
2.5 注释
2.6 处理指令
2.7 CDATA 段
2.8 序言和文件类型声明
2.9 独立文件声明
2.10 空白处理
2.11 行尾处理
2.12 语言标识
3. 逻辑结构
3.1 起始标签,结束标签和空元素标签
3.2 元素类型声明
3.2.1 元素型内容
3.2.2 混合型内容
3.3 属性表声明
3.3.1 属性类型
3.3.2 属性的缺省值
3.3.3 属性-值对的规范化
3.4 条件段
4. 物理结构
4.1 字符和实体引用
4.2 实体声明
4.2.1 内部实体
4.2.2 外部实体
4.3 已析实体
4.3.1 文本声明
4.3.2 格式正确的已析实体
4.3.3 实体中的字符编码
4.4 XML 处理器对实体和引用的处理
4.4.1 不被识别
4.4.2 被包含
4.4.3 进行验证时被包含
4.4.4 被禁止
4.4.5 作为常量被包含
4.4.6 通知
4.4.7 不处理
4.4.8 作为参数实体被包含
4.5 内部实体置换文本的构建
4.6 预定义实体
4.7 记法声明
4.8 文件实体
5. 一致性
5.1 进行验证和不进行验证的处理器
5.2 使用 XML 处理器
6. 记法
A. 参考文献
A.1 正式参考文献
A.2 其他参考文献
B. 字符的分类
C. XML 和 SGML(非正式)
D. 实体和字符引用的展开(非正式)
E. 确定型内容模型(非正式)
F. 字符编码的自动检测(非正式)
F.1 无外部编码信息时的检测
F.2 有外部编码信息时的优先级
G. W3C XML 工作组(非正式)
H. W3C XML 核心工作组(非正式)
I. 文档制作说明(非正式)
可扩展标记语言,缩写为 XML,描述了一类称为 XML 文件的数据对象,同时也部分地描述了处理这些数据对象的计算机程序的动作。XML 是 SGML(标准通用标记语言 [ISO 8879])针对特定应用领域的一个子集,或者说是 SGML 的一种受限形式。根据定义,XML 文件是合乎规范的 SGML 文件。
XML 文件由称为实体的存储单元组成,实体可以包含已析(parsed)数据或未析(unparsed)数据。已析数据由字符组成,其中一些字符组成字符数据,另一些字符组成标记。标记中包含了对文件存储格式(storage layout)和逻辑结构的描述。XML 提供了一种机制用于约束存储格式和逻辑结构。
[定义:称为 XML 处理器的软件模块用于读取 XML 文件,存取其中的内容和结构。] [定义:XML 处理器被设想为是为另一个称为应用的模块作处理。] 本规范从 XML 处理器应如何读取 XML 数据以及应向应用提供哪些信息的这两个方面,描述了要求 XML 处理器作出的动作。
XML 由 XML 工作组(原先的 SGML 编辑审查委员会)开发,此工作组由 World Wide Web Consortium (W3C) 在 1996 年主持成立。工作组由 Sun Microsystems 的 Jon Bosak 负责,同样由 W3C 组织的 XML SIG (Special Interest Group)(原先的 SGML 工作组)积极参与了 XML 工作组的工作。XML 工作组的成员在附录中给出。 工作组与 W3C 的联系人是 Dan Connolly。
XML 的设计目标如下:
本规范与其他相关的标准一起(Unicode 和 ISO/IEC 10646 定义了字符集,Internet RFC1766 定义了语言识别码,ISO 639 定义了语言名称代码,ISO 3166 定义了国家名称代码),提供了理解 XML 版本 1.0 和构建相应计算机处理程序所需的所有信息。
在完整保留所有文本和法律注意事项的前提下,本版本的 XML 规范可以自由分发。
用于描述 XML 文件的术语在此规范的正文中定义。 在这些定义中以及描述一个 XML 处理器的动作时,使用了下表中的术语:
[定义:如果一个数据对象满足本规范中格式正确的之定义时,它是一个 XML 文件。一个格式正确的 XML 文件可以更进一步是有效的,如果它满足某些进一步的约束的话。]
每一个 XML 文件都有逻辑和物理结构。物理上而言,文件由称为实体的单元组成。一个实体可以引用(refer)其他实体,将它们包含在文件中。文件开始于"根(root)"或文件实体。逻辑上而言,文件由声明,元素,注释,字符引用和处理指令组成,所有这些都在文件中用显式标记指明。逻辑和物理结构必须如"4.3.2 格式正确的已析实体"中所描述的那样严格地嵌套。
[定义:一个文本对象是一个格式正确的 XML 文件如果它满足:]
document
产生式。[1] | document |
::= | prolog element Misc* |
匹配 document
产生式意味着:
[定义:这样做的结果是,对于每一个非根的元素 C
,文件中另有一个元素 P
,C
在 P
的内容中,而不在其他任何被 P
所包含的元素的内容中。P
被称为 C
的父元素(parent),而 C
被称为 P
的子元素(child)。]
[定义:一个已析实体包含文本(text),文本是一个字符(character)序列,可以表示标记或字符数据。] [定义:一个字符是 ISO/IEC 10646 [ISO/IEC 10646](或 [ISO/IEC 10646-2000])中定义的文本最小单元。合法的字符包括制表符,回车,换行以及 Unicode 和 ISO/IEC 10646 中定义的合法字符。在制定本文档时,在附录 A.1 正式参考文献中引用的标准都是当时的最新版本,在这些标准的增补版或新版中可能会加入新的字符。因此,XML 处理器必须能接受产生式 Char 中所定义范围内的任意字符。不提倡使用 [Unicode] 6.8 节(或 [Unicode3] 3.6 节 D21 )中定义的"兼容字符(compatibility characters)"。]
[2] | Char |
::= | #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] |
/* 除了代用块(surrogate block),FFFE 和 FFFF 以外的任意 Unicode 字符。*/ |
将字符代码编码成位模式的机制各个实体间可能会有所不同。所有的 XML 处理器必须接受 10646 中的 UTF-8 和 UTF-16 编码;用于指出所用编码或指定使用其他编码的机制在后面的"4.3.3 实体中的字符编码"中讨论。
本节中定义了一些在文法中广泛使用的符号。
S
(空白)包括一个或多个空格字符(#x20),回车,换行和制表符。
[3] | S |
::= | (#x20 | #x9 | #xD | #xA)+ |
为方便起见,字符被分为字母,数字和其他字符三类。字母可以是字母表中的字母,或是一个音节基字符(syllabic base character),也可以是一个表意字符。在"B. 字符的分类"中给出了每一类字符的完整定义。
[定义:名字(name)是以字母或某些标点符号开头的记号,后跟字母,数字,连字符,下划线,冒号或句号,这些符号统称为命名字符(name character)。] 以 "xml
" 或其他任何匹配 (('X'|'x') ('M'|'m') ('L'|'l'))
的字符串开头的名字,被保留用于本规范的此版本或后续版本的标准化。
注:
XML 建议中的名域 [XML Names] 赋予了包含冒号的名字某种含义。因此除非用于名域,XML 文件作者不应该在 XML 名字中使用冒号,但 XML 处理器应该接受冒号作为一个命名字符。
Nmtoken
(名字记号,name token)是任何命名字符的混合体。
[4] | NameChar |
::= | Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender |
[5] | Name |
::= | (Letter | '_' | ':') (NameChar)* |
[6] | Names |
::= | Name (S Name)* |
[7] | Nmtoken |
::= | (NameChar)+ |
[8] | Nmtokens |
::= | Nmtoken (S Nmtoken)* |
常量数据是任何用引号括起的字符串,不包括用作定界符的引号。常量用于指明内部实体的内容(EntityValue
),属性值(AttValue
),以及外部标识符(SystemLiteral
)。注意,对 SystemLiteral
的语法分析可以不扫描标记。
[9] | EntityValue |
::= | '"' ([^%&"] | PEReference | Reference)* '"' |
| "'" ([^%&'] | PEReference | Reference)* "'" |
|||
[10] | AttValue |
::= | '"' ([^<&"] | Reference)* '"' |
| "'" ([^<&'] | Reference)* "'" |
|||
[11] | SystemLiteral |
::= | ('"' [^"]* '"') | ("'" [^']* "'") |
[12] | PubidLiteral |
::= | '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" |
[13] | PubidChar |
::= | #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] |
注:
虽然产生式 EntityValue 允许定义只包含单个 <
的实体(如,<!ENTITY mylt "<">
),但是强烈建议避免这种用法,因为对此实体的任何引用都会引起一个格式正确性错误。
文本由字符数据和标记混合构成。[定义:标记包括起始标签,结束标签,空元素标签,实体引用,字符引用,注释,CDATA 段定界符,文件类型声明,处理指令,XML 声明,文本声明,以及任何在文件实体顶层的空白(即,在文件元素之外且不在任何其他的标记中)。]
[定义:其他所有非标记的文本组成文件的字符数据。]
"and"号(&)和左尖括号(<)只有作为标记定界符,或在注释,处理指令,或 CDATA 段中时才能以常量形式出现。如果在其他地方需要用到这两个字符,它们必须用数值式字符引用来转义或分别用字符串"&
"和"<
"表示。右尖括号(>)可以用">
"表示,而当它在内容中的字符串"]]>
"中出现,但此字符串不表示一个 CDATA 段的结束时,出于兼容性考虑,必须用">
"或一个字符引用转义得到。
在一个元素的内容中,字符数据可以是不包括任何标记的起始定界符的任意字符串。在一个 CDATA 段中,字符数据可以是不包括 CDATA 段结束定界符"]]>
"的任意字符串。
为了允许在属性值中包含单引号和双引号,省略符或称单引号(')可以被表示为"'
",而双引号(")可以被表示为""
"。
[14] | CharData |
::= | [^<&]* - ([^<&]* ']]>' [^<&]*) |
[定义:注释可以在其他标记之外的文件中的任何位置出现。另外,它们可以在文件类型声明中文法允许的地方出现。它们不是文件字符数据的一部分,XML 处理器可以,但不是必须,允许一个应用检索注释的文本。出于兼容性考虑,字符串"--
"(双连字符)不能在注释中出现。] 注释中的参数实体不被识别。
[15] | Comment |
::= | '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->' |
注释的一个例子:
<!-- declarations for <head> & <body> --> |
注意,此文法不允许注释以 --->
结尾。下面的例子不是格式正确的。
<!-- B+, B, or B---> |
[定义:处理指令(PI)允许文件中包含由应用来处理的指令。]
[16] | PI |
::= | '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>' |
[17] | PITarget |
::= | Name - (('X' | 'x') ('M' | 'm') ('L' | 'l')) |
PI 不是文件字符数据的一部分,但必须传递给应用。PI 以用于指示传递给哪个应用的目标(PITarget
)开头。目标名字 "XML
","xml
",等等,保留用于本规范的此版本或后续版本的标准化。XML 记法机制可以用于 PI 目标的形式化声明。参数实体在处理指令中不被识别。
[定义:CDATA 段可以出现在字符数据可以出现的任何地方,它们用于转义包含会被识别为标记的字符串的文本块。CDATA 段以字符串 "<![CDATA[
" 开始,以字符串 "]]>
" 结束:]
[18] | CDSect |
::= | CDStart CData CDEnd |
[19] | CDStart |
::= | '<![CDATA[' |
[20] | CData |
::= | (Char* - (Char* ']]>' Char*)) |
[21] | CDEnd |
::= | ']]>' |
在一个 CDATA 段内,只有 CDEnd
字符串被识别为标记,因此左尖括号和"&"可以以它们的常量形式出现,不需要(也不能)被换码为"<
"和"&
"。CDATA 段不能嵌套。
一个 CDATA 段的例子,其中"<greeting>
"和"</greeting>
"被识别为字符数据,而不是标记:
<![CDATA[<greeting>Hello, world!</greeting>]]> |
[定义:XML 文件应该以一个 XML 声明开始,其中指明了所用 XML 的版本。] 例如,以下是一个完整的 XML 文件,它是格式正确的,但不是有效的:
<?xml version="1.0"?> |
下面这个也同样:
<greeting>Hello, world!</greeting> |
版本号 "1.0
" 应该用于表明与本规范的本版本相一致,如果使用了值 "1.0
" 但又与本规范的本版本不一致,那么这是文件的一个错误。XML 工作组打算赋予本规范的后续版本不同于 "1.0
" 的数值,但这并不代表开发后续版本的承诺,也不代表如果有后续版本,会使用任何特殊的命名方案的承诺。因为不排除有后续版本的可能性,提供了本构造 (construct)作为一旦需要时进行自动版本识别的手段。当处理器收到的文件标有它们不支持的版本时,可以给出一个错误。
XML 文件中标记的功能是描述文件的存储格式和逻辑结构,并将属性-值对和逻辑结构关联起来。XML 提供一种称为文件类型声明的机制,用于定义对逻辑结构的约束,支持预定义存储单元的使用。[定义:如果一个 XML 文件有相应的文件类型声明并且它遵循其中的约束,则称它是有效的(valid)。]
文件类型声明必须位于文件第一个元素之前。
[22] | prolog |
::= | XMLDecl? Misc* (doctypedecl Misc*)? |
[23] | XMLDecl |
::= | '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' |
[24] | VersionInfo |
::= | S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')/* */ |
[25] | Eq |
::= | S? '=' S? |
[26] | VersionNum |
::= | ([a-zA-Z0-9_.:] | '-')+ |
[27] | Misc |
::= | Comment | PI | S |
[定义:XML 文件类型声明包含或指向标记声明,标记声明提供某一类文件的文法。这种文法被称为文件类型定义(document type difinition,DTD)。文件类型定义可以指向一个外部子集(一种特殊类型的外部实体),或者可以在一个内部子集中直接包含标记声明,或者两者兼用。一个文件的文件类型定义由这两个子集合在一起组成。]
[定义:标记声明可以是元素类型声明,属性表声明,实体声明,或是记法声明。] 这些声明可以如下面格式正确性和有效性约束中所述,全部或部分地包含在参数实体中,"4. 物理结构"中有更多的信息。
[28] | doctypedecl |
::= | '<!DOCTYPE' S Name (S ExternalID)? S? ('[' (markupdecl | DeclSep)* ']' S?)? '>' |
[VC: 根元素类型] |
[WFC: 外部子集] | ||||
/* */ | ||||
[28a] | DeclSep |
::= | PEReference | S |
[WFC: 声明间的参数实体] |
/* */ | ||||
[29] | markupdecl |
::= | elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment |
[VC: 严格的声明/参数实体嵌套] |
[WFC: 内部子集中的参数实体] |
注意,要构建包含了一个既不指向外部子集也不包含内部子集的 doctypedecl 而格式正确的文件是可能的。
标记声明可以全部或部分地由参数实体的置换文本组成。本规范后面的各个非终结符(elementdecl
,AttlistDecl
,等等)产生式描述的是在所有的参数实体被包含(include)之后的声明。
除了在常量,处理指令,注释和被忽略的条件段的内容中出现的参数实体引用以外,DTD 中的其他任何地方(内部或外部子集以及外部参数实体)的参数实体引用都被识别(见 3.4 条件段)。在实体值常量中的参数实体引用也被识别。内部子集中参数实体引用的使用限制如下所述。
有效性约束: 根元素类型(Root Element Type)
文件类型声明中的 Name
必须匹配根元素的类型。
有效性约束: 严格的声明/参数实体嵌套
参数实体的置换文本必须用标记声明严格嵌套。即,如果一个标记声明(上面的 markupdecl
)的第一个或最后一个字符被包含于一个参数实体引用的置换文本中,两者必须都在此置换文本中。
格式正确性约束: 内部子集中的参数实体
在内部 DTD 子集中,参数实体引用只能出现在标记声明可以出现的地方,而不能在标记声明内部出现。(这个约束不适用于出现在外部参数实体内的引用,也不适用于外部子集。)
格式正确性约束: 外部子集
外部子集(如果有的话)必须匹配产生式 extSubset。
格式正确性约束: 声明间的参数实体
一个 DeclSep 内的参数实体引用的置换文本必须匹配产生式 extSubsetDecl。
同内部子集一样,外部子集和任何 DeclSep 中引用的外部参数实体,必须由一系列被非终结符 markupdecl
所允许的完整的标记声明组成,其中可以夹杂空白字符或参数实体引用。但是,外部子集和外部参数实体的部分内容可以通过使用条件段(conditional section)被有条件地忽略,在内部子集中则不允许这么做。
[30] | extSubset |
::= | TextDecl? extSubsetDecl |
|
[31] | extSubsetDecl |
::= | ( markupdecl | conditionalSect | DeclSep)* |
/* */ |
外部子集和外部参数实体与内部实体不同之处还在于:在它们内,参数实体引用不仅可以出现在标记声明间,还可以出现在标记声明内。
有文件类型声明的 XML 文件的例子:
<?xml version="1.0"?> |
系统标识符 "hello.dtd
" 给出了此文件的 DTD 的地址(一个 URI 引用)。
声明也可以如同下面这个例子一样直接(locally)给出:
<?xml version="1.0" encoding="UTF-8" ?> |
如果同时使用外部和内部子集,子集子集被看成出现在外部子集之前,这意味着内部子集中的实体和属性表声明的优先级要比在外部子集中的高。
当文件从 XML 处理器递给应用时,标记声明可以影响它的内容,属性缺省值和实体声明是其中的例子。可以作为 XML 声明一个成分的独立文件声明,指明了是否存在着在文件实体外或在参数实体中的声明。[定义:外部标记声明被定义为出现在外部子集或参数实体(外部或内部,包括内部参数实体是因为并不强制不进行验证的处理器读取其中的标记声明)中的标记声明。]
[32] | SDDecl |
::= | S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')) |
[VC: 独立文件声明] |
在一个独立文件声明中,值 "yes
" 表示对于文件实体没有外部标记声明(不论是在 DTD 外部子集中,还是在由内部实体引用的外部参数实体中)会影响从 XML 处理器传递给应用的信息。值 "no
" 表示有或可能有这样的外部标记声明。注意,独立文件声明只是表示外部声明的存在,如果文件中存在对外部实体的引用,而这些实体已在内部声明时,不影响它的独立状态。
如果不存在外部标记声明,独立文件声明没有意义。如果存在外部标记声明,但没有独立文件声明,就假定取值 "no
"。
某些网络传输应用也许需要独立的文件,任何满足 standalone="no"
的 XML 文件可以通过一定的算法转换为独立文件。
有效性约束: 独立文件声明
独立文件声明必须取值为 "no
",如果任何外部标记声明中包含:
amp
,lt
,gt
,apos
,quot
外的)实体的声明,而对这些实体的引用出现在文件中的话。具有独立文件声明的 XML 声明的例子:
<?xml version="1.0" standalone='yes'?> |
在编辑 XML 文件时,使用"空白"(空格,制表符,空行)来分开标记以获得更好的可读性是很方便的。通常在文件的交付版本中不想包含这些空白。另一方面,必须保留在交付版本中的有意义的空白是很常见的,如在诗歌和源码中的空白。
XML 处理器必须始终把不是标记的所有字符传递给应用。 一个进行验证的 XML 处理器必须同时通知应用这些字符中的那一些组成了出现在元素型内容中的空白。
可以在元素中附加一个名为 xml:space
的特殊属性,以通知应用应该保留此元素中的空白。在有效的文件中,此属性和其他属性一样,使用时必须声明。它必须被声明为枚举类型,可以取值 "default
" 和 "preserve
" 两者之一,也可以两个都取。例如:
<!ATTLIST poem xml:space (default|preserve) 'preserve'> |
"default
" 表示可以对此元素使用应用的缺省空白处理模式,"preserve
" 表示应用应该保留所有的空白。这适用于其所处元素的内容中的所有元素,除非被另一个 xml:space
属性的实例所覆盖。
任何文件的根元素被认为对应用的空白处理方式不作要求,除非它给此属性赋了值或将此属性声明为带缺省值。
为编辑的方便起见,存储 XML 已析实体的计算机文件经常用行来组织。通常这些行用回车符(#xD)和换行符(#xA)的一些组合来分隔。
为了使应用的工作简单化,XML 处理器应在将字符传给应用前,将外部已析实体(包括文件实体)中的两字符序列 "#xD#xA" 或没有尾随 #xA 的 #xD 在进行语法分析前转换成单个 #xA 字符。在进行文件处理时,标识出其内容所使用的自然或形式化语言经常是很有用的。可以在文件中插入一个名为 xml:lang
的特殊属性用于指出 XML 文件中任何元素的内容和属性所使用的语言。在有效的文件中,此属性和其他属性一样,使用时必须声明。此属性的值是 [IETF RFC 1766],Tags for the Identification of Languages 或其后的 ITEF 标准中定义的语言标识符。
注:
[IETF RFC 1766] 中的标签由 [ISO 639] 中定义的两字母语言码和 [ISO 3166] 中定义的两字母国家码构成,或者由 Internet Assigned Numbers Authority [IANA-LANGCODES] 注册的语言标识符构成。 预计 [IETF RFC 1766] 的后继标准将会引入三字母语言码用于表示 [ISO 639] 中没有涉及的语言。
(产生式 33 到 38 已被删除。)
举例如下:
<p xml:lang="en">The quick brown fox jumps over the lazy dog.</p> |
xml:lang
所表示的语言选择适用于它所处元素的所有属性和内容,除非被此内容中的元素内的另一个 xml:lang
的实例所覆盖。
xml:lang
的一个简单声明可以采用如下形式:
xml:lang NMTOKEN #IMPLIED |
但是如果合适的话,也可以给出特定的缺省值。在一本供英国学生使用的法文诗歌集中,评注和注解使用英语,xml:lang 属性可以这样声明:
<!ATTLIST poem xml:lang NMTOKEN 'fr'> |
[定义:每个 XML 文件包含一个或多个元素,它们的边界用起始标签和结束标签分隔,或者,对于空元素,用一个空元素标签分隔。每一个元素有一个用名字标识的类型,有时称之为它的"通用标识符(generic identifier)"(GI),同时它可以有一个属性值说明(attribute specification)集。] 每一个属性值说明有一个名字和一个值。
[39] | element |
::= | EmptyElemTag |
|
| STag content ETag |
[WFC: 元素类型匹配] | |||
[VC: 元素有效性] |
除了那些开头匹配(('X'|'x')('M'|'m')('L'|'l'))
的名字保留用于本规范的此版本和后继版本的标准化外,本规范不对元素类型和属性的语义,用法和名字(语法之外)作出限制。
格式正确性约束: 元素类型匹配
元素结束标签中的 Name
必须和起始标签中的元素类型相匹配。
有效性约束: 元素有效性
如果有一个与 elementdecl
相匹配的声明的 Name
与元素类型相匹配,且下述之一成立时,称此元素是有效的:
children
相匹配,同时子元素的序列属于内容模型中的正则表达式所产生的语言,在起始标签和第一个子元素之间,子元素之间以及最后一个子元素和结束标签之间允许有空白(匹配非终结符 S
的字符)。注意,仅包括空白的 CDATA 段不匹配非终结符 S
,因此不能在这些位置出现。 Mixed
相匹配,同时内容由其类型匹配内容模型中的名字的字符数据和子元素组成。[定义:每一个非空 XML 元素以一个起始标签作为开始的标记。]
[40] | STag |
::= | '<' Name (S Attribute)* S? '>' |
[WFC: 唯一的属性值说明] |
[41] | Attribute |
::= | Name Eq AttValue |
[VC: 属性值类型] |
[WFC: 无外部实体引用] | ||||
[WFC: 在属性值中没有<] |
起始标签和结束标签中的 Name
给出了元素的类型。[定义:Name
-AttValue
对被统称为元素的属性值说明],[定义:其中每一对中的 Name
被称为属性名],[定义:AttValue
的内容(在'
或"
定界符间的文本)被称为属性值]。注意,在起始标签和空元素标签中各个属性值声明的次序没有意义。
格式正确性约束: 唯一的属性值说明
一个属性名只能在同一个起始标签或空元素标签中出现一次。
有效性约束: 属性值类型
属性必须被声明,其值必须具有所声明的类型。(属性类型参见"3.3 属性表声明"。)
格式正确性约束: 无外部实体引用
属性值不能包含对外部实体直接或间接的实体引用。
格式正确性约束: 在属性值中没有 <
在一个属性值中直接或间接引用的实体的置换文本不能包含 <
。
起始标签的一个例子:
<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" |
出于验证的目的,可以用元素类型和属性表声明限制 XML 文件中元素的结构。元素类型声明限制了元素的内容。
元素类型声明通常限制了子元素的类型。由使用者选择,当声明提到的元素类型没有相应的声明时,XML 处理器可以给出警告,但这不是一个错误。
[定义:元素类型声明的形式如下:]
[45] | elementdecl |
::= | '<!ELEMENT' S Name S contentspec S? '>' |
[VC: 唯一的元素类型声明] |
[46] | contentspec |
::= | 'EMPTY' | 'ANY' | Mixed | children |
其中 Name
给出了所声明的元素类型。
有效性约束: 唯一的元素类型声明
元素类型只能声明一次。
元素类型声明的例子:
<!ELEMENT br EMPTY> |
[定义:当某一类型的元素只能包含用可选空白(匹配非终结符 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?)> |
[定义:当某元素类型可以包含字符数据,其间可以随意穿插子元素时,称此元素类型具有混合型内容。] 在这种情况下,对子元素的类型可能有所限制,但对它们的次序和出现次数没有限制:
[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)*> |
属性用于关联名字-值对和元素。属性值说明只能在起始标签和空元素标签中出现; 因此,用于识别它们的产生式出现在"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 处理器可以,由使用者选择,给出警告,但这不是一个错误。
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 声明,此属性的所有实例必须匹配该缺省值。
属性表声明的例子:
<!ATTLIST termdef |
在将属性的值传给应用或检验其有效性之前,XML 处理器必须使用下面的算法(或使用其他能使传给应用的值与用此算法得到的值相同的方法)将其规范化。
所有的行尾必须在输入时如 2.11 行尾处理中所述规范成 #xA,本算法的其余部分作用于以此方法规范化之后的文本。
开始时规范化之后的值包含空字符串。
对于未经规范化的属性值中的每个字符,实体引用或字符引用,从第一个开始,直到最后一个,做如下操作:
对于一个字符引用,将其所引用的字符加在规范化之后的值的末尾。
对于一个实体引用,对此实体的置换文本递归地使用本算法的第 3 步。
对于一个空白字符(#x20, #xD, #xA, #x9),在规范化之后的值的末尾加一个空格字符(#x20)。
对于其他字符,将其加在规范化之后的值的末尾。
如果属性值的类型不是 CDATA,那么 XML 处理器必须继续处理规范化之后的值,去掉其前导和尾随空格(#x20)字符,并将空格(#x20)字符序列替换成单个空格(#x20)字符。
注意,如果未经规范化的属性值中包含对空格字符(#x20)以外的空白字符的引用,那么规范化之后的值包含被引用的字符本身(#xD, #xA or #x9),而不是空格(#x20)。这与未经规范化的属性值中包含空白字符(不是引用)的情况不同,在那种情况下空白字符被置换成空格字符(#x20)。 同时这也与未经规范化的属性值中所包含的实体引用的置换文本中包含空白字符的的情况不同,在那种情况下,实体引用的置换文本被递归处理,空白字符被置换成 空格字符(#x20)。
不进行验证的处理器应该将所有尚未读到其声明的属性当成声明为 CDATA 处理。
以下是属性规范化的例子。有如下声明:
<!ENTITY d "
"> |
下表中左边一列中的属性值说明在 a
声明为 NMTOKENS 的情况下规范化为中间一列的字符序列,在 a
声明为 CDATA 的情况下规范化为右边一列中的字符序列。
属性值说明 | a 声明为 NMTOKENS | a 声明为 CDATA | |
---|---|---|---|
|
x y z |
#x20 #x20 x y z |
|
|
A #x20 B |
#x20 #x20 A #x20 #x20 B #x20 #x20 |
|
|
#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 |
::= | '<![' 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' > |
[定义:一个 XML 文件可能包含一个或多个存储单元。它们被称为实体(entity);它们都具有内容并且都用名字进行标识(除了文件实体,见下,和外部 DTD 子集之外)。] 每一个 XML 文件有一个称为文件实体的实体,它作为 XML 处理器处理的起点并可能包含了整个文件。
实体可以是已析的或未析的。[定义:已析实体(parsed entity)的内容被称为它的置换文本;此文本被看成是文件整体的一部分。]
未析实体(unparsed entity)是一种资源,其内容可以是也可以不是文本,并且,如果是文本的话,可以不是 XML 文本。每一个未析实体有一个相关联的用名字标识的记法。除了要求 XML 处理器能向应用提供实体和记法的标识符之外,XML 对未析实体的内容不作任何限制。]
已析实体以实体引用的方式使用名字来调用;未析实体用 ENTITY 或 ENTITIES 属性中给出的名字调用。
[定义:普通实体(general entity)是那些在文件内容中使用的实体。在本规范中,普通实体有时用未修饰的术语entity来表示。] [定义:参数实体是用于 DTD 内的已析实体。]这两类实体用不同形式的引用,在不同的上下文中识别。另外,它们使用不同的名域;具有相同名字的参数实体和普通实体是两个截然不同的两个实体。
一个字符引用引用 ISO/IEC 10646 字符集中的一个字符。例如不能用输入设备直接输入的字符。
[66] | CharRef |
::= | '&#' [0-9]+ ';' |
|
| '&#x' [0-9a-fA-F]+ ';' |
[WFC: 合法字符] |
格式正确性约束: 合法字符
用字符引用引用的字符必须匹配 Char 产生式。
如果字符引用以 "&#x
" 开头,直到终结 ;
的数字和字母提供了某字符在 ISO/IEC 10646 中代码的一个十六进制表示。如果它仅以 "&#
" 开头,直到终结 ;
的数字提供了某字符的代码的十进值表示。
实体引用(entity reference)引用一个命名实体的内容。对已析普通实体的引用使用 "and" 号(&
)和分号(;
)作为定界符。参数实体引用则使用百分号(%
)和分号(;
)作为定界符。
[67] | Reference |
::= | EntityRef | CharRef |
|
[68] | EntityRef |
::= | '&' Name ';' |
[WFC: 声明实体] |
[VC: 声明实体] | ||||
[WFC: 已析实体] | ||||
[WFC: 无递归] | ||||
[69] | PEReference |
::= | '%' Name ';' |
[VC: 声明实体] |
[WFC: 无递归] | ||||
[WFC: 在 DTD 内] |
格式正确性约束: 声明实体
在一个没有任何 DTD 的文件,或一个只有不包含参数实体引用的内部 DTD 子集的文件,或一个 "standalone='yes'
" 的文件内,不在外部子集或参数实体内的实体引用中给出的 Name
必须与不在外部子集或参数实体内实体声明中所给出的相匹配,但格式正确的文件不需要声明以下的这些实体:amp
,lt
,gt
,apos
和 quot
。普通实体的声明必须先于任何在属性表声明中的缺省值中出现的对它的引用。注意,对于在外部子集或外部参数实体中声明的实体,不进行验证的处理器不必要读取和处理它们的声明;对这些文件,仅当 standalone='yes' 时,实体必须被声明的规则才是一个格式正确性约束。
有效性约束: 声明实体
在一个有外部子集或外部参数实体且 "standalone='no'
" 的实体中,实体引用中给出的 Name
必须与实体声明中所给出的相匹配。出于互操作性考虑,有效的文件应该以"4.6 预定义实体"中的简化形式声明实体 amp
,lt
,gt
,apos
和 quot
。参数实体的声明必须先于任何对它的引用。类似地,普通实体的声明必须先于任何在属性表声明中的缺省值中出现的对它直接或间接的引用。
格式正确性约束: 已析实体
实体引用不能包含一个未析实体的名字。未析实体只能在声明为 ENTITY 或 ENTITIES 的属性值中引用。
格式正确性约束: 无递归
已析实体不能直接或间接地包含对自身的递归引用。
格式正确性约束: 在 DTD 内
参数实体引用只能在 DTD 中出现。
字符引用和实体引用的例子:
Type <key>less-than</key> (<) to save options. |
参数实体引用的例子:
<!-- declare the parameter entity "ISOLat2"... --> |
[定义:实体以如下方式声明:]
[70] | EntityDecl |
::= | GEDecl | PEDecl |
[71] | GEDecl |
::= | '<!ENTITY' S Name S EntityDef S? '>' |
[72] | PEDecl |
::= | '<!ENTITY' S '%' S Name S PEDef S? '>' |
[73] | EntityDef |
::= | EntityValue | (ExternalID NDataDecl?) |
[74] | PEDef |
::= | EntityValue | ExternalID |
实体引用中的 Name
标识了该实体;对于未析实体,ENTITY 或 ENTITIES 属性的值标识了该实体。如果同一实体被声明了不止一次,绑定第一个遇到的声明。由使用者选择,如果实体被多次声明,XML 处理器可以给出警告。
[定义:如果实体定义是一个 EntityValue
,被定义的实体被称为内部实体。] 内部实体没有单独的物理存储对象,实体的内容在声明中给出。注意常量实体值中一些实体和字符引用的处理可能要求产生正确的置换文本:参见"4.5 内部置换文本的构造"。
内部实体是已析实体。
内部实体声明的例子:
<!ENTITY Pub-Status "This is a pre-release of the |
[定义:如果实体不是内部的,那么它是一个外部实体,声明如下:]
[75] | ExternalID |
::= | 'SYSTEM' S SystemLiteral |
|
| 'PUBLIC' S PubidLiteral S SystemLiteral |
||||
[76] | NDataDecl |
::= | S 'NDATA' S Name |
[VC: 声明记法] |
如果有 NDataDecl
,那么这是一个普通未析实体;否则它是一个已析实体。
有效性约束: 声明记法
Name
必须与记法的名字相匹配。
[定义:SystemLiteral
被称为该实体的系统标识符。这是一个 URI 引用(在 [IETF RFC 2396] 中定义,在 [IETF RFC 2732] 中更新),可以由此获得 XML 处理器的输入用于构建此实体的置换文本。] 片断标识符(以 #
开头)出现在系统标识符中是一个错误。如果一个片断标识符作为系统标识符的部分给出,XML 处理器可以给出一个错误。除非在本规范范围之外另外给出(如,一个特殊 DTD 中定义的专用 XML 元素类型,或一个特殊应用规范中定义的处理指令),相对 URI 指相对于实体声明所在资源的位置。因此,一个 URI 可能是相对于文件实体,或相对于包含外部 DTD 子集的实体,或相对于其他一些外部参数实体。
URI 引用需要对某些字符进行编码和转义。不允许出现的字符包括所有非 ASCII 字符,以及 [IETF RFC 2396] 第 2.4 节中列出的不被允许的字符,井号(#
)、百分号(%
)) 和 [IETF RFC 2732] 中允许的方括号除外。不被允许的字符必须用如下的方法转义:
每个不被允许的字符首先被转换成一个或多个字节的 UTF-8 [IETF RFC 2279] 编码。
任何对应于一个不被允许的字符的八位组用 URI 转义机制转义(即,将其转换成%
HH,其中 HH 是字节值的十六进制记法)。
用得到的字符序列置换原来的字符。
除了系统标识符之外,外部标识符还可以包含公共标识符。试图存取实体内容的 XML 处理器可以用公共标识符试着产生一个可选 URI 引用。如果处理器无法做到这一点,它必须使用系统常量中的 URI 引用。在试着匹配之前,公共标识符中所有空白字符串必须被规范为单个空格字符(#x20),同时必须去掉前导和尾随空白。
外部实体声明的例子:
<!ENTITY open-hatch |
[定义:每个外部已析实体应该以文本声明作为开始。]
[77] | TextDecl |
::= | '<?xml' VersionInfo? EncodingDecl S? '?>' |
文本声明必须以常量形式给出,而不能使用已析实体的引用。文本声明只能在外部已析实体的开头出现,不允许在其他任何地方出现。在外部已析实体中的文本声明不被认为是其置换文本的一部分
如果文件实体匹配 document
产生式,那么它是格式正确的。如果外部普通已析实体匹配 extParsedEnt
产生式,那么它是格式正确的。如果外部参数实体匹配 extPE
产生式,那么它是格式正确的。根据定义,外部参数实体是格式正确的。
[78] | extParsedEnt |
::= | TextDecl? content |
如果内部普通已析实体的置换文本匹配 content
产生式,那么它是格式正确的。根据定义,所有内部的参数实体都是格式正确的。
实体符合格式正确性的一个结果是 XML 文件的逻辑和物理结构是严格嵌套的;起始标签,结束标签,空元素标签,元素,注释,处理指令,字符引用,或实体引用都不能在一个实体中开始而在另一个实体中结束。
XML 文件中的每个外部已析实体都可以对其字符采用一种不同的编码方案。所有 XML 处理器必须能读取编码为 UTF-8 和 UTF-16 的实体。本规范中的术语 "UTF-8" 和 "UTF-16" 不适用于任何采用其他标识(label)的字符编码,即使这种编码或标识与 UTF-8 或 UTF-16 非常类似。
以 UTF-16 编码的实体必须以 ISO/IEC 10646 增补 F,[ISO/IEC 10646-2000] 增补 H, [Unicode] 的 2.4 节和 [Unicode3] 2.7 节(零宽度不间断空格字符,#xFEFF)中所描述的字节次序标记(Byte Order Mark)开头。这是一个编码签名,即不是 XML 文件中标记的一部分,也不是 XML 文件字符数据的一部分。XML 处理器必须能用此字符区分 UTF-8 编码和 UTF-16 编码的文件。
虽然 XML 处理器只被要求能读取 UTF-8 和 UTF-16 编码的实体,不过对于世界上还有其他的编码方案已有共识。有时可能想让 XML 处理器读取以那些编码方案编码的实体。在没有外部字符编码信息(如 MIME 头)的情况时,以不同于 UTF-8 和 UTF-16 的编码方案存储的实体必须以包含编码声明的文本声明(见 4.3.1 文本声明)开头:
[80] | EncodingDecl |
::= | S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" ) |
|
[81] | EncName |
::= | [A-Za-z] ([A-Za-z0-9._] | '-')* |
/* 编码方案的名称只包含拉丁字母 */ |
在文件实体中,编码声明是 XML 声明的一部分。EncName
是所用编码方案的名称。
在一个编码声明中,值 "UTF-8
","UTF-16
","ISO-10646-UCS-2
" 和 "ISO-10646-UCS-4
" 应该用于表示 Unicode 或 ISO/IEC 10646 中的各种不同编码和变换方案,值 "ISO-8859-1
","ISO-8859-2
",... "ISO-8859-
n" (其中 n 是区块号)应该用于表示 ISO 8859 的各个部分,而值 "ISO-2022-JP
","Shift_JIS
" 和 "EUC-JP
" 应该用于表示 JIS X-0208-1997 的各种编码。建议对于在 Internet Assigned Numbers Authority [IANA] 注册的字符编码方案(以字符集(charset)的 方式),除了以上所列之外的编码方案,应该用它们的注册名引用。其他的编码应该使用带 "x-" 前缀的名称。欲与之匹配的 XML 处理器应该以大小写敏感的方式对字符编码的名称进行匹配。而且 XML 处理器处理字符编码的名称时,应该将在 IANA 注册的编码名称解释为在 IANA 注册的相应编码,不然就应该当成未知的编码(当然,不要求处理器支持所有在 IANA 注册的编码)。
在缺少外部传输协议(如 HTTP 或 MIME)所提供的信息时,以下情况均是错误:XML 处理器接收到的实体的编码方案与实体所含编码声明中指出的编码方案不同,既不以字节次序标记开头也不以编码声明开头的实体使用了不同于 UTF-8 的编码。注意,因为 ASCII 是 UTF-8 的一个子集,严格说来普通 ASCII 字符不需要编码声明。
TextDecl 出现在外部实体开头以外的地方是一个严重错误。
当 XML 处理器遇到的实体使用了它不能处理的编码时,是一个严重错误。 如果一个 XML 实体被确认为使用了某种编码(由默认值,编码声明或高层协议确定),但是它包含了在此编码中非法的八位组序列的话,是一个严重错误。如果一个 XML 实体没有编码声明而它的内容不是合法的 UTF-8 或 UTF-16 编码的话,也是一个严重错误。
包含编码声明的文本声明的例子:
<?xml encoding='UTF-8'?> |
下表汇总了字符引用,实体引用, 和对未析实体的调用可以出现的上下文,以及每种情况下 XML 处理器的动作。 最左边一列的标识指明了识别时的上下文:
content
。
AttValue
。
Name
而不是以引用的形式出现,作为声明为
ENTITY 类型的属性的值,或可以作为声明为
ENTITIES 类型的属性值中的以空白分隔的记号之一。
EntityValue
。
实体类型 | 字符 | ||||
参数 | 内部普通 | 外部已析普通 | 未析 | ||
内容中的引用 | 不被识别 | 被包含 | 进行验证时被包含 | 被禁止 | 被包含 |
属性值中的引用 | 不被识别 | 作为常量被包含 | 被禁止 | 被禁止 | 被包含 |
作为属性值 | 不被识别 | 被禁止 | 被禁止 | 通知 | 不被识别 |
实体值中的引用 | 作为常量被包含 | 不处理 | 不处理 | 被禁止 | 被包含 |
DTD 中的引用 | 作为参数实体被包含 | 被禁止 | 被禁止 | 被禁止 | 被禁止 |
在 DTD 之外,百分号字符 %
没有特殊含义;因此在 DTD 中的参数实体引用在 content
中不被当成标记识别。类似地,除非未析实体的名字出现在已适当声明的属性的值中,否则它们不被识别。
[定义:当一个实体的置换文本被当成出现在引用所在位置的文件的一部分一样被存取和处理时,称此实体被包含。] 其置换文本可以包含字符数据和标记(不包括参数实体),其中标记必须以通常的方式识别。(字符串 "AT&T;
" 展开为 "AT&T;
",尚存的 "and" 号 & 不被识别为实体引用的定界符。)当被表示的字符被当成出现在引用所在位置一样被处理时,称此字符引用被包含。
当 XML 处理器识别出一个对已析实体的引用,为了验证该文件,处理器必须包含此实体的置换文本。如果实体是外部的,而处理器不试图验证该 XML 文件,那么处理器可以,但不是必须,包含此实体的置换文本。如果一个不进行验证的处理器不包含此置换文本,它必须通知应用它识别出但没有读取此实体。
这条规则基于这样一个共识:由 SGML 和 XML 的实体机制提供的起初设计用于支持模块化创作的自动包含不一定适合于其他应用,尤其是文件浏览。例如,当浏览器遇到一个外部已析实体引用时,可能选择用可视方式表示其存在但只在被请求时才读取它进行显示。
以下情况被禁止,并构成一个严重错误:
EntityValue
或 AttValue
中。当实体引用出现在属性值中或参数实体引用出现在常量实体值中时,它们的置换文本被当成出现在引用所在位置的文件的一部分一样被存取和处理,置换文本中的单双引号总是被当成正常的数据字符而不会结束此常量。例如,下面的例子是格式正确的:
<!-- --> |
而这个例子不是:
<!ENTITY EndAttr "27'" > |
当未析实体名字作为记号在声明为 ENTITY 或 ENTITIES 类型的属性的值中出现时, 进行验证的处理器必须将此实体和它的相关记法的系统和公共(如果有的话)标识符通知给应用。
当实体声明内一个普通实体引用出现在 EntityValue
中时, 它不被处理,保持不变。
和外部已析实体一样,参数实体只需在进行验证时被包含。当参数实体引用在 DTD 中被识别并被包含时,它的置换文本被前后各加上一个空格字符;其目的在于强制参数实体的置换文本包含整数个 DTD 中的语法记号。这不适用于实体值内的参数实体;对它们的处理见 4.4.5 作为常量被包含
在讨论内部实体的处理时,区分两种形式的实体值是有帮助的。[定义:常量实体值(literal entity value)是实际出现在实体声明中用引号扩起的字符串。] 对应于非终结符 EntityValue
。置换文本(replacement text)是置换了字符引用和参数实体引用后的实体内容。
在内部实体声明(EntityValue
)中给出的常量实体值可以包括字符引用,参数实体引用和普通实体引用。这些引用必须被整个包含于常量实体值中。如前述方式被包含的实际置换文本必须包含所有被引用的参数实体的置换文本,同时所有被引用的字符必须在常量实体值中字符引用所在位置被包含。但普通实体的引用必须保持不变,不被展开。例如,如果有以下的声明:
<!ENTITY % pub "Éditions Gallimard" > |
那么实体 "book
" 的置换文本为:
La Peste: Albert Camus, |
一旦引用 "&book;
" 出现在文件的内容或属性值中时,普通实体引用 "&rights;
" 应该被展开。
这些简单的规则将可能会有复杂的相互作用;参见 "D. 实体和字符引用的展开" 中对一个难的例子的详细讨论。
[定义:实体和字符引用都可以用于转义左尖括号,"and" 号(&)和其他定界符。普通实体集合(amp
,lt
,gt
,apos
,quot
)专门用于此目的。也可以使用数值字符引用;一旦被识别,它们立即被展开,同时它们必须被当成字符数据,因此数值字符引用 "<
" 和 "&
" 可以用于转义出现在字符数据中的 <
和 &
。]
不管这些实体是否被声明,所有的 XML 处理器必须能识别它们。出于互操作性考虑,有效的 XML 文件应该如其他实体一样,在使用这些实体前先声明它们。如果实体 lt
或 amp
被声明,它们必须被声明为置换文本为相应被转义字符的字符引用(小于号或 "and" 号)的内部实体;对这些实体需要转义两次以使对它们的引用能得到格式正确的结果。如果实体 gt
,apos
或 quot
被声明,它们必须被声明为置换文本为相应被转义的单个字符的内部实体(或指向被转义字符的字符引用;这里转义两次是不必要的,但也是无害的)。例如:
<!ENTITY lt "&#60;"> |
[定义:记法用名字标识了未析实体的格式,具有记法属性的元素的格式以及处理指令所针对的应用的格式。]
[定义:记法声明赋予记法一个名字用于实体中,属性表声明中和属性值说明中,同时也给出了一个记法的外部标识符使得 XML 处理器或它的客户应用可以定位能以给定记法的格式处理数据的助理应用。]
[82] | NotationDecl |
::= | '<!NOTATION' S Name S (ExternalID | PublicID) S? '>' |
[VC: 唯一的记法名字] |
[83] | PublicID |
::= | 'PUBLIC' S PubidLiteral |
有效性约束:唯一的记法名字
一个给定的 Name 只能被一个记法声明所声明.
XML 处理器必须向应用提供任何在属性值中,属性定义中或实体声明中定义或引用的记法的名字和外部标识符。它们还可以将外部标识符解析成系统标识符,文件名,或是应用调用相应处理器处理给定记法格式的数据的所需的其他信息。(但如果 XML 处理器或应用所运行的系统中没有处理 XML 文件声明和引用的记法的相应应用的情况,不是一个错误。)
[定义:文件实体(document entity)是实体树的根和 XML 处理器的处理起点。] 本规范没有规定 XML 如何定位文件实体;与其他实体不同,文件实体没有名字,而且可以完全不带任何标识地出现在处理器的输入流中。
合乎规范的 XML 处理器可以分为两类:进行验证的和不进行验证的。
进行验证和不进行验证的处理器都必须报告在文件实体的内容中和任何其他它们读到的已析实体中对格式正确性约束的违反。
[定义:进行验证的处理器必须,由使用者选择,报告违反 DTD 声明中所述约束的情况以及不满足本规范中给出的有效性约束的情况。] 要完成这一点,进行验证的 XML 处理器必须读取和处理整个 DTD 和所有在文件中引用的外部已析实体。
不进行验证的处理器只被要求检查文件实体和整个内部 DTD 子集的格式正确性。[定义:虽然它们不被要求检查文件的有效性,但它们必须处理它们读取的所有内部 DTD 子集中的声明和所有参数实体,直到遇到第一个对它们没有读取的参数实体的引用;也就是说,它们必须根据这些声明中的信息规范化属性值,包含内部实体的置换文本,并提供缺省属性值。] 除了 standalone="yes"
的情况,它们在遇到第一个对它们没有读取的参数实体的引用后,不应处理其后的实体声明或属性表声明,因为此实体中包含的声明可能覆盖前面的声明。
进行验证的处理器的行为是高度可预测的;它必须读取文件的所有部分,报告所有对格式正确性和有效性的违反。对一个不进行验证的处理器的要求要低一点;它不需要读取文件实体以外的任何文件部分。这对 XML 的处理器的使用者而言可能会有两个重要的影响:
为了使不同 XML 处理器间的互操作有最大的可靠性, 使用不进行验证的处理器的应用不应依赖于不要求这些处理器具备的动作。 那些要求使用如缺省值或在外部实体中声明内部实体等功能的应用应该使用进行验证的 XML 处理器。
本规范中 XML 的形式化文法用一种简单的扩展巴科斯范式(Extended Backus-Naur Form,EBNF)给出。文法中的每一条规则定义了一个符号,形式如下:
symbol ::= expression |
如果符号是正则语言的起始符号,则它以大写字母开头, 否则以小写字母开头。字符串常量(literal strings)用引号括起。
在规则右边的表达式中,以下表达式用于匹配一个或多个字符的字符串:
#xN
N
是一个十六进制的整数,当 ISO/IEC 10646 中某个字符的规范(UCS-4)代码值作为无符号二进制数与 N
相等时,此表达式匹配这个字符。#xN
中的前导 0 没有意义,在相应的代码值中的前导 0 的个数则由所用字符编码方案决定,对 XML 没有意义。
[a-zA-Z]
,
[#xN-#xN]
与其值在指定范围内的任何 Char 相匹配(含界,inclusive)。
[abc]
,
[#xN#xN#xN]
与其值为所枚举的值之一的 Char 相匹配。在一对方括号内枚举和范围可以混用。
[^a-z]
,
[^#xN-#xN]
与其值在指定范围之外的任何 Char 相匹配。
[^abc]
,
[^#xN#xN#xN]
与任何不在给定字符集内的 Char 相匹配。在一对方括号内被禁值的枚举和范围可以混用。
"string"
与匹配双引号中所给字符串的常量字符串相匹配。
'string'
与匹配单引号中所给字符串的常量字符串相匹配。
这些符号可以按下列方式组合,以匹配更复杂的模式,其中A
和B
表示简单表达式:
expression
)
expression
被当成一个单元,可以向本表描述的那样进行组合。
A?
A
相匹配,即
A
可选。
A B
A
后跟
B
的模式相匹配。这个操作符的优先级高于 |,因此
A B | C D
相当于
(A B) | (C D)
。
A | B
A
或
B
之一相匹配,但不同时匹配。
A - B
A
但不匹配
B
的字符串相匹配。
A+
A
相匹配。连接操作的优先级高于 |,因此
A+ | B+
相当于
(A+) | (B+)
。
A*
A
相匹配。连接操作的优先级高于 |,因此
A* | B*
相当于
(A*) | (B*)
。
其他在产生式中使用的记法有:
/* ... */
[ wfc: ... ]
[ vc: ... ]
根据 Unicode 标准中定义的特征,字符被分为基字符(其中包含了拉丁字母),表意字符和组合字符(其中包含了大多数的变音符)。数字和扩展符(extender)也各自被分成类。
[84] | Letter |
::= | BaseChar | Ideographic |
[85] | BaseChar |
::= | [#x0041-#x005A] | [#x0061-#x007A] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | [#x00F8-#x00FF] | [#x0100-#x0131] | [#x0134-#x013E] | [#x0141-#x0148] | [#x014A-#x017E] | [#x0180-#x01C3] | [#x01CD-#x01F0] | [#x01F4-#x01F5] | [#x01FA-#x0217] | [#x0250-#x02A8] | [#x02BB-#x02C1] | #x0386 | [#x0388-#x038A] | #x038C | [#x038E-#x03A1] | [#x03A3-#x03CE] | [#x03D0-#x03D6] | #x03DA | #x03DC | #x03DE | #x03E0 | [#x03E2-#x03F3] | [#x0401-#x040C] | [#x040E-#x044F] | [#x0451-#x045C] | [#x045E-#x0481] | [#x0490-#x04C4] | [#x04C7-#x04C8] | [#x04CB-#x04CC] | [#x04D0-#x04EB] | [#x04EE-#x04F5] | [#x04F8-#x04F9] | [#x0531-#x0556] | #x0559 | [#x0561-#x0586] | [#x05D0-#x05EA] | [#x05F0-#x05F2] | [#x0621-#x063A] | [#x0641-#x064A] | [#x0671-#x06B7] | [#x06BA-#x06BE] | [#x06C0-#x06CE] | [#x06D0-#x06D3] | #x06D5 | [#x06E5-#x06E6] | [#x0905-#x0939] | #x093D | [#x0958-#x0961] | [#x0985-#x098C] | [#x098F-#x0990] | [#x0993-#x09A8] | [#x09AA-#x09B0] | #x09B2 | [#x09B6-#x09B9] | [#x09DC-#x09DD] | [#x09DF-#x09E1] | [#x09F0-#x09F1] | [#x0A05-#x0A0A] | [#x0A0F-#x0A10] | [#x0A13-#x0A28] | [#x0A2A-#x0A30] | [#x0A32-#x0A33] | [#x0A35-#x0A36] | [#x0A38-#x0A39] | [#x0A59-#x0A5C] | #x0A5E | [#x0A72-#x0A74] | [#x0A85-#x0A8B] | #x0A8D | [#x0A8F-#x0A91] | [#x0A93-#x0AA8] | [#x0AAA-#x0AB0] | [#x0AB2-#x0AB3] | [#x0AB5-#x0AB9] | #x0ABD | #x0AE0 | [#x0B05-#x0B0C] | [#x0B0F-#x0B10] | [#x0B13-#x0B28] | [#x0B2A-#x0B30] | [#x0B32-#x0B33] | [#x0B36-#x0B39] | #x0B3D | [#x0B5C-#x0B5D] | [#x0B5F-#x0B61] | [#x0B85-#x0B8A] | [#x0B8E-#x0B90] | [#x0B92-#x0B95] | [#x0B99-#x0B9A] | #x0B9C | [#x0B9E-#x0B9F] | [#x0BA3-#x0BA4] | [#x0BA8-#x0BAA] | [#x0BAE-#x0BB5] | [#x0BB7-#x0BB9] | [#x0C05-#x0C0C] | [#x0C0E-#x0C10] | [#x0C12-#x0C28] | [#x0C2A-#x0C33] | [#x0C35-#x0C39] | [#x0C60-#x0C61] | [#x0C85-#x0C8C] | [#x0C8E-#x0C90] | [#x0C92-#x0CA8] | [#x0CAA-#x0CB3] | [#x0CB5-#x0CB9] | #x0CDE | [#x0CE0-#x0CE1] | [#x0D05-#x0D0C] | [#x0D0E-#x0D10] | [#x0D12-#x0D28] | [#x0D2A-#x0D39] | [#x0D60-#x0D61] | [#x0E01-#x0E2E] | #x0E30 | [#x0E32-#x0E33] | [#x0E40-#x0E45] | [#x0E81-#x0E82] | #x0E84 | [#x0E87-#x0E88] | #x0E8A | #x0E8D | [#x0E94-#x0E97] | [#x0E99-#x0E9F] | [#x0EA1-#x0EA3] | #x0EA5 | #x0EA7 | [#x0EAA-#x0EAB] | [#x0EAD-#x0EAE] | #x0EB0 | [#x0EB2-#x0EB3] | #x0EBD | [#x0EC0-#x0EC4] | [#x0F40-#x0F47] | [#x0F49-#x0F69] | [#x10A0-#x10C5] | [#x10D0-#x10F6] | #x1100 | [#x1102-#x1103] | [#x1105-#x1107] | #x1109 | [#x110B-#x110C] | [#x110E-#x1112] | #x113C | #x113E | #x1140 | #x114C | #x114E | #x1150 | [#x1154-#x1155] | #x1159 | [#x115F-#x1161] | #x1163 | #x1165 | #x1167 | #x1169 | [#x116D-#x116E] | [#x1172-#x1173] | #x1175 | #x119E | #x11A8 | #x11AB | [#x11AE-#x11AF] | [#x11B7-#x11B8] | #x11BA | [#x11BC-#x11C2] | #x11EB | #x11F0 | #x11F9 | [#x1E00-#x1E9B] | [#x1EA0-#x1EF9] | [#x1F00-#x1F15] | [#x1F18-#x1F1D] | [#x1F20-#x1F45] | [#x1F48-#x1F4D] | [#x1F50-#x1F57] | #x1F59 | #x1F5B | #x1F5D | [#x1F5F-#x1F7D] | [#x1F80-#x1FB4] | [#x1FB6-#x1FBC] | #x1FBE | [#x1FC2-#x1FC4] | [#x1FC6-#x1FCC] | [#x1FD0-#x1FD3] | [#x1FD6-#x1FDB] | [#x1FE0-#x1FEC] | [#x1FF2-#x1FF4] | [#x1FF6-#x1FFC] | #x2126 | [#x212A-#x212B] | #x212E | [#x2180-#x2182] | [#x3041-#x3094] | [#x30A1-#x30FA] | [#x3105-#x312C] | [#xAC00-#xD7A3] |
[86] | Ideographic |
::= | [#x4E00-#x9FA5] | #x3007 | [#x3021-#x3029] |
[87] | CombiningChar |
::= | [#x0300-#x0345] | [#x0360-#x0361] | [#x0483-#x0486] | [#x0591-#x05A1] | [#x05A3-#x05B9] | [#x05BB-#x05BD] | #x05BF | [#x05C1-#x05C2] | #x05C4 | [#x064B-#x0652] | #x0670 | [#x06D6-#x06DC] | [#x06DD-#x06DF] | [#x06E0-#x06E4] | [#x06E7-#x06E8] | [#x06EA-#x06ED] | [#x0901-#x0903] | #x093C | [#x093E-#x094C] | #x094D | [#x0951-#x0954] | [#x0962-#x0963] | [#x0981-#x0983] | #x09BC | #x09BE | #x09BF | [#x09C0-#x09C4] | [#x09C7-#x09C8] | [#x09CB-#x09CD] | #x09D7 | [#x09E2-#x09E3] | #x0A02 | #x0A3C | #x0A3E | #x0A3F | [#x0A40-#x0A42] | [#x0A47-#x0A48] | [#x0A4B-#x0A4D] | [#x0A70-#x0A71] | [#x0A81-#x0A83] | #x0ABC | [#x0ABE-#x0AC5] | [#x0AC7-#x0AC9] | [#x0ACB-#x0ACD] | [#x0B01-#x0B03] | #x0B3C | [#x0B3E-#x0B43] | [#x0B47-#x0B48] | [#x0B4B-#x0B4D] | [#x0B56-#x0B57] | [#x0B82-#x0B83] | [#x0BBE-#x0BC2] | [#x0BC6-#x0BC8] | [#x0BCA-#x0BCD] | #x0BD7 | [#x0C01-#x0C03] | [#x0C3E-#x0C44] | [#x0C46-#x0C48] | [#x0C4A-#x0C4D] | [#x0C55-#x0C56] | [#x0C82-#x0C83] | [#x0CBE-#x0CC4] | [#x0CC6-#x0CC8] | [#x0CCA-#x0CCD] | [#x0CD5-#x0CD6] | [#x0D02-#x0D03] | [#x0D3E-#x0D43] | [#x0D46-#x0D48] | [#x0D4A-#x0D4D] | #x0D57 | #x0E31 | [#x0E34-#x0E3A] | [#x0E47-#x0E4E] | #x0EB1 | [#x0EB4-#x0EB9] | [#x0EBB-#x0EBC] | [#x0EC8-#x0ECD] | [#x0F18-#x0F19] | #x0F35 | #x0F37 | #x0F39 | #x0F3E | #x0F3F | [#x0F71-#x0F84] | [#x0F86-#x0F8B] | [#x0F90-#x0F95] | #x0F97 | [#x0F99-#x0FAD] | [#x0FB1-#x0FB7] | #x0FB9 | [#x20D0-#x20DC] | #x20E1 | [#x302A-#x302F] | #x3099 | #x309A |
[88] | Digit |
::= | [#x0030-#x0039] | [#x0660-#x0669] | [#x06F0-#x06F9] | [#x0966-#x096F] | [#x09E6-#x09EF] | [#x0A66-#x0A6F] | [#x0AE6-#x0AEF] | [#x0B66-#x0B6F] | [#x0BE7-#x0BEF] | [#x0C66-#x0C6F] | [#x0CE6-#x0CEF] | [#x0D66-#x0D6F] | [#x0E50-#x0E59] | [#x0ED0-#x0ED9] | [#x0F20-#x0F29] |
[89] | Extender |
::= | #x00B7 | #x02D0 | #x02D1 | #x0387 | #x0640 | #x0E46 | #x0EC6 | #x3005 | [#x3031-#x3035] | [#x309D-#x309E] | [#x30FC-#x30FE] |
在此定义的字符类可以从 Unicode 2.0 字符库中如下导出:
XML 被设计为 SGML 的一个子集,表现在每一个有效的 XML 文件也应该是一个合乎规范的 SGML 文件。对 XML 在 SGML 之外对文件所加的限制的详细讨论参见[Clark]。
本附录中举例说明了在 "4.4 XML 处理器对实体和引用的处理"一节中规定的实体和字符引用的识别和展开的次序。
如果声明包含在 DTD 中
<!ENTITY example "<p>An ampersand (&#38;) may be escaped |
那么 XML 处理器将在对实体声明进行语法分析时识别出字符引用,并在将下面的字符串存为实体"example
"的值前解析这些字符引用:
<p>An ampersand (&) may be escaped |
文件中对 "&example;
" 的引用会导致对文本的重新分析,此时元素 "p
" 的起始和结束标签被识别,三个引用被识别和展开,其结果是一个包含下面内容(所有数据,无定界符或标记)"p
" 元素:
An ampersand (&) may be escaped |
一个更复杂的例子可以完整地说明这些规则和它们的作用。在下面的例子中,行号仅仅是为了方便说明。
1 <?xml version='1.0'?> |
这个例子会导致下列动作:
xx
" 以值 "%zz;
" 存于符号表中。因为置换文本不被再次扫描,对参数实体 "zz
" 的引用不会被识别。(而且如果它被识别的话则是一个错误,因为 "zz
" 还没有被声明。)<
" 被立即展开,而参数实体 "zz
" 以置换文本 "<!ENTITY tricky "error-prone" >
" 被存储,此置换文本是一个格式正确的实体声明。xx
" 的引用被识别,"xx
" 的置换文本(即 "%zz;
")被分析。对 "zz
" 的引用随后被识别,它的置换文本("<!ENTITY tricky "error-prone" >
")被分析。此时普通实体 "tricky
" 被声明,它的置换文本是 "error-prone
"。tricky
" 的引用被识别,并被展开,因此 "test
" 元素的全部内容为一个自说明的(也不合语法)字符串This sample shows a error-prone method.。如 3.2.1 元素型内容中所述,元素类型声明中的内容模型要求是确定型的。这个要求是出于和 SGML 的兼容性考虑(SGML 称为"无歧义的");用 SGML 系统生成的 XML 处理器可能会把非确定型内容模型标为错误。
例如,内容模型((b, c) | (b, d))
是非确定型的,因为给定一个初始 b
,XML 处理器没有在向前看以知道 b
后是什么元素之前,无法知道匹配模型中的哪个 b
。在这种情况下,两个对 b
的引用可以简化成单个的引用,使得模型成为(b,(c | d))
。此时初始的 b
只和内容模型中的一个名字明确匹配。处理器不需要向前看其后的内容。c
或 d
都能被接受。
更形式化的说法:使用 Aho,Sethi 和 Ullman 所著 [Aho/Ullman] 3.9 节中的标准算法 3.5,可以从内容模型构造出一个有限状态自动机。在很多这样的算法中,对应正则表达式中的每一个位置(即正则表达式的语法树中的每个叶子节点),都构造 一个随集(follow set);如果任一位置的随集中不止一个后继位置被标为同一元素类型时,那么此内容模型出错,并且可以被报为错误。
存在将许多但不是所有非确定型内容模型自动规约为等价的确定型模型的算法;参见 Br黦gemann-Klein 1991 [Br黦gemann-Klein].
XML 编码声明在实体中以内部标签的方式工作,用于指出使用了何种字符编码。然而,在 XML 处理器能读取这个内部标签前,显然它必须知道当前使用的是何种字符编码-而这正是此内部标签要试图指出的。通常情况下,这是一种无法解决的情况。但在 XML 中并非如此,因为 XML 在两个方面对这种情形作出了限制:假定每一种实现只支持一个有限的字符编码集,并且,为了使得正常情况下自动检测每个实体中所用字符编码成为可能,限制了 XML 编码声明的位置和内容。同时,很多情况下除了 XML 数据流本身之外,另外还有可用的信息源。根据 XML 实体交给处理器时没有或有任何的附带(外部)信息,可以区分出两种情况。我们先考虑第一种情况。
因为每一个没有外部编码信息且非 UTF-8 或 UTF-16 编码的 XML 实体必须以 XML 编码声明开头,其开始的几个字符必须为 '<?xml
',任何合乎规范的处理器可以在两到四个八位组的输入后,检测出适用于下列何种情况。在读这张表时,知道这些是有帮助的:在 UCS-4 中,'<' 是 "#x0000003C
",'?' 是 "#x0000003F
",UTF-16 数据流的字节次序标记要求为 "#xFEFF
"。记法 ## 用于表示任意的字节值,但两个连续的 ## 不能同时为 00。
有字节次序标记:
00 00 FE FF |
UCS-4,big-endian 编码的计算机(1234次序) |
FF FE 00 00 |
UCS-4,little-endian 编码的计算机(4321次序) |
00 00 FF FE |
UCS-4,异常的八位组次序(2143) |
FE FF 00 00 |
UCS-4,异常的八位组次序(3412) |
FE FF ## ## |
UTF-16, big-endian |
FF FE ## ## |
UTF-16, little-endian |
EF BB BF |
UTF-8 |
无字节次序标记:
00 00 00 3C |
UCS-4 或其他 32 位码元的编码,同时 ASCII 字符的码值就是 ASCII 值,次序分别为 big-endian(1234),little-endian(4321)和两种异常的字节次序(2143 和 3412)。必须读取编码声明以确定使用的是 或其他被支持的 32 位编码。 |
3C 00 00 00 |
|
00 00 3C 00 |
|
00 3C 00 00 |
|
00 3C 00 3F |
UTF-16BE,big-endian 的 ISO-10646-UCS-2 或其他 16 位码元的 big-endian 的编码,其中 ASCII 字符的码值就是 ASCII (必须读取编码声明以确定使用的是哪一种) |
3C 00 3F 00 |
UTF-16LE,little-endian 的 ISO-10646-UCS-2 或其他 16 位码元的 little-endian 的编码,其中 ASCII 字符的码值就是 ASCII (必须读取编码声明以确定使用的是哪一种) |
3C 3F 78 6D |
UTF -8,ISO 646,ASCII,ISO 8859 的某些部分,Shift-JIS,EUC,或任何其他 7 位,8 位或混合宽度的编码,这些编码必须保证 ASCII 字符有它们正常的位置,宽度和取值;具体其中哪一个适用需读取实际的编码声明来检测确定,但是因为所有这些编码中的 ASCII 字符使用了相同的位模式,所以能够可靠地读取编码声明本身 |
4C 6F A7 94 |
EBCDIC (其中的某些情况;必须读取完整的编码声明以确定使用的是哪一个代码页) |
其他 | 没有编码声明则为 UTF-8,否则不是数据流被标错了(没有所需的编码声明),被损坏了,是不完整的,就是被包含在某种外层数据中 |
注:
在上述不需要读取编码声明来确定所用编码的情况下,4.3.3 节仍然要求读取可能出现的编码声明,并检查其中的编码名称是否与实体实际的编码相一致。同时,现在不要求有编码声明的情况有可能会因为新的字符编码方案的发明而变得必须使用编码声明用于确定所用的编码。
这种层次的自动检测足以用于读取 XML 编码声明和分析字符编码标识符。字符编码标识符仍然是必须的,它用于区分编码方案集中的单个成员(例如从 8859 中区分出 UTF-8,8859 各个部分间的相互区分,以及区分所用的特定 EBCDIC 代码页,等等)。
因为编码声明的内容限于 ASCII 字符集中的字符(不管怎样编码),一旦处理器检测到使用的是哪一个编码方案集,它能够可靠地读取整个编码声明。因为在实际中,所有广泛使用的字符编码都可 以归于上述种类中,XML 编码声明保证了可靠的内嵌(in-band)字符编码标注,即使是在操作系统或传输协议级的外部信息源并不可靠的情况下。象 UTF-7 那样重用了 ASCII 编码值的字符编码方案有可能无法可靠地被检测。
一旦处理器检测到所用的字符编码,它就可以作出合适的动作,或是针对每种情况调用单独的输入例程,或是对每个输入的字符调用版本合适的转换函数。
和任何自标注(self-labeling)的系统一样,一旦任何软件改变了实体的字符集或其编码而没有相应修改编码声明的话,XML的编码声明将无法工作。字符编码方案的实现者必须小心仔细,以保证用于标注实体的内部和外部信息的正确性。
第二种可能的情况是 XML 实体有附带的信息,如在一些文件系统和网络协议中。当具有多个信息源时,它们间的相对优先级和首选冲突处理方法必须在传输 XML 的高层协议中给出。具体请参考 [IETF RFC 2376] 或其后续标准,其中定义了 text/xml
和 application/xml
MIME 类型并且提供了一些有用的指导。然而出于互操作性考虑,建议使用下列规则。
本规范由 W3C XML 工作组(WG)完成并批准发表。工作组批准本规范并不表示所有的工作组成员都一致同意本规范。现有和以前的 XML 工作组成员包括:
本规范的第二版由 W3C XML 核心工作组完成。在此版本发表时此工作组的成员包括:
第二版用 XMLspec DTD 书写(见其文档)。其 HTML 版本用 xmlspec.xsl,diffspec.xsl,和 REC-xml-2e.xsl XSLT 样式表制成。其 PDF 版本使用 html2ps 和一个 distiller 程序制成。