XML概览
XML(可扩展标记语言)是一种用于描述结构化信息的语言。作为SGML的一种简化,由W3组织维护。与用非XML格式相比,使用基于XML的格式有以下优点:
- 由于已有现成的解析器等成熟的配套工具,容易可靠地处理
- XML是经过深思熟虑的,可以避免不少常见问题
- XML格式往往是自描述的,容易理解和排错
XML
文档结构
由于树是常见的数据模型,XML对就是对树的一种表示方式。XML文档是树的表示,如:
<?xml version="1.0"?>
<!DOCTYPE greeting SYSTEM "hello.dtd">
<greeting>Hello, world!</greeting>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE greeting [
<!ELEMENT greeting (#PCDATA)>
]>
<greeting>Hello, world!</greeting>
严格地说,一个良构的XML文档的开始符号为:
[1] document ::= ( prolog element Misc* ) - ( Char* RestrictedChar Char* )
其中,prolog
给出一些元数据,element
为实质的数据。以下是一些常用符号:
[2] Char ::= [#x1-#xD7FF] | [#xE000-#xFFFD] | /* any Unicode character, excluding
[#x10000-#x10FFFF] the surrogate blocks, FFFE, and
FFFF. */
[2a] RestrictedChar ::= [#x1-#x8] | [#xB-#xC] | [#xE-#x1F] |
[#x7F-#x84] | [#x86-#x9F]
[3] S ::= (#x20 | #x9 | #xD | #xA)+ /*white space consists of one or more space , carriage returns, line feeds, ortabs*/
[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] |
[#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] |
[#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] |
[#x10000-#xEFFFF]
[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
[5] Name ::= NameStartChar (NameChar)*
[6] Names ::= Name (#x20 Name)*
[7] Nmtoken ::= (NameChar)+
[8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
由(('X'|'x') ('M'|'m') ('L'|'l'))
开始的名字留给XML标准用。
XML处理器分为验证的和非验证的,两者都检查文档实体良构性,但前者还检查有效性条件(于是必须处理整个DTD和所有引用的外部解析实体),前者的行为较可预测。除非standalone="yes"
,不能处理在对未读的参数实体引用后的实体声明或属性列表声明。
导言
XML文档的导言部分(prolog
)给出一些元数据:
[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 ::= '1.' [0-9]+
[27] Misc ::= Comment | PI | S
[28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? [验证条件: 文档类型声明中的Name匹配根元素]
('[' intSubset ']' S?)? '>'
[良构条件: 外部子集必须匹配extSubset生成规则]
[28a] DeclSep ::= PEReference | S [良构条件: PEReference必须匹配生成规则extSubsetDecl]
[28b] intSubset ::= (markupdecl | DeclSep)*
[69] PEReference ::= '%' Name ';' [验证条件:对于有外部子集或参数实体引用且没有`standalone='yes'`的文档,则实体引用的Name必须匹配一个前面的实体声明,类似地一般实体必须声明在于属性列表声明的默认值被直接或间接引用之前]
[良构条件:已解析实体不能包含到时自身的直接或间接的引用]
[良构条件:参数实体引用不能出现于DTD外]
[29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl [验证条件: 参数实体的替换文本必须适当嵌套,即`markupdecl`的首末字符要落在同一替换文本中]
| NotationDecl | PI | Comment
[良构条件: 参数实体引用不能出现于内部子集的标签声明内,但可出现于标签声明可出现的地方]
[30] extSubset ::= TextDecl? extSubsetDecl
[31] extSubsetDecl ::= ( markupdecl | conditionalSect | DeclSep)*
[32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') [验证条件: 见下面对应的列表项目]
"'") | ('"' ('yes' | 'no') '"'))
[75] ExternalID ::= 'SYSTEM' S SystemLiteral
| 'PUBLIC' S PubidLiteral S SystemLiteral
[11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
[12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
[13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
[80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
[81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
XMLDecl指定XML文档的XML参数:
VersionInfo
给出XML版本,目前只有1.0
和1.1
两种,这里主要介绍后者,它们区别包括:- XML 1.0的哲学是给出容许的名字集合,XML 1.1则给出禁止的名字集合
- XML 1.1把NEL (
#x85
)和#x2028
加到行结束符列表 - XML 1.1容许到控制字符
#x1
到#x1F
的字符引用,而#x7F
到#x9F
也只可通过字符引用出现 - XML 1.1要求文档应当是完全正规化的,由此简化名字、属性值和字符内容的相等性比较
EncodingDecl
给出文档的编码方式SDDecl
说明文档是否自足,yes
表示没有外部标记声明(出现在外部子集或参数实体的标签声明)会影响从XML处理器送给应用程序的信息。如果有外部标记声明,则默认为no
。非自足文档可以机械地化为自足的文档(在网络传输时可能有用)。若有以下外部标记声明,必须为no
:- 被应用默认值的带默认值的属性
- 被引用的实体(amp、lt、gt、apos、quot除外)
- 出现的分词类型属性,且声明存在与否会导致不同值
- 空白直接在内的有元素内容的元素类型
doctypedecl给出XML文档的类型:
Name
指定根元素的类型- 余下是文档类型声明(DTD):
intSubset
中直接可以放置一些标记声明或者参数实体引用(会替换为真正的标记声明),这些声明属于内部子集ExternalID
指定采用位于其它文档的标记声明,有关声明属性外部子集:- 系统标识符
SystemLiteral
会被转换(必要时转义)为外部子集所在的URI
- 系统标识符
- 公共标识符
PublicLiteral
指定众所周知的DTD 当内外部子集都用时,内部子集视为在外部子集前,从而内部子集中的实体和属性表声明优先。
元素
XML文档中的每个元素对应于一棵树,其语法为:
[39] element ::= EmptyElemTag
| STag content ETag [良构条件: STag与ETag的元素类型匹配]
[验证条件: 元素类型已声明且content合乎其要求]
[40] STag ::= '<' Name (S Attribute)* S? '>' [良构条件: 在同一start-tag或empty-element中各属性名互异]
[41] Attribute ::= Name Eq AttValue [验证条件: 属性必须已声明且其值有指定的类型]
[良构条件: 属性值不含直接或间接的外部实体引用]
[良构条件: 属性值中直接或间接的实体引用的替换文本不含`<`]
[10] AttValue ::= '"' ([^<&"] | Reference)* '"'| "'" ([^<&'] | Reference)* "'"
[42] ETag ::= '</' Name S? '>'
[43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)*
[44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>' [良构条件:在同一start-tag或empty-element中各属性名互异]
[14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
[18] CDSect ::= '<![CDATA[' CData ']]>'
[20] CData ::= Char* - (Char* ']]>' Char*)
[66] CharRef ::= '&#' [0-9]+ ';'
| '&#x' [0-9a-fA-F]+ ';' [良构条件: 引用的字符匹配Char规则]
[67] Reference ::= EntityRef | CharRef
[68] EntityRef ::= '&' Name ';' [良构条件:对于没有任何DTD、只有一个没有参数实体引用的内部DTD子集或`standalone='yes'`的文档,对于不出现在外部子集或参数实体中的实体引用,给定的Name(除amp、lt、gt、apos和quot)必须匹配不在外部子集或参数实体中的实体声明,而且一般实体的声明要在于属性列表声明的默认值被引用之前]
[验证条件:对于有外部子集或参数实体引用且没有`standalone='yes'`的文档,则实体引用的Name必须匹配一个前面的实体声明,类似地一般实体必须声明在于属性列表声明的默认值被直接或间接引用之前]
[良构条件:实体引用不能包含未解析实体的名字]
[良构条件:已解析实体不能包含到时自身的直接或间接的引用]
元素中STag
、ETag
和EmptyElemTag
中Name
为元素类型,元素可以有若干属性用于存放树的元数据,各属性顺序不重要。content
中给出树根的各孩子节点,它们分别为以下之一:
- 子树,这时用元素递归地表示之
- 字符数据
- 如果其中没有标签状或引用状的东西,则可以直接写出
- 如果没有
]]>
,则可用<![CDATA[
与]]>
包围,不能嵌套。如<![CDATA[<greeting>Hello, world!</greeting>]]>
会视为字面的文本<greeting>Hello, world!</greeting>
- 字符可以用其Unicode值引用,
&#x
开始的用十六进制,&#
开始的用十进制
- 实体引用形如
&名称;
在属性值送给应用程序或验证前会被正规化:
- 所有行结束符正规化为
#xA
- 令结果初始为空字符串
- 对正规化前的每个:
- 字符引用: 附加引用的字符
- 实体引用: 对实体的替换文本用本步
- 空白字符(
#x20
、#xD
、#xA
、#x9
):附加#x20
- 其它:附加之
- 若属性类型非
CDATA
,则去除前导和末尾的空白,中间的连续空白归一
作为例子,设有声明:
<!ENTITY d "
">
<!ENTITY a "
">
<!ENTITY da "
">
则
属性描述 a 为 NMTOKENS a 为 CDATA
a=" x y z #x20 #x20 x y z
xyz"
a="&d;&d;A&a; &a;B&da;" A #x20 B #x20 #x20 A #x20 #x20 #x20 B #x20 #x20
a= #xD #xD A #xA #xA B #xD #xA #xD #xD A #xA #xA B #xD #xA
"

A

B
"
最后一例子的NMTOKENS情况是良构但不有效的
其它
注释
注释可出现于标签外的地方,应用程序可能接收或不接收到它,其语法为:
[15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
如<!-- declarations for <head> & <body> -->
是合法注释而<!-- B+, B, or B--->
不是,这保证只用向前看至多一个字符。
处理指令
处理指令为留给应用程序的指令,其语法为:
[16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
其中PITarget用于指定应用程序,参数中不识别实体引用。
类型声明
元素声明
声明元素类型的语法如下:
[45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? [验证条件: 每个元素类型不能重复声明]
'>'
[46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
[47] children ::= (choice | seq) ('?' | '*' | '+')?
[48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
[49] choice ::= '(' S? cp ( S? '|' S? cp )+ S? ')' [验证条件: 参数实体的替换文本必须与参数化的组恰当地嵌套,即若choice、seq或Mixed中开括号与闭括号要在同一替换文本中。]
[50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')' [验证条件: 参数实体的替换文本必须与参数化的组恰当地嵌套,即若choice、seq或Mixed中开括号与闭括号要在同一替换文本中。]
[51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S?
')*'
| '(' S? '#PCDATA' S? ')' [验证条件: 参数实体的替换文本必须与参数化的组恰当地嵌套,即若choice、seq或Mixed中开括号与闭括号要在同一替换文本中。]
[验证条件: Name不能重复]
以下为各contentspec
含义
EMPTY
表示元素不能有任何内容(哪怕实体引用、注释、处理指令或空白)ANY
表示且在替换实体引用后内容由字符数据(含CDATA节)、注释、处理指令和类型已声明的孩子元素组成- Mixed表示在替换实体引用后内容由字符数据(含CDATA节)、注释、处理指令和指定类型的孩子元素组成。注意,只可指定孩子元素的容许类型,但不能指定顺序和数量。
- children表示除了可夹杂可选的空白、注释和处理指令(CDATA节即使只包含空白和替换文本为空白的实体引用也不行)外,子元素匹配‘正则表达式’:
- Name为容许的子元素类型
- choice表示容许指定类型之一
- seq表示容许指定类型顺序出现
至于修饰符
?
表示可出现一次或零次,+
表示可出现一次或多次,*
表示可出现零次或多次,没有表示只可出现恰一次。
以下是例子:
<!ELEMENT br EMPTY>
<!ELEMENT p (#PCDATA|emph)* >
<!ELEMENT %name.para; %content.para; >
<!ELEMENT container ANY>
<!ELEMENT spec (front, body, back?)>
<!ELEMENT div1 (head, (p | list | note)*, div2*)>
<!ELEMENT dictionary-body (%div.mix; | %dict.mix;)*>
<!ELEMENT p (#PCDATA|a|ul|b|i|em)*>
<!ELEMENT p (#PCDATA | %font; | %phrase; | %special; | %form;)* >
<!ELEMENT b (#PCDATA)>
属性列表声明
属性列表声明指定一个元素类型可用的属性集以及各属性值的类型和默认值:
[52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
[53] AttDef ::= S Name S AttType S DefaultDecl
[54] AttType ::= StringType | TokenizedType |
EnumeratedType
[55] StringType ::= 'CDATA'
[56] TokenizedType ::= 'ID' [验证条件: ID必须符合Name规则且在同一XML文档的这类型中惟一]
[验证条件: 一个元素类型至多有一个ID属性]
[验证条件: ID属性必须声明默认`#IMPLIED`或`#REQUIRED`]
| 'IDREF' [验证条件: IDREF类型的值必须匹配Name规则,其中Name必须匹配XML文档中的某个ID属性]
| 'IDREFS' [验证条件: IDREFS类型的值必须匹配Names,其中Name必须匹配XML文档中的某个ID属性]
| 'ENTITY' [验证条件: ENTITY类型的值必须匹配Name规则,其中Name必须匹配DTD中声明的未解析实体]
| 'ENTITIES' [验证条件: ENTITIES类型的值必须匹配Names,其中Name必须匹配DTD中声明的未解析实体]
| 'NMTOKEN' [验证条件: NMTOKEN类型的值必须匹配Nmtoken规则]
| 'NMTOKENS' [验证条件: NMTOKENS类型的值必须匹配Nmtokens规则]
[57] EnumeratedType ::= NotationType | Enumeration
[58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')' [验证条件:这类型的值必须匹配声明中某个记号名]
[验证条件:每个元素类型至多指定一个NOTATION属性]
[验证条件:EMPTY元素不能声明NOTATION属性]
[验证条件:单个属性声明中各记号名互异]
[59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')' [验证条件:这类型的值必须匹配声明中Nmtoken之一]
[验证条件: 单个属性声明中NmTokens互异]
[60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED'
| (('#FIXED' S)? AttValue) [验证条件: 若属性为`#REQUIRED`,则所有这类型元素必须给出这属性]
[验证条件: 默认值在语法上正确]
[良构条件: 属性值中直接或间接的实体引用的替换文本不含`<`]
[验证条件: 若属性声明为`#FIXED`,则属性的实例值必须匹配默认值]
[良构条件: 没有外部实体引用]
AttlistDecl中的Name为元素类型,AttDef中的Name则是属性名。有多个AttlistDecl时,它们的内容会合并,如果同一属性被重复声明,则首个生效。在属性声明中可指定在没有指定属性时如何处理:
#REQUIRED
表示必须提供属性#IMPLIED
表示没有默认值- 给定默认值,符合:
- IDREF或ENTITY类型的匹配Name规则
- IDREFS或ENTITIES类型的匹配Names规则
- NMTOKEN类型的匹配Nmtoken规则
- NMTOKENS类型的规则匹配Nmtokens规则
- 枚举类型(NOTATION或枚举)的匹配必须匹配一个枚举值
给出
#FIXED
表示属性必须有其默认值
<!ATTLIST termdef
id ID #REQUIRED
name CDATA #IMPLIED>
<!ATTLIST list
type (bullets|ordered|glossary) "ordered">
<!ATTLIST form
method CDATA #FIXED "POST">
实体声明
XML文档由称为实体的若干存储单元组成。已解析实体可以用引用,未解析实体则可用于类型为ENTITY或ENTITIES的属性。一般实体用在文档内容,参数实体则用于DTD,它们占用不同的名字空间。
[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
[9] EntityValue::= '"' ([^%&"] | PEReference | Reference)* '"'| "'" ([^%&'] | PEReference | Reference)* "'"
[76] NDataDecl ::= S 'NDATA' S Name [验证条件:Name匹配一个已声明记号]
其中Name指定引用实体用的名字。一个实体重复声明时首个生效。
- 内部实体给出EntityValue作为内容,内部实体都是已解析实体
- 否则为外部实体,SystemLiteral会被转换(必要时转义)为URI引用以便构造替换文字
- 有NDataDecl时为未解析实体
- 否则为已解析实体
以下是一些例子:
<!ENTITY Pub-Status "This is a pre-release of the
specification.">
<!ENTITY open-hatch
SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">
<!ENTITY open-hatch
PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN"
"http://www.textuality.com/boilerplate/OpenHatch.xml">
<!ENTITY hatch-pic
SYSTEM "../grafix/OpenHatch.gif"
NDATA gif >
外部已解析实体如extParsedEnt:
[77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
[78] extParsedEnt ::= TextDecl? content
另外,有预定义实体:
<!ENTITY lt "&#60;">
<!ENTITY gt ">">
<!ENTITY amp "&#38;">
<!ENTITY apos "'">
<!ENTITY quot """>
记号声明
记号给出未解析实体格式的名称,用于带notation属性的元素或处理指令。
[82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | [验证条件: 同一个Name不能在多个记号声明中重复声明]
PublicID) S? '>'
[83] PublicID ::= 'PUBLIC' S PubidLiteral
XML处理器必须向应用程序提供所声明和在属性值、属性定义或实体声明中引用的记号的名字和外部标识符,也可能定位外部标识符到系统标识符、文件名或其它信息以便调用辅助程序。
条件节
条件节用于根据参数实体引用决定包含或忽略内容。
[61] conditionalSect ::= includeSect | ignoreSect
[62] includeSect ::= '<![' S? 'INCLUDE' S? '[' [验证条件: 若条件节的`<![`、`[`或`]]>`部分在一个参数实体的替换文本中,则它们都要在]
extSubsetDecl ']]>'
[63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' [验证条件: 若条件节的`<![`、`[`或`]]>`部分在一个参数实体的替换文本中,则它们都要在]
ignoreSectContents* ']]>'
[64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents
']]>' Ignore)*
[65] Ignore ::= Char* - (Char* ('<![' | ']]>')
Char*)
若关键字为INCLUDE
,则条件节的内容会作为DTD的一部分处理;若关键字为IGNORE
,则条件节的内容不会作为DTD的一部分处理(内部的INCLUDE也忽略),其中参数引用也不识别。以下是一个例子:
<!ENTITY % draft 'INCLUDE' >
<!ENTITY % final 'IGNORE' >
<![%draft;[
<!ELEMENT book (comments*, title, body, supplements?)>
]]>
<![%final;[
<!ELEMENT book (title, body, supplements?)>
]]>
其它问题
实体引用的处理
上下文 | 参数实体 | 内部一般实体 | 外部已解析一般实体 | 外部未解析实体 | 字符实体 |
---|---|---|---|---|---|
在内容中引用 | 不识别 | 包含 | 有效则包含 | 禁止 | 包含 |
在属性值中引用 | 不识别 | 字面地包含 | 禁止 | 禁止 | 包含 |
作为属性值 | 不识别 | 禁止 | 禁止 | 向应用程序报告公共和系统标识符 | 不识别 |
在实体值中引用 | 字面地包含 | 保留 | 保留 | 错误 | 包含 |
在DTD中引用 | 作为参数实体包含 | 禁止 | 禁止 | 禁止 | 禁止 |
- 包含一般实体在用替换文本取代实体引用会继续处理,包含字符实体则在替换后不再处理
- 字面地包含在用替换文本取代实体引用会继续处理,但其中的引号被转义(
<!ENTITY EndAttr "27'" ><element attribute='a-&EndAttr;>
不合法) - 有效时包含意味着没有包含替换文本时向应用程序交代
-
作为参数实体包含的替换文本前后分别加上空格(只在有效时替换)
- 在DTD中引用指在内部或外部DTD子集(但在实体值、属性值、处理指令、注释、系统标识符、公共标识符或被忽略的条件节外)中引用
如对:
<!ENTITY % pub "Éditions Gallimard" >
<!ENTITY rights "All rights reserved" >
<!ENTITY book "La Peste: Albert Camus,
© 1947 %pub;. &rights;" >
则book的替换文字为:
La Peste: Albert Camus,
© 1947 Éditions Gallimard. &rights;
空白和文本
标签外的空白会被送给应用程序,但可以用取值为default
或preserve
的属性xml:space
提示应用程序如何处理空白。在DTD中应声明这属性如:
<!ATTLIST poem xml:space (default|preserve) 'preserve'>
<!ATTLIST pre xml:space (preserve) #FIXED 'preserve'>
各种行结束符会预先转换为#xA
:
#xD #xA
#xD #x85
#x85
#x2028
- 不接
#xA
或#x85
的#xD
可用属性xml:lang
提示属性和内容的语言,值如IETF BCP 47或空字符串(用于消除外围属性),如:
<p xml:lang="en">The quick brown fox jumps over the lazy dog.</p>
<p xml:lang="en-GB">What colour is it?</p>
<p xml:lang="en-US">What color is it?</p>
<sp who="Faust" desc='leise' xml:lang="de">
<l>Habe nun, ach! Philosophie,</l>
<l>Juristerei, und Medizin</l>
<l>und leider auch Theologie</l>
<l>durchaus studiert mit heißem Bemüh'n.</l>
</sp>
xml:lang
的简单声明可能如xml:lang CDATA #IMPLIED
,但也可能给出默认值,如:
<!ATTLIST poem xml:lang CDATA 'fr'>
<!ATTLIST gloss xml:lang CDATA 'en'>
<!ATTLIST note xml:lang CDATA 'en'>
编码检测
由于XML文档由<?xml
开始’:
有字节顺序标记情况 | 猜测 |
---|---|
00 00 FE FF | UCS-4, big-endian machine (1234 order) |
FF FE 00 00 | UCS-4, little-endian machine (4321 order) |
00 00 FF FE | UCS-4, unusual octet order (2143) |
FE FF 00 00 | UCS-4, unusual octet order (3412) |
FE FF ## ## | UTF-16, big-endian(## 不同为00) |
FF FE ## ## | UTF-16, little-endian |
EF BB BF | UTF-8 |
有字节顺序标记情况 | 猜测 |
---|---|
00 00 00 3C | UCS-4 或其它32位代码单元ASCII一致编码,big-endian (1234),再用编码声明 |
3C 00 00 00 | UCS-4 或其它32位代码单元ASCII一致编码,little-endian (4321),再用编码声明 |
00 00 3C 00 | UCS-4 或其它32位代码单元ASCII一致编码,(2143),再用编码声明 |
00 3C 00 00 | UCS-4 或其它32位代码单元ASCII一致编码,(3412),再用编码声明 |
00 3C 00 3F | UTF-16BE 或 big-endian ISO-10646-UCS-2 或其它big-endian16位代码单元ASCII一致编码再用编码声明 |
3C 00 3F 00 | UTF-16LE 或 little-endian ISO-10646-UCS-2或其它little-endian16位代码单元ASCII一致编码再用编码声明 |
3C 3F 78 6D | UTF-8, ISO 646, ASCII, ISO 8859, Shift-JIS, EUC或其它7/8位代码单元ASCII一致编码再用编码声明 |
4C 6F A7 94 | EBCDIC,再用编码声明 |
Other | 没有编码声明的UTF-8或损坏 |
在有外部编码信息时,各信息的优先级应由高级协议指定如IETF RFC 3023。建议对文件中的XML实体用字节顺序和编码顺序决定。
命名惯例
- 首字符应有Unicode属性ID_Start或为’_’
- 其余字符应有Unicode属性ID_Continue或为UAX中自然语言标识符字符(”'”和”’”除外)
- 字符应用正规化形式C表示
- 不宜用有规范分解的会意字符(如
[#xF900-#xFAFF]
或[#x2F800-#x2FFFD]
中的,但有12个例外) - 不宜用有相容分解的字符,但如在对应文字中正常使用则例外
- 组合字符(
[#x20D0-#x20EF]
或[#x1D165-#x1D1AD]
中)不应用于名字 - 不用
[#xFFF9-#xFFFB]
中字符 - 不应用可变选择器字符
- 不宜用不合常理、不可发音、难读或容易混淆的名字
与HTML对比
- 所有标签必须结束
- XML为空标签提供了语法糖如
<happiness />
- XML中属性值必须被引用
- XML没有内置的元素名
- XML中只有五个内置字符实体
<
、>
、&
、"
和'
分别表示<
、>
、&
、"
、'
,但你可定义其它字符实体 - XML支持十六进制字符引用如
&
名称空间
引入名称空间是为了降低发生名字冲突的可能性,这对重用XML文档是重要的。它的思想是引入由名字空间名和局部名组成的全名。名字空间用IRI(见IETF RFC 3987)标识,但不允许空字符串,相对引用也被视为过时。由于IRI太长且部分字符不能用于XML名字,在命名元素和属性时用限定名代替,但要声明对应的IRI引用。更准确地说,在使用XML名字空间的文档中Name
必须匹配QName
:
[7] QName ::= PrefixedName | UnprefixedName
[8] PrefixedName ::= Prefix ':' LocalPart
[9] UnprefixedName ::= LocalPart
[10] Prefix ::= NCName
[11] LocalPart ::= NCName
[4] NCName ::= NCNameStartChar NCNameChar* /* An XML Name, minus the ":" */
[5] NCNameChar ::= NameChar - ':'
[6] NCNameStartChar ::= NameStartChar - ':'
声明名字空间是通过以下属性完成的:
[1] NSAttName ::= PrefixedAttName | DefaultAttName
[2] PrefixedAttName ::= 'xmlns:' NCName [名称空间约束: 前缀xml总是绑定到http://www.w3.org/XML/1998/namespace,xmlns总绑定到http://www.w3.org/2000/xmlns/,不能反绑定这两个前缀(后者甚至原样绑定都不能),其它前缀不能绑定到它们,也不能声明为默认名称空间]
[3] DefaultAttName ::= 'xmlns'
这些属性的正规化值必须为IRI引用或空字符串(后者表示在作用域取消绑定)
- 若属性名匹配
PrefixedAttName
,则前缀NCName
绑定到时属性值指定的名称空间 - 若属性名匹配
DefaultAttName
,则把属性值指定的名称空间作为默认名称空间(不指定前缀的元素名视为在它里面的局部名) 作用域为属性所有元素。如通常的,如果一个前缀或默认名称空间被多次声明,按最内层优先原则。
IRI引用的比较是字符串比较,区分大小写,且不会解码%
转义,所以不同可能解析到相同的资源。由于名称空间声明中IRI引用为属性的正规化值,故实体和字符引用已经替换。
由(('X'|'x') ('M'|'m') ('L'|'l'))
开始的前缀留给XML标准用,到于局部名这样开始是不宜用的(这样只能带前缀用)。
对于使用名字空间的文档,一些XML语法会有更多限制(防止一个元素的两个属性有相同全名之类):
[12] STag ::= '<' QName (S Attribute)* S? '>' [名称空间约束:除了xml或xmlns,用到的前缀必须在本元素或某个祖先元素声明且最内层的绑定不是空字符串]
[13] ETag ::= '</' QName S? '>' [名称空间约束:除了xml或xmlns,用到的前缀必须在本元素或某个祖先元素声明且最内层的绑定不是空字符串]
[14] EmptyElemTag ::= '<' QName (S Attribute)* S? '/>' [名称空间约束:除了xml或xmlns,用到的前缀必须在本元素或某个祖先元素声明且最内层的绑定不是空字符串]
[15] Attribute ::= NSAttName Eq AttValue
| QName Eq AttValue [名称空间约束:除了xml或xmlns,用到的前缀必须在本元素或某个祖先元素声明且最内层的绑定不是空字符串]
[16] doctypedecl ::= '<!DOCTYPE' S QName (S ExternalID)? S? ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
[17] elementdecl ::= '<!ELEMENT' S QName S contentspec S? '>'
[18] cp ::= (QName | choice | seq) ('?' | '*' | '+')?
[19] Mixed ::= '(' S? '#PCDATA' (S? '|' S? QName)* S? ')*' | '(' S? '#PCDATA' S? ')'
[20] AttlistDecl ::= '<!ATTLIST' S QName AttDef* S? '>'
[21] AttDef ::= S (QName | NSAttName) S AttType S DefaultDecl
例如:
<x xmlns:edi='http://ecommerce.example.org/schema'>
<!-- the "edi" prefix is bound to http://ecommerce.example.org/schema
for the "x" element and contents -->
</x>
<!-- the 'price' element's namespace is http://ecommerce.example.org/schema -->
<edi:price xmlns:edi='http://ecommerce.example.org/schema' units='Euro'>32.18</edi:price>
<x xmlns:edi='http://ecommerce.example.org/schema'>
<!-- the 'taxClass' attribute's namespace is http://ecommerce.example.org/schema -->
<lineItem edi:taxClass="exempt">Baby food</lineItem>
</x>
完整的例子:
<?xml version="1.1"?>
<!-- initially, the default namespace is "books" -->
<book xmlns='urn:loc.gov:books'
xmlns:isbn='urn:ISBN:0-395-36341-6'>
<title>Cheaper by the Dozen</title>
<isbn:number>1568491379</isbn:number>
<notes>
<!-- make HTML the default namespace for some commentary -->
<p xmlns='http://www.w3.org/1999/xhtml'>
This is a <i>funny</i> book!
</p>
</notes>
</book>
注意,基于DTD的验证不是名称空间感知的:为了验证一个用名称空间的文档,DTD中要用相同的前缀。DTD中可通过#FIXED
属性控制名字空间。
总结一下,在使用名字空间的文档,所有元素和属性名必须符合QName规则且满足名字空间约束,其它为良构性(有效性)要满足XML中Name规则的也要满足NCName规则,特别地:
- 所有元素或属性名至多有一个冒号
- 实体名、处理指令目标或记号名都没有冒号
- 在类型为ID、IDREF(S)、ENTITY(IES)或NOTATION的属性值不含冒号(若有有效性要求)
XML模式
XML模式是用于描述一类XML文档应满足的约束的语言,它能
- 提供元素和属性的词汇表
- 为文档中和值指定类型
- 控制元素和属性可出现的位置
- 作为人和机器都能读的文档
- 给出一类文档的形式定义
- 协助编辑器提供自动补全等功能
现成的XML验证器可验证一个XML文档是否满足一个特定的模式,还可能给出类型信息。
XML模式定义(XML Schema Definitions)是W3官方的模式语言,XSD本身就是基于XML,以下用DTD近似刻画它,根元素类型就是schema
。其中,名字空间没有准确处理,使用时有关名字大都在名字空间http://www.w3.org/2001/XMLSchema
(常用前缀xsd
)。
<!ENTITY % complexDerivationSet "CDATA">
<!-- #all or space-separated list drawn from derivationChoice -->
<!ENTITY % blockSet "CDATA">
<!-- #all or space-separated list drawn from
derivationChoice + 'substitution' -->
<!ENTITY % composition 'include | import | override | redefine'>
<!ENTITY % mgs 'all | choice | sequence'>
<!ENTITY % cs 'choice | sequence'>
<!ENTITY % formValues '(qualified|unqualified)'>
<!ENTITY % attrDecls '((attribute| attributeGroup)*,(anyAttribute)?)'>
<!ENTITY % assertions '(assert)*'>
<!ENTITY % particleAndAttrs '(openContent?, (%mgs; | group)?,
%attrDecls;, %assertions;)'>
<!-- the duplication below is to produce an unambiguous content model
which allows annotation everywhere -->
<!ELEMENT schema ((%composition; | annotation)*,
(defaultOpenContent, (annotation)*)?,
((simpleType | complexType
| element | attribute
| attributeGroup | group
| notation ),
(annotation)*)* )>
<!ATTLIST schema
targetNamespace %URIref; #IMPLIED
version CDATA #IMPLIED
xmlns:xs %URIref; #FIXED 'http://www.w3.org/2001/XMLSchema'
xmlns CDATA #IMPLIED
finalDefault %complexDerivationSet; ''
blockDefault %blockSet; ''
id ID #IMPLIED
elementFormDefault %formValues; 'unqualified'
attributeFormDefault %formValues; 'unqualified'
defaultAttributes CDATA #IMPLIED
xpathDefaultNamespace CDATA '##local'
xml:lang CDATA #IMPLIED>
<!-- Note the xmlns declaration is NOT in the
schema for schema documents,
because at the Infoset level where schemas operate,
xmlns(:prefix) is NOT an attribute! -->
<!-- The declaration of xmlns is a convenience for schema authors -->
<!-- The id attribute here and below is for use in external references
from non-schemas using simple fragment identifiers.
It is NOT used for schema-to-schema reference, internal or
external. -->
<!ELEMENT defaultOpenContent ((annotation)?, any)>
<!ATTLIST defaultOpenContent
appliesToEmpty (true|false) 'false'
mode (interleave|suffix) 'interleave'
id ID #IMPLIED>
类型
简单类型
简单类型没有属性也没有子元素,其中最基本的原子类型和它们可加的约束如下表:
原子类型 | length|minLength|maxLength|pattern|enumeration|whiteSpace
:—|:—|:—|:—|:—|:—|:—
string | y | y | y | y | y | y
normalizedString | y | y | y | y | y | y
token | y | y | y | y | y | 见 (1)
base64Binary | y | y | y | y | y | 见 (1)
hexBinary | y | y | y | y | y | 见 (1)
integer | | | | y | y | 见 (1)
positiveInteger | | | | y | y | 见 (1)
negativeInteger | | | | y | y | 见 (1)
nonNegativeInteger| | | | y | y | 见 (1)
nonPositiveInteger| | | | y | y | 见 (1)
long | | | | y | y | 见 (1)
unsignedLong | | | | y | y | 见 (1)
int | | | | y | y | 见 (1)
unsignedInt | | | | y | y | 见 (1)
short | | | | y | y | 见 (1)
unsignedShort | | | | y | y | 见 (1)
byte | | | | y | y | 见 (1)
unsignedByte | | | | y | y | 见 (1)
decimal | | | | y | y | 见 (1)
float | | | | y | y | 见 (1)
double | | | | y | y | 见 (1)
boolean | | | | y | | 见 (1)
duration | | | | y | y | 见 (1)
dateTime | | | | y | y | 见 (1)
date | | | | y | y | 见 (1)
time | | | | y | y | 见 (1)
gYear | | | | y | y | 见 (1)
gYearMonth | | | | y | y | 见 (1)
gMonth | | | | y | y | 见 (1)
gMonthDay | | | | y | y | 见 (1)
gDay | | | | y | y | 见 (1)
Name | y | y | y | y | y | 见 (1)
QName | y | y | y | y | y | 见 (1)
NCName | y | y | y | y | y | 见 (1)
anyURI | y | y | y | y | y | 见 (1)
language | y | y | y | y | y | 见 (1)
ID | y | y | y | y | y | 见 (1)
IDREF | y | y | y | y | y | 见 (1)
IDREFS | y | y | y | y | y | 见 (1)
ENTITY | y | y | y | y | y | 见 (1)
ENTITIES | y | y | y | y | y | 见 (1)
NOTATION | y | y | y | y | y | 见 (1)
NMTOKEN | y | y | y | y | y | 见 (1)
NMTOKENS | y | y | y | y | y | 见 (1)
(1) whiteSpace
约束的惟一可用值为collapse
原子类型 |maxInclusive | maxExclusive | minInclusive | minExclusive | totalDigits | fractionDigits
:—|:—|:—|:—|:—|:—|:—
integer | y | y | y | y | y | 见 (1)
positiveInteger | y | y | y | y | y | 见 (1)
negativeInteger | y | y | y | y | y | 见 (1)
nonNegativeInteger| y | y | y | y | y | 见 (1)
nonPositiveInteger| y | y | y | y | y | 见 (1)
long | y | y | y | y | y | 见 (1)
unsignedLong | y | y | y | y | y | 见 (1)
int | y | y | y | y | y | 见 (1)
unsignedInt | y | y | y | y | y | 见 (1)
short | y | y | y | y | y | 见 (1)
unsignedShort | y | y | y | y | y | 见 (1)
byte | y | y | y | y | y | 见 (1)
unsignedByte | y | y | y | y | y | 见 (1)
decimal | y | y | y | y | y | y
float | y | y | y | y | |
double | y | y | y | y | |
duration | y | y | y | y | |
dateTime | y | y | y | y | |
date | y | y | y | y | |
time | y | y | y | y | |
gYear | y | y | y | y | |
gYearMonth | y | y | y | y | |
gMonth | y | y | y | y | |
gMonthDay | y | y | y | y | |
gDay | y | y | y | y | |
(1) fractionDigits
约束的惟一可用值为零
可以通过原子类型用simpleType
构造其它简单类型:
- 通过对原子类型增加上述约束
- 若干个原子类型的并类型
- 元素类型分别为指定原子类型的列表类型
<!-- Define some entities for informative use as attribute
types -->
<!ENTITY % URIref "CDATA">
<!ENTITY % XPathExpr "CDATA">
<!ENTITY % QName "NMTOKEN">
<!ENTITY % QNames "NMTOKENS">
<!ENTITY % NCName "NMTOKEN">
<!ENTITY % nonNegativeInteger "NMTOKEN">
<!ENTITY % boolean "(true|false)">
<!ENTITY % simpleDerivationSet "CDATA">
<!--
#all or space-separated list drawn from derivationChoice
-->
<!--
Note that the use of 'facet' below is less restrictive
than is really intended: There should in fact be no
more than one of each of minInclusive, minExclusive,
maxInclusive, maxExclusive, totalDigits, fractionDigits,
length, maxLength, minLength within datatype,
and the min- and max- variants of Inclusive and Exclusive
are mutually exclusive. On the other hand, pattern and
enumeration and assertion may repeat.
-->
<!ENTITY % minBound "(minInclusive | minExclusive)">
<!ENTITY % maxBound "(maxInclusive | maxExclusive)">
<!ENTITY % bounds "%minBound; | %maxBound;">
<!ENTITY % numeric "totalDigits | fractionDigits">
<!ENTITY % ordered "%bounds; | %numeric;">
<!ENTITY % unordered
"pattern | enumeration | whiteSpace | length |
maxLength | minLength | assertion | explicitTimezone">
<!ENTITY % implementation-defined-facets "">
<!ENTITY % facet "%ordered; | %unordered; %implementation-defined-facets;">
<!ENTITY % facetAttr
"value CDATA #REQUIRED
id ID #IMPLIED">
<!ENTITY % fixedAttr "fixed %boolean; #IMPLIED">
<!ENTITY % facetModel "(annotation)?">
<!ELEMENT simpleType
((annotation)?, (restriction | list | union))>
<!ATTLIST simpleType
name %NCName; #IMPLIED
final %simpleDerivationSet; #IMPLIED
id ID #IMPLIED>
<!-- name is required at top level -->
<!ENTITY % restriction1 '(%openContent;?, (%mgs; | group)?)'>
<!ELEMENT restriction ((annotation)?,
(%restriction1; |
((simpleType)?,(%facet;)*)),
(%attrDecls;))>
<!ATTLIST restriction
base %QName; #IMPLIED
id ID #IMPLIED>
<!--
base and simpleType child are mutually exclusive,
one is required.
restriction is shared between simpleType and
simpleContent and complexContent (in XMLSchema.xsd).
restriction1 is for the latter cases, when this
is restricting a complex type, as is attrDecls.
-->
<!ELEMENT list ((annotation)?,(simpleType)?)>
<!ATTLIST list
itemType %QName; #IMPLIED
id ID #IMPLIED>
<!--
itemType and simpleType child are mutually exclusive,
one is required
-->
<!ELEMENT union ((annotation)?,(simpleType)*)>
<!ATTLIST union
id ID #IMPLIED
memberTypes %QNames; #IMPLIED>
<!--
At least one item in memberTypes or one simpleType
child is required
-->
<!ELEMENT maxExclusive %facetModel;>
<!ATTLIST maxExclusive
%facetAttr;
%fixedAttr;>
<!ELEMENT minExclusive %facetModel;>
<!ATTLIST minExclusive
%facetAttr;
%fixedAttr;>
<!ELEMENT maxInclusive %facetModel;>
<!ATTLIST maxInclusive
%facetAttr;
%fixedAttr;>
<!ELEMENT minInclusive %facetModel;>
<!ATTLIST minInclusive
%facetAttr;
%fixedAttr;>
<!ELEMENT totalDigits %facetModel;>
<!ATTLIST totalDigits
%facetAttr;
%fixedAttr;>
<!ELEMENT fractionDigits %facetModel;>
<!ATTLIST fractionDigits
%facetAttr;
%fixedAttr;>
<!ELEMENT length %facetModel;>
<!ATTLIST length
%facetAttr;
%fixedAttr;>
<!ELEMENT minLength %facetModel;>
<!ATTLIST minLength
%facetAttr;
%fixedAttr;>
<!ELEMENT maxLength %facetModel;>
<!ATTLIST maxLength
%facetAttr;
%fixedAttr;>
<!-- This one can be repeated -->
<!ELEMENT enumeration %facetModel;>
<!ATTLIST enumeration
%facetAttr;>
<!ELEMENT whiteSpace %facetModel;>
<!ATTLIST whiteSpace
%facetAttr;
%fixedAttr;>
<!-- This one can be repeated -->
<!ELEMENT pattern %facetModel;>
<!ATTLIST pattern
%facetAttr;>
<!ELEMENT assertion %facetModel;>
<!ATTLIST assertion
%facetAttr;>
<!ELEMENT explicitTimezone %facetModel;>
<!ATTLIST explicitTimezone
%facetAttr;>
xsi:noNamespaceSchemaLocation: instance element [Structures]
xsi:nil: instance element [Structures]
xsi:type: instance element [Structures]
复合类型
<!-- a type is a named content type specification which allows attribute
declarations-->
<!-- -->
<!ELEMENT complexType ((annotation)?,
(simpleContent|complexContent|
%particleAndAttrs;))>
<!ATTLIST complexType
name %NCName; #IMPLIED
id ID #IMPLIED
abstract %boolean; #IMPLIED
final %complexDerivationSet; #IMPLIED
block %complexDerivationSet; #IMPLIED
mixed (true|false) 'false'
defaultAttributesApply %boolean; 'true'>
<!-- particleAndAttrs is shorthand for a root type -->
<!-- mixed is disallowed if simpleContent, overridden if complexContent has one too. -->
<!-- If anyAttribute appears in one or more referenced attributeGroups
and/or explicitly, the intersection of the permissions is used -->
<!ELEMENT complexContent ((annotation)?, (restriction|extension))>
<!ATTLIST complexContent
mixed (true|false) #IMPLIED
id ID #IMPLIED>
<!ELEMENT openContent ((annotation)?, (any)?)>
<!ATTLIST openContent
mode (none|interleave|suffix) 'interleave'
id ID #IMPLIED>
<!-- restriction should use the branch defined above, not the simple
one from part2; extension should use the full model -->
<!ELEMENT simpleContent ((annotation)?, (restriction|extension))>
<!ATTLIST simpleContent
id ID #IMPLIED>
<!-- restriction should use the simple branch from part2, not the
one defined above; extension should have no particle -->
<!ELEMENT extension ((annotation)?, (%particleAndAttrs;))>
<!ATTLIST extension
base %QName; #REQUIRED
id ID #IMPLIED
>
元素的声明
<!-- an element is declared by either:
a name and a type (either nested or referenced via the type attribute)
or a ref to an existing element declaration -->
<!ELEMENT element ((annotation)?, (complexType| simpleType)?,
(alternative)*,
(unique | key | keyref)*)>
<!-- simpleType or complexType only if no type|ref attribute -->
<!-- ref not allowed at top level -->
<!ATTLIST element
name %NCName; #IMPLIED
id ID #IMPLIED
ref %QName; #IMPLIED
type %QName; #IMPLIED
minOccurs %nonNegativeInteger; #IMPLIED
maxOccurs CDATA #IMPLIED
nillable %boolean; #IMPLIED
substitutionGroup %QName; #IMPLIED
abstract %boolean; #IMPLIED
final %complexDerivationSet; #IMPLIED
block %blockSet; #IMPLIED
default CDATA #IMPLIED
fixed CDATA #IMPLIED
form %formValues; #IMPLIED
targetNamespace %URIref; #IMPLIED>
<!-- type and ref are mutually exclusive.
name and ref are mutually exclusive, one is required -->
<!-- In the absence of type AND ref, type defaults to type of
substitutionGroup, if any, else xs:anyType, i.e. unconstrained -->
<!-- default and fixed are mutually exclusive -->
<!ELEMENT alternative ((annotation)?,
(simpleType | complexType)?) >
<!ATTLIST alternative
test CDATA #IMPLIED
type %QName; #IMPLIED
xpathDefaultNamespace CDATA #IMPLIED
id ID #IMPLIED >
<!ELEMENT group ((annotation)?,(%mgs;)?)>
<!ATTLIST group
name %NCName; #IMPLIED
ref %QName; #IMPLIED
minOccurs %nonNegativeInteger; #IMPLIED
maxOccurs CDATA #IMPLIED
id ID #IMPLIED>
<!ELEMENT all ((annotation)?, (element| group| any)*)>
<!ATTLIST all
minOccurs (0 | 1) #IMPLIED
maxOccurs (0 | 1) #IMPLIED
id ID #IMPLIED>
<!ELEMENT choice ((annotation)?, (element| group| %cs; | any)*)>
<!ATTLIST choice
minOccurs %nonNegativeInteger; #IMPLIED
maxOccurs CDATA #IMPLIED
id ID #IMPLIED>
<!ELEMENT sequence ((annotation)?, (element| group| %cs; | any)*)>
<!ATTLIST sequence
minOccurs %nonNegativeInteger; #IMPLIED
maxOccurs CDATA #IMPLIED
id ID #IMPLIED>
<!-- an anonymous grouping in a model, or
a top-level named group definition, or a reference to same -->
<!ELEMENT any (annotation)?>
<!ATTLIST any
namespace CDATA #IMPLIED
notNamespace CDATA #IMPLIED
notQName CDATA ''
processContents (skip|lax|strict) 'strict'
minOccurs %nonNegativeInteger; '1'
maxOccurs CDATA '1'
id ID #IMPLIED>
<!-- namespace is interpreted as follows:
##any - - any non-conflicting WFXML at all
##other - - any non-conflicting WFXML from namespace other
than targetNamespace
##local - - any unqualified non-conflicting WFXML/attribute
one or - - any non-conflicting WFXML from
more URI the listed namespaces
references
##targetNamespace ##local may appear in the above list,
with the obvious meaning -->
<!-- notNamespace is interpreted as follows:
##local - - any unqualified non-conflicting WFXML/attribute
one or - - any non-conflicting WFXML from
more URI the listed namespaces
references
##targetNamespace ##local may appear in the above list,
with the obvious meaning -->
属性声明
<!ELEMENT anyAttribute (annotation)?>
<!ATTLIST anyAttribute
namespace CDATA #IMPLIED
notNamespace CDATA #IMPLIED
notQName CDATA ''
processContents (skip|lax|strict) 'strict'
id ID #IMPLIED>
<!-- namespace and notNamespace are interpreted as for 'any' above -->
<!-- simpleType only if no type|ref attribute -->
<!-- ref not allowed at top level, name iff at top level -->
<!ELEMENT attribute ((annotation)?, (simpleType)?)>
<!ATTLIST attribute
name %NCName; #IMPLIED
id ID #IMPLIED
ref %QName; #IMPLIED
type %QName; #IMPLIED
use (prohibited|optional|required) #IMPLIED
default CDATA #IMPLIED
fixed CDATA #IMPLIED
form %formValues; #IMPLIED
targetNamespace %URIref; #IMPLIED
inheritable %boolean; #IMPLIED>
<!-- type and ref are mutually exclusive.
name and ref are mutually exclusive, one is required -->
<!-- default for use is optional when nested, none otherwise -->
<!-- default and fixed are mutually exclusive -->
<!-- type attr and simpleType content are mutually exclusive -->
<!-- an attributeGroup is a named collection of attribute decls, or a
reference thereto -->
<!ELEMENT attributeGroup ((annotation)?,
(attribute | attributeGroup)*,
(anyAttribute)?) >
<!ATTLIST attributeGroup
name %NCName; #IMPLIED
id ID #IMPLIED
ref %QName; #IMPLIED>
<!-- ref iff no content, no name. ref iff not top level -->
<!-- better reference mechanisms -->
<!ELEMENT unique ((annotation)?, selector, (field)+)>
<!ATTLIST unique
name %NCName; #IMPLIED
ref %QName; #IMPLIED
id ID #IMPLIED>
<!ELEMENT key ((annotation)?, selector, (field)+)>
<!ATTLIST key
name %NCName; #IMPLIED
ref %QName; #IMPLIED
id ID #IMPLIED>
<!ELEMENT keyref ((annotation)?, selector, (field)+)>
<!ATTLIST keyref
name %NCName; #IMPLIED
ref %QName; #IMPLIED
refer %QName; #IMPLIED
id ID #IMPLIED>
<!ELEMENT selector ((annotation)?)>
<!ATTLIST selector
xpath XPathExpr #REQUIRED
xpathDefaultNamespace CDATA #IMPLIED
id ID #IMPLIED>
<!ELEMENT field ((annotation)?)>
<!ATTLIST field
xpath XPathExpr #REQUIRED
xpathDefaultNamespace CDATA #IMPLIED
id ID #IMPLIED>
其它
断言
<!-- co-constraint assertions -->
<!ELEMENT assert ((annotation)?)>
<!ATTLIST assert
test %XPathExpr; #REQUIRED
id ID #IMPLIED
xpathDefaultNamespace CDATA #IMPLIED>
导入
<!-- Schema combination mechanisms -->
<!ELEMENT include (annotation)?>
<!ATTLIST include
schemaLocation %URIref; #REQUIRED
id ID #IMPLIED>
<!ELEMENT import (annotation)?>
<!ATTLIST import
namespace %URIref; #IMPLIED
schemaLocation %URIref; #IMPLIED
id ID #IMPLIED>
<!ELEMENT redefine (annotation | simpleType | complexType |
attributeGroup | group)*>
<!ATTLIST redefine
schemaLocation %URIref; #REQUIRED
id ID #IMPLIED>
<!ELEMENT override ((annotation)?,
((simpleType | complexType | group | attributeGroup) |
element | attribute | notation)*)>
<!ATTLIST override
schemaLocation %URIref; #REQUIRED
id ID #IMPLIED>
<!ELEMENT notation (annotation)?>
<!ATTLIST notation
name %NCName; #REQUIRED
id ID #IMPLIED
public CDATA #REQUIRED
system %URIref; #IMPLIED>
注解
在XML schema中,除了用面向设计者的注释外,还可以加入面向用户的注解(有点像javadocs),它们位于元素xsd:annotation
(如有,则通常为其父元素的首个子元素)的子元素xsd:documentation
(面向人)或xsd:appinfo
(面向机器)中。
<!-- Annotation is either application information or documentation -->
<!-- By having these here they are available for datatypes as well
as all the structures elements -->
<!ELEMENT annotation (appinfo | documentation)*>>
<!-- User must define annotation elements in internal subset for this
to work -->
<!ELEMENT appinfo ANY> <!-- too restrictive -->
<!ATTLIST appinfo
source %URIref; #IMPLIED
id ID #IMPLIED>
<!ELEMENT documentation ANY> <!-- too restrictive -->
<!ATTLIST documentation
source %URIref; #IMPLIED
id ID #IMPLIED
xml:lang CDATA #IMPLIED>
关于Schema的详细语法,参考http://www.w3.org/2001/XMLSchema.xsd与http://www.w3.org/2009/XMLSchema/datatypes.xsd或http://www.w3.org/2009/XMLSchema/XMLSchema.dtd与
XML查询
XQuery类似于SQL,但用于整合数据。XQuery 1.0语法如下:
[1] Module ::= VersionDecl? (LibraryModule | MainModule)
[2] VersionDecl ::= "xquery" "version" StringLiteral ("encoding" StringLiteral)? Separator
[3] MainModule ::= Prolog QueryBody
[4] LibraryModule ::= ModuleDecl Prolog
[5] ModuleDecl ::= "module" "namespace" NCName "=" URILiteral Separator
[6] Prolog ::= ((DefaultNamespaceDecl | Setter | NamespaceDecl | Import) Separator)* ((VarDecl | FunctionDecl | OptionDecl) Separator)
[7] Setter ::= BoundarySpaceDecl | DefaultCollationDecl | BaseURIDecl | ConstructionDecl | OrderingModeDecl | EmptyOrderDecl |
[8] Import ::= SchemaImport | ModuleImport
[9] Separator ::= ";"
[10] NamespaceDecl ::= "declare" "namespace" NCName "=" URILiteral
[11] BoundarySpaceDecl ::= "declare" "boundary-space" ("preserve" | "strip")
[12] DefaultNamespaceDecl ::= "declare" "default" ("element" | "function") "namespace" URILiteral
[13] OptionDecl ::= "declare" "option" QName StringLiteral
[14] OrderingModeDecl ::= "declare" "ordering" ("ordered" | "unordered")
[15] EmptyOrderDecl ::= "declare" "default" "order" "empty" ("greatest" | "least")
[16] CopyNamespacesDecl ::= "declare" "copy-namespaces" PreserveMode "," InheritMode
[17] PreserveMode ::= "preserve" | "no-preserve"
[18] InheritMode ::= "inherit" | "no-inherit"
[19] DefaultCollationDecl ::= "declare" "default" "collation" URILiteral
[20] BaseURIDecl ::= "declare" "base-uri" URILiteral
[21] SchemaImport ::= "import" "schema" SchemaPrefix? URILiteral ("at" URILiteral ("," URILiteral)*)?
[22] SchemaPrefix ::= ("namespace" NCName "=") | ("default" "element" "namespace")
[23] ModuleImport ::= "import" "module" ("namespace" NCName "=")? URILiteral ("at" URILiteral ("," URILiteral)*)?
[24] VarDecl ::= "declare" "variable" "$" QName TypeDeclaration? ((":=" ExprSingle) | "external")
[25] ConstructionDecl ::= "declare" "construction" ("strip" | "preserve")
[26] FunctionDecl ::= "declare" "function" QName "(" ParamList? ")" ("as" SequenceType)? (EnclosedExpr | "external")
[27] ParamList ::= Param ("," Param)*
[28] Param ::= "$" QName TypeDeclaration?
[29] EnclosedExpr ::= "{" Expr "}"
[30] QueryBody ::= Expr
[31] Expr ::= ExprSingle ("," ExprSingle)*
[32] ExprSingle ::= FLWORExpr
| QuantifiedExpr
| TypeswitchExpr
| IfExpr
| OrExpr
[33] FLWORExpr ::= (ForClause | LetClause)+ WhereClause? OrderByClause? "return" ExprSingle
[34] ForClause ::= "for" "$" VarName TypeDeclaration? PositionalVar? "in" ExprSingle ("," "$" VarName TypeDeclaration? PositionalVar? "in"
ExprSingle)*
[35] PositionalVar ::= "at" "$" VarName
[36] LetClause ::= "let" "$" VarName TypeDeclaration? ":=" ExprSingle ("," "$" VarName TypeDeclaration? ":=" ExprSingle)*
[37] WhereClause ::= "where" ExprSingle
[38] OrderByClause ::= (("order" "by") | ("stable" "order" "by")) OrderSpecList
[39] OrderSpecList ::= OrderSpec ("," OrderSpec)*
[40] OrderSpec ::= ExprSingle OrderModifier
[41] OrderModifier ::= ("ascending" | "descending")? ("empty" ("greatest" | "least"))? ("collation" URILiteral)?
[42] QuantifiedExpr ::= ("some" | "every") "$" VarName TypeDeclaration? "in" ExprSingle ("," "$" VarName TypeDeclaration? "in" ExprSingle)*
"satisfies" ExprSingle
[43] TypeswitchExpr ::= "typeswitch" "(" Expr ")" CaseClause+ "default" ("$" VarName)? "return" ExprSingle
[44] CaseClause ::= "case" ("$" VarName "as")? SequenceType "return" ExprSingle
[45] IfExpr ::= "if" "(" Expr ")" "then" ExprSingle "else" ExprSingle
[46] OrExpr ::= AndExpr ( "or" AndExpr )*
[47] AndExpr ::= ComparisonExpr ( "and" ComparisonExpr )*
[48] ComparisonExpr ::= RangeExpr ( (ValueComp
| GeneralComp
| NodeComp) RangeExpr )?
[49] RangeExpr ::= AdditiveExpr ( "to" AdditiveExpr )?
[50] AdditiveExpr ::= MultiplicativeExpr ( ("+" | "-") MultiplicativeExpr )*
[51] MultiplicativeExpr ::= UnionExpr ( ("*" | "div" | "idiv" | "mod") UnionExpr )*
[52] UnionExpr ::= IntersectExceptExpr ( ("union" | "|") IntersectExceptExpr )*
[53] IntersectExceptExpr ::= InstanceofExpr ( ("intersect" | "except") InstanceofExpr )*
[54] InstanceofExpr ::= TreatExpr ( "instance" "of" SequenceType )?
[55] TreatExpr ::= CastableExpr ( "treat" "as" SequenceType )?
[56] CastableExpr ::= CastExpr ( "castable" "as" SingleType )?
[57] CastExpr ::= UnaryExpr ( "cast" "as" SingleType )?
[58] UnaryExpr ::= ("-" | "+")* ValueExpr
[59] ValueExpr ::= ValidateExpr | PathExpr | ExtensionExpr
[60] GeneralComp ::= "=" | "!=" | "<" | "<=" | ">" | ">="
[61] ValueComp ::= "eq" | "ne" | "lt" | "le" | "gt" | "ge"
[62] NodeComp ::= "is" | "<<" | ">>"
[63] ValidateExpr ::= "validate" ValidationMode? "{" Expr "}"
[64] ValidationMode ::= "lax" | "strict"
[65] ExtensionExpr ::= Pragma+ "{" Expr? "}"
[66] Pragma ::= "(#" S? QName (S PragmaContents)? "#)" /* ws: explicit */
[67] PragmaContents ::= (Char* - (Char* '#)' Char*))
[68] PathExpr ::= ("/" RelativePathExpr?) /* xgs: leading-lone-slash */
| ("//" RelativePathExpr)
| RelativePathExpr
[69] RelativePathExpr ::= StepExpr (("/" | "//") StepExpr)*
[70] StepExpr ::= FilterExpr | AxisStep
[71] AxisStep ::= (ReverseStep | ForwardStep) PredicateList
[72] ForwardStep ::= (ForwardAxis NodeTest) | AbbrevForwardStep
[73] ForwardAxis ::= ("child" "::")
| ("descendant" "::")
| ("attribute" "::")
| ("self" "::")
| ("descendant-or-self" "::")
| ("following-sibling" "::")
| ("following" "::")
[74] AbbrevForwardStep ::= "@"? NodeTest
[75] ReverseStep ::= (ReverseAxis NodeTest) | AbbrevReverseStep
[76] ReverseAxis ::= ("parent" "::")
| ("ancestor" "::")
| ("preceding-sibling" "::")
| ("preceding" "::")
| ("ancestor-or-self" "::")
[77] AbbrevReverseStep ::= ".."
[78] NodeTest ::= KindTest | NameTest
[79] NameTest ::= QName | Wildcard
[80] Wildcard ::= "*" /* ws: explicit */
| (NCName ":" "*")
| ("*" ":" NCName)
[81] FilterExpr ::= PrimaryExpr PredicateList
[82] PredicateList ::= Predicate*
[83] Predicate ::= "[" Expr "]"
[84] PrimaryExpr ::= Literal | VarRef | ParenthesizedExpr | ContextItemExpr | FunctionCall | OrderedExpr | UnorderedExpr | Constructor
[85] Literal ::= NumericLiteral | StringLiteral
[86] NumericLiteral ::= IntegerLiteral | DecimalLiteral | DoubleLiteral
[87] VarRef ::= "$" VarName
[88] VarName ::= QName
[89] ParenthesizedExpr ::= "(" Expr? ")"
[90] ContextItemExpr ::= "."
[91] OrderedExpr ::= "ordered" "{" Expr "}"
[92] UnorderedExpr ::= "unordered" "{" Expr "}"
[93] FunctionCall ::= QName "(" (ExprSingle ("," ExprSingle)*)? ")" /* xgs:
reserved-function-names */
/* gn: parens */
[94] Constructor ::= DirectConstructor
| ComputedConstructor
[95] DirectConstructor ::= DirElemConstructor
| DirCommentConstructor
| DirPIConstructor
[96] DirElemConstructor ::= "<" QName DirAttributeList ("/>" | (">" DirElemContent* "</" QName S? ">")) /* ws: explicit */
[97] DirAttributeList ::= (S (QName S? "=" S? DirAttributeValue)?)* /* ws: explicit */
[98] DirAttributeValue ::= ('"' (EscapeQuot | QuotAttrValueContent)* '"') /* ws: explicit */
| ("'" (EscapeApos | AposAttrValueContent)* "'")
[99] QuotAttrValueContent ::= QuotAttrContentChar
| CommonContent
[100] AposAttrValueContent ::= AposAttrContentChar
| CommonContent
[101] DirElemContent ::= DirectConstructor
| CDataSection
| CommonContent
| ElementContentChar
[102] CommonContent ::= PredefinedEntityRef | CharRef | " | " | EnclosedExpr
[103] DirCommentConstructor ::= "<!--" DirCommentContents "-->" /* ws: explicit */
[104] DirCommentContents ::= ((Char - '-') | ('-' (Char - '-')))* /* ws: explicit */
[105] DirPIConstructor ::= "<?" PITarget (S DirPIContents)? "?>" /* ws: explicit */
[106] DirPIContents ::= (Char* - (Char* '?>' Char*)) /* ws: explicit */
[107] CDataSection ::= "<![CDATA[" CDataSectionContents "]]>" /* ws: explicit */
[108] CDataSectionContents ::= (Char* - (Char* ']]>' Char*)) /* ws: explicit */
[109] ComputedConstructor ::= CompDocConstructor
| CompElemConstructor
| CompAttrConstructor
| CompTextConstructor
| CompCommentConstructor
| CompPIConstructor
[110] CompDocConstructor ::= "document" "{" Expr "}"
[111] CompElemConstructor ::= "element" (QName | ("{" Expr "}")) "{" ContentExpr? "}"
[112] ContentExpr ::= Expr
[113] CompAttrConstructor ::= "attribute" (QName | ("{" Expr "}")) "{" Expr? "}"
[114] CompTextConstructor ::= "text" "{" Expr "}"
[115] CompCommentConstructor ::= "comment" "{" Expr "}"
[116] CompPIConstructor ::= "processing-instruction" (NCName | ("{" Expr "}")) "{" Expr? "}"
[117] SingleType ::= AtomicType "?"?
[118] TypeDeclaration ::= "as" SequenceType
[119] SequenceType ::= ("empty-sequence" "(" ")")
| (ItemType OccurrenceIndicator?)
[120] OccurrenceIndicator ::= "?" | "*" | "+" /* xgs: occurrence-indicators
*/
[121] ItemType ::= KindTest | ("item" "(" ")") | AtomicType
[122] AtomicType ::= QName
[123] KindTest ::= DocumentTest
| ElementTest
| AttributeTest
| SchemaElementTest
| SchemaAttributeTest
| PITest
| CommentTest
| TextTest
| AnyKindTest
[124] AnyKindTest ::= "node" "(" ")"
[125] DocumentTest ::= "document-node" "(" (ElementTest | SchemaElementTest)? ")"
[126] TextTest ::= "text" "(" ")"
[127] CommentTest ::= "comment" "(" ")"
[128] PITest ::= "processing-instruction" "(" (NCName | StringLiteral)? ")"
[129] AttributeTest ::= "attribute" "(" (AttribNameOrWildcard ("," TypeName)?)? ")"
[130] AttribNameOrWildcard ::= AttributeName | "*"
[131] SchemaAttributeTest ::= "schema-attribute" "(" AttributeDeclaration ")"
[132] AttributeDeclaration ::= AttributeName
[133] ElementTest ::= "element" "(" (ElementNameOrWildcard ("," TypeName "?"?)?)? ")"
[134] ElementNameOrWildcard ::= ElementName | "*"
[135] SchemaElementTest ::= "schema-element" "(" ElementDeclaration ")"
[136] ElementDeclaration ::= ElementName
[137] AttributeName ::= QName
[138] ElementName ::= QName
[139] TypeName ::= QName
[140] URILiteral ::= StringLiteral
[141] IntegerLiteral ::= Digits
[142] DecimalLiteral ::= ("." Digits) | (Digits "." [0-9]*) /* ws: explicit */
[143] DoubleLiteral ::= (("." Digits) | (Digits ("." [0-9]*)?)) [eE] [+-]? Digits /* ws: explicit */
[144] StringLiteral ::= ('"' (PredefinedEntityRef | CharRef | EscapeQuot | [^"&])* '"') | ("'" (PredefinedEntityRef | CharRef | EscapeApos | [^'&])* /* ws: explicit */
"'")
[145] PredefinedEntityRef ::= "&" ("lt" | "gt" | "amp" | "quot" | "apos") ";" /* ws: explicit */
[146] EscapeQuot ::= '""'
[147] EscapeApos ::= "''"
[148] ElementContentChar ::= Char - [{}<&]
[149] QuotAttrContentChar ::= Char - ["{}<&]
[150] AposAttrContentChar ::= Char - ['{}<&]
[151] Comment ::= "(:" (CommentContents | Comment)* ":)" /* ws: explicit */
/* gn: comments */
[152] PITarget ::= [http://www.w3.org/TR/REC-xml#NT-PITarget]^XML /* xgs: xml-version */
[153] CharRef ::= [http://www.w3.org/TR/REC-xml#NT-CharRef]^XML /* xgs: xml-version */
[154] QName ::= [http://www.w3.org/TR/REC-xml-names/#NT-QName]^Names /* xgs: xml-version */
[155] NCName ::= [http://www.w3.org/TR/REC-xml-names/#NT-NCName]^Names /* xgs: xml-version */
[156] S ::= [http://www.w3.org/TR/REC-xml#NT-S]^XML /* xgs: xml-version */
[157] Char ::= [http://www.w3.org/TR/REC-xml#NT-Char]^XML /* xgs: xml-version */
[158] Digits ::= [0-9]+
[159] CommentContents ::= (Char+ - (Char* ('(:' | ':)') Char*))
XML转换
XSLT
XSLT是一种描述如何对文档转换的XML语言,它基于模板,可用于生成文本、XML、HTML或其它树状格式的结果。XSLT 1.0近似用以下DTD表示(名字空间问题没有处理),其中xsl:stylesheet
为起始:
<!ENTITY % char-instructions "
| xsl:apply-templates
| xsl:call-template
| xsl:apply-imports
| xsl:for-each
| xsl:value-of
| xsl:copy-of
| xsl:number
| xsl:choose
| xsl:if
| xsl:text
| xsl:copy
| xsl:variable
| xsl:message
| xsl:fallback
">
<!ENTITY % instructions "
%char-instructions;
| xsl:processing-instruction
| xsl:comment
| xsl:element
| xsl:attribute
">
<!ENTITY % char-template "
(#PCDATA
%char-instructions;)*
">
<!ENTITY % template "
(#PCDATA
%instructions;
%result-elements;)*
">
<!-- Used for the type of an attribute value that is a URI reference.-->
<!ENTITY % URI "CDATA">
<!-- Used for the type of an attribute value that is a pattern.-->
<!ENTITY % pattern "CDATA">
<!-- Used for the type of an attribute value that is an
attribute value template.-->
<!ENTITY % avt "CDATA">
<!-- Used for the type of an attribute value that is a QName; the prefix
gets expanded by the XSLT processor. -->
<!ENTITY % qname "NMTOKEN">
<!-- Like qname but a whitespace-separated list of QNames. -->
<!ENTITY % qnames "NMTOKENS">
<!-- Used for the type of an attribute value that is an expression.-->
<!ENTITY % expr "CDATA">
<!-- Used for the type of an attribute value that consists
of a single character.-->
<!ENTITY % char "CDATA">
<!-- Used for the type of an attribute value that is a priority. -->
<!ENTITY % priority "NMTOKEN">
<!ENTITY % space-att "xml:space (default|preserve) #IMPLIED">
<!-- This may be overridden to customize the set of elements allowed
at the top-level. -->
<!ENTITY % non-xsl-top-level "">
<!ENTITY % top-level "
(xsl:import*,
(xsl:include
| xsl:strip-space
| xsl:preserve-space
| xsl:output
| xsl:key
| xsl:decimal-format
| xsl:attribute-set
| xsl:variable
| xsl:param
| xsl:template
| xsl:namespace-alias
%non-xsl-top-level;)*)
">
<!ENTITY % top-level-atts '
extension-element-prefixes CDATA #IMPLIED
exclude-result-prefixes CDATA #IMPLIED
id ID #IMPLIED
version NMTOKEN #REQUIRED
xmlns:xsl CDATA #FIXED "http://www.w3.org/1999/XSL/Transform"
%space-att;
'>
<!-- This entity is defined for use in the ATTLIST declaration
for result elements. -->
<!ENTITY % result-element-atts '
xsl:extension-element-prefixes CDATA #IMPLIED
xsl:exclude-result-prefixes CDATA #IMPLIED
xsl:use-attribute-sets %qnames; #IMPLIED
xsl:version NMTOKEN #IMPLIED
'>
<!ELEMENT xsl:stylesheet %top-level;>
<!ATTLIST xsl:stylesheet %top-level-atts;>
<!ELEMENT xsl:transform %top-level;>
<!ATTLIST xsl:transform %top-level-atts;>
<!ELEMENT xsl:import EMPTY>
<!ATTLIST xsl:import href %URI; #REQUIRED>
<!ELEMENT xsl:include EMPTY>
<!ATTLIST xsl:include href %URI; #REQUIRED>
<!ELEMENT xsl:strip-space EMPTY>
<!ATTLIST xsl:strip-space elements CDATA #REQUIRED>
<!ELEMENT xsl:preserve-space EMPTY>
<!ATTLIST xsl:preserve-space elements CDATA #REQUIRED>
<!ELEMENT xsl:output EMPTY>
<!ATTLIST xsl:output
method %qname; #IMPLIED
version NMTOKEN #IMPLIED
encoding CDATA #IMPLIED
omit-xml-declaration (yes|no) #IMPLIED
standalone (yes|no) #IMPLIED
doctype-public CDATA #IMPLIED
doctype-system CDATA #IMPLIED
cdata-section-elements %qnames; #IMPLIED
indent (yes|no) #IMPLIED
media-type CDATA #IMPLIED
>
<!ELEMENT xsl:key EMPTY>
<!ATTLIST xsl:key
name %qname; #REQUIRED
match %pattern; #REQUIRED
use %expr; #REQUIRED
>
<!ELEMENT xsl:decimal-format EMPTY>
<!ATTLIST xsl:decimal-format
name %qname; #IMPLIED
decimal-separator %char; "."
grouping-separator %char; ","
infinity CDATA "Infinity"
minus-sign %char; "-"
NaN CDATA "NaN"
percent %char; "%"
per-mille %char; "‰"
zero-digit %char; "0"
digit %char; "#"
pattern-separator %char; ";"
>
<!ELEMENT xsl:namespace-alias EMPTY>
<!ATTLIST xsl:namespace-alias
stylesheet-prefix CDATA #REQUIRED
result-prefix CDATA #REQUIRED
>
<!ELEMENT xsl:template
(#PCDATA
%instructions;
%result-elements;
| xsl:param)*
>
<!ATTLIST xsl:template
match %pattern; #IMPLIED
name %qname; #IMPLIED
priority %priority; #IMPLIED
mode %qname; #IMPLIED
%space-att;
>
<!ELEMENT xsl:value-of EMPTY>
<!ATTLIST xsl:value-of
select %expr; #REQUIRED
disable-output-escaping (yes|no) "no"
>
<!ELEMENT xsl:copy-of EMPTY>
<!ATTLIST xsl:copy-of select %expr; #REQUIRED>
<!ELEMENT xsl:number EMPTY>
<!ATTLIST xsl:number
level (single|multiple|any) "single"
count %pattern; #IMPLIED
from %pattern; #IMPLIED
value %expr; #IMPLIED
format %avt; '1'
lang %avt; #IMPLIED
letter-value %avt; #IMPLIED
grouping-separator %avt; #IMPLIED
grouping-size %avt; #IMPLIED
>
<!ELEMENT xsl:apply-templates (xsl:sort|xsl:with-param)*>
<!ATTLIST xsl:apply-templates
select %expr; "node()"
mode %qname; #IMPLIED
>
<!ELEMENT xsl:apply-imports EMPTY>
<!-- xsl:sort cannot occur after any other elements or
any non-whitespace character -->
<!ELEMENT xsl:for-each
(#PCDATA
%instructions;
%result-elements;
| xsl:sort)*
>
<!ATTLIST xsl:for-each
select %expr; #REQUIRED
%space-att;
>
<!ELEMENT xsl:sort EMPTY>
<!ATTLIST xsl:sort
select %expr; "."
lang %avt; #IMPLIED
data-type %avt; "text"
order %avt; "ascending"
case-order %avt; #IMPLIED
>
<!ELEMENT xsl:if %template;>
<!ATTLIST xsl:if
test %expr; #REQUIRED
%space-att;
>
<!ELEMENT xsl:choose (xsl:when+, xsl:otherwise?)>
<!ATTLIST xsl:choose %space-att;>
<!ELEMENT xsl:when %template;>
<!ATTLIST xsl:when
test %expr; #REQUIRED
%space-att;
>
<!ELEMENT xsl:otherwise %template;>
<!ATTLIST xsl:otherwise %space-att;>
<!ELEMENT xsl:attribute-set (xsl:attribute)*>
<!ATTLIST xsl:attribute-set
name %qname; #REQUIRED
use-attribute-sets %qnames; #IMPLIED
>
<!ELEMENT xsl:call-template (xsl:with-param)*>
<!ATTLIST xsl:call-template
name %qname; #REQUIRED
>
<!ELEMENT xsl:with-param %template;>
<!ATTLIST xsl:with-param
name %qname; #REQUIRED
select %expr; #IMPLIED
>
<!ELEMENT xsl:variable %template;>
<!ATTLIST xsl:variable
name %qname; #REQUIRED
select %expr; #IMPLIED
>
<!ELEMENT xsl:param %template;>
<!ATTLIST xsl:param
name %qname; #REQUIRED
select %expr; #IMPLIED
>
<!ELEMENT xsl:text (#PCDATA)>
<!ATTLIST xsl:text
disable-output-escaping (yes|no) "no"
>
<!ELEMENT xsl:processing-instruction %char-template;>
<!ATTLIST xsl:processing-instruction
name %avt; #REQUIRED
%space-att;
>
<!ELEMENT xsl:element %template;>
<!ATTLIST xsl:element
name %avt; #REQUIRED
namespace %avt; #IMPLIED
use-attribute-sets %qnames; #IMPLIED
%space-att;
>
<!ELEMENT xsl:attribute %char-template;>
<!ATTLIST xsl:attribute
name %avt; #REQUIRED
namespace %avt; #IMPLIED
%space-att;
>
<!ELEMENT xsl:comment %char-template;>
<!ATTLIST xsl:comment %space-att;>
<!ELEMENT xsl:copy %template;>
<!ATTLIST xsl:copy
%space-att;
use-attribute-sets %qnames; #IMPLIED
>
<!ELEMENT xsl:message %template;>
<!ATTLIST xsl:message
%space-att;
terminate (yes|no) "no"
>
<!ELEMENT xsl:fallback %template;>
<!ATTLIST xsl:fallback %space-att;>
XSL-FO
XSL格式化对象是一种用于描述页面布局和格式的XML语言,可协助把XML文档排版为HTML或PDF等格式。参考http://www.w3.org/standards/techs/xsl
XPath
XPath是用于指定XML文档的一部分的小语言,用于XSLT与XPointer等。以下只介绍简单的XPath 1.0:
XPath把XML文档视为树(其中引用已经替换、属性值也已经正规化),其中的结点分为:
类型 | 说明 | 字符串值 | 长名 |
---|---|---|---|
根 | 树根,其孩子有文档元素、处理指令和注释 | 其字符串值由所有后代文本结点的字符串值连接而成 | 无 |
元素 | 对应于文档中的元素,其孩子有元素、注释、处理指令和文本 | 其字符串值由所有后代文本结点的字符串值连接而成 | 展开元素的QName而得 |
属性 | 对应于元素中非名字空间声明的属性(但不是父元素的孩子),包括默认属性 | 属性的正规化值 | 展开元素的QName而得 |
文本 | 由字符和/或CDATA节构成,不会有两个相邻的文本结点 | 字符数据,到少有一个字符 | 无 |
名字空间 | 对应父元素的所有生效的每个名字空间声明(但不是父元素的孩子) | 名字空间的IRI(已解析) | 局部名为前缀而名字空间为空 |
处理指令 | 对应文档中不在DTD的每个处理指令 | 从目标后首个非空白到?> (不含) |
局部名为目标而名字空间为空 |
注释 | 对应文档中不在DTD的的注释 | 注释内容 | 无 |
元素可能有惟一ID,即在DTD中声明为类型ID的属性,如果两个元素指定相同ID,后一视为没有惟一ID。
XML用表达式语法,一个表达式在每种上下文可以有不同值,值类型为以下之一:
- 结点集合(无序、无重复)
- 布尔值
- 数值(浮点数)
- 字符串(UCS字符的序列) 上下文(由XSLT之类使用XPath的规范决定)包括:
- 结点(称为上下文结点)
- 一对正整数(上下文位置和上下文大小,后者不小于前者)
- 变量绑定集合
- 函数库
- 表达式处生效的名字空间声明集合
词法
各词为符合ExprToken
的最长序列,各首末和各词之间可以放置ExprWhitespace
。
[28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::'
| NameTest
| NodeType
| Operator
| FunctionName
| AxisName
| Literal
| Number
| VariableReference
[29] Literal ::= '"' [^"]* '"'
| "'" [^']* "'"
[30] Number ::= Digits ('.' Digits?)?
| '.' Digits
[31] Digits ::= [0-9]+
[32] Operator ::= OperatorName
| MultiplyOperator
| '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>='
[33] OperatorName ::= 'and' | 'or' | 'mod' | 'div'
[34] MultiplyOperator ::= '*'
[35] FunctionName ::= QName - NodeType
[36] VariableReference ::= '$' QName
[37] NameTest ::= '*' /* 对有主类型的结点为真 */
| NCName ':' '*' /* 对主类型有指定名字的结点为真 */
| QName /* 对主类型在指定名字空间的结点为真 */
[38] NodeType ::= 'comment' /* 对注释结点都是真 */
| 'text' /* 对文本结点都是真 */
| 'processing-instruction' /* 对处理指令结点都是真 */
| 'node' /* 对所有结点都是真 */
[39] ExprWhitespace ::= S
以下是消歧义规则:
- 若前有单词且它不是
@
、::
、(
、[
、,
或Operator
,则*
视为MultiplyOperator
而NCName
视为OperatorName
- 若
NCName
后面的字符(中间容许ExprWhitespace
)为(
,则视为NodeType
或FunctionName
- 若
NCName
后面的两个字符(中间容许ExprWhitespace
)为::
,则视为AxisName
- 否则,单词不能视为
MultiplyOperator
、OperatorName
、NodeType
、FunctionName
或AxisName
语法和语义
XPath语法如:
[14] Expr ::= OrExpr /* 值为OrExpr的值 */
[15] PrimaryExpr ::= VariableReference /* 值为变量名绑定的值,未绑定是错误 */
| '(' Expr ')' /* 值为Expr的值 */
| Literal /* 值为字符串Literal */
| Number /* 值为数值Number */
| FunctionCall /* 值为FunctionCall的值 */
[16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument )* )? ')' /* 值为以各Argument的值转换到指定类型作为参数调用FunctionName绑定的函数的返回值 */
[17] Argument ::= Expr /* 值为Expr的值 */
[18] UnionExpr ::= PathExpr /* 值为PathExpr的值 */
| UnionExpr '|' PathExpr /* 值为并 */
[19] PathExpr ::= LocationPath /* 值为LocationExpr选取的结点集 */
| FilterExpr /* 值为FilterExpr的值 */
| FilterExpr '/' RelativeLocationPath
| FilterExpr '//' RelativeLocationPath /* `//` 相当于 `/descendant-or-self::node()/` */
[20] FilterExpr ::= PrimaryExpr /* 值为PrimaryExpr的值 */
| FilterExpr Predicate /* 值为FilterExpr的值由关于孩子轴满足Predicate的组成的子集 */
[21] OrExpr ::= AndExpr /* 值为AndExpr的值 */
| OrExpr 'or' AndExpr /* 值为或(短路) */
[22] AndExpr ::= EqualityExpr /* 值为EqualityExpr的值 */
| AndExpr 'and' EqualityExpr /* 值为与(短路) */
[23] EqualityExpr ::= RelationalExpr /* 值为RelationalExpr的值 */
| EqualityExpr '=' RelationalExpr /* 值为是否相等 */
| EqualityExpr '!=' RelationalExpr /* 值为是否不相等 */
[24] RelationalExpr ::= AdditiveExpr /* 值为AdditionExpr的值 */
| RelationalExpr '<' AdditiveExpr /* 值为是否小于 */
| RelationalExpr '>' AdditiveExpr /* 值为是否大于 */
| RelationalExpr '<=' AdditiveExpr /* 值为是否不大于 */
| RelationalExpr '>=' AdditiveExpr /* 值为是否不小于 */
[25] AdditiveExpr ::= MultiplicativeExpr /* 值为MultiplicativeExpr的值 */
| AdditiveExpr '+' MultiplicativeExpr /* 值为和 */
| AdditiveExpr '-' MultiplicativeExpr /* 值为差 */
[26] MultiplicativeExpr ::= UnaryExpr /* 值为UnionExpr的值 */
| MultiplicativeExpr MultiplyOperator UnaryExpr /* 值为积 */
| MultiplicativeExpr 'div' UnaryExpr /* 值为商 */
| MultiplicativeExpr 'mod' UnaryExpr /* 值为截断除法的余数 */
[27] UnaryExpr ::= UnionExpr /* 值为UnionExpr的值 */
| '-' UnaryExpr /* 值为UnionExpr的相反数 */
- 若比较运算的两个操作数都是结点集,则结果为真当且仅当它们分别存在结点的字符串值使这比较为真
- 若比较运算的两个操作数分别是结点集和数值,则结果为真当且仅当存在其中结点的字符串值转换为数值后使这比较为真
- 若比较运算的两个操作数分别是结点集和字符串,则结果为真当且仅当存在其中结点的字符串值使这比较为真
- 若比较运算的两个操作数分别是结点集和布尔值,则结果为真当且仅当结点集转换为布尔值后使这比较为真
若=
或!=
的操作数都不是结点集:
- 若其中一个为布尔值,则另一个也转换为布尔值,它们相等当且仅当它们都真或都假
- 否则,若其中一个为数值,则另一个也转换为数值,它们相等当且仅当它们按IEEE 754相等
- 否则,两个都转换为字符串,相等当且仅当它们有相同的UCS字符序列
若<=
、<
、>=
或>
的操作数都不是结点集,则两者都转换为数值,然后按IEEE 754比较
值得注意的是,$x="foo"
不等价于 does not mean the same as not($x!="foo")
:前者真当且仅当结点集$x
有结点的字符串值为foo
,后者真当且仅当结点集$x
所有结点的字符串值为foo
选取结点集
- 相对位置路径由一个或多个由
/
分隔的步骤组成,从左到右每步中以上一步结点集中每个结点作为上下文结点选取一个结点集,取并作为结点集。如child::div/child::para
选取父亲为div
的para
所有孙结点。 - 绝对位置路径由
/
开始,/
选取包含上下文结点的文档的根结点,后面如有相对位置路径,则以根结点为初始上下文结点按上段规则选取。
其中,每个步骤由以下部分组成
- 轴,指定要选取结点与上下文结点间的关系
- 结点测试,指定要选取结点的类型或全名
- 零个或多个谓词(用
[
与]
包围),指定要选取结点要满足的XPath表达式
[1] LocationPath ::= RelativeLocationPath
| AbsoluteLocationPath
[2] AbsoluteLocationPath ::= '/' RelativeLocationPath?
| AbbreviatedAbsoluteLocationPath
[3] RelativeLocationPath ::= Step
| RelativeLocationPath '/' Step
| AbbreviatedRelativeLocationPath
[4] Step ::= AxisSpecifier NodeTest Predicate*
| AbbreviatedStep
[5] AxisSpecifier ::= AxisName '::'
| AbbreviatedAxisSpecifier
[6] AxisName ::= 'ancestor' /*由上下文结点的祖先组成*/
| 'ancestor-or-self' /*由上下文结点及其祖先组成*/
| 'attribute' /*由上下文结点的属性组成*/
| 'child' /*由上下文结点的孩子组成*/
| 'descendant' /*由上下文结点的后代组成*/
| 'descendant-or-self' /*由上下文结点及其后代组成*/
| 'following' /*由上下文结点的较早兄弟结点组成*/
| 'following-sibling' /*由上下文结点的下个兄弟结点(如有一个)组成*/
| 'namespace' /*由上下文结点的名字空间结点组成*/
| 'parent' /*由上下文结点的双亲结点(如有一个)组成*/
| 'preceding' /*由上下文结点的较晚兄弟结点组成*/
| 'preceding-sibling' /*由上下文结点的上个兄弟结点(如有一个)组成*/
| 'self' /*由上下文结点组成*/
[7] NodeTest ::= NameTest
| NodeType '(' ')'
| 'processing-instruction' '(' Literal ')'
[8] Predicate ::= '[' PredicateExpr ']'
[9] PredicateExpr ::= Expr /*表达保留结点条件的表达式,保留当且仅当其值为等于结点在轴的位置的数值或转换为布尔值真*/
[10] AbbreviatedAbsoluteLocationPath ::= '//' RelativeLocationPath /* `//` 相当于 `/descendant-or-self::node()/` */
[11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step /* `//` 相当于 `/descendant-or-self::node()/` */
[12] AbbreviatedStep ::= '.' /*`self::node()`的缩写*/
| '..' /*`parent::node()`的缩写*/
[13] AbbreviatedAxisSpecifier ::= '@'? /*`@`是`attribute::`的缩写,忽略则表示`child::`*/
核心库
选取函数 | 效果 |
---|---|
number last() | 返回上下文大小 |
number position() | 返回上下文位置 |
number count(node-set) | 返回参数中结点数 |
node-set id(object) | 若参数为结点集,则返回用各字符串值作ID分别选取到时结点集之并;否则,先转换为字符串,视为由空白分隔的ID列表,c返回对应的结点集 |
string local-name(node-set?) | 返回参数(默认为上下文结点)按文档顺序的首个结点的全名的局部名 |
string namespace-uri(node-set?) | 返回参数(默认为上下文结点)按文档顺序的首个结点的全名的名字空间IRI |
string name(node-set?) | 返回参数(默认为上下文结点)按文档顺序的首个结点的全名的QName表示 |
字符串函数|效果 :—|:— string string(object?) | 若参数为结点集,返回首个结点的字符串值;若参数为数值,返回其十进制表示;若参数为布尔值,返回true或false字符串 string concat(string, string, string*) |返回各参数的连接结果 boolean starts-with(string, string) |返回首参数是否开始于次参数 boolean contains(string, string) |返回首参数是否包含次参数 string substring-before(string, string) |返回首参数在次参数首次出现前的子字符串(不出现则空) string substring-after(string, string) |返回首参数在次参数首次出现后的子字符串(不出现则空) string substring(string, number, number?) |返回首参数从第次参数个字符开始的末参数个字符组成的的子字符串 number string-length(string?) |返回参数(默认为上下文结点转换为字符串)的字符数 string normalize-space(string?) |返回把参数中首尾空白去除并把中间空白归一得到的字符串 string translate(string, string, string) |返回把首参数中于次参数中出现的字符替换为末参数中同位置字符(没有则删除)得到的字符串
布尔函数 | 效果 |
---|---|
boolean boolean(object) | 若参数类型数值,返回它不是正负零或NaN;若参数类型为结点集或字符串,返回它是否非空 |
boolean not(boolean) | 返回boolean的非 |
boolean true() | 返回真 |
boolean false() | 返回假 |
boolean lang(string) | 返回上下文结点或最近祖先的xml:lang 属性是否为参数指定语言或其子语言 |
数值函数 | 效果 |
---|---|
number number(object?) | 若参数为字符串,返回它表示的数值或NaN;若参数为布尔值,真返回1,否则0;若参数为结点集,先转换为字符串再转换为数值。参数默认为上下文结点。 |
number sum(node-set) | 返回各结点的字符串值对应数值之和 |
number floor(number) | 返回不大于参数的最大参数 |
number ceiling(number) | 返回不小于参数的最小参数 |
number round(number) | 返回与参数最接近的整数 |
其中,文档顺序指其XML表示的首个字符的出现顺序(但一个元素的名字空间声明先于属性),故根结点最先,父先于子。注意,不同结点不共享孩子。
其它XML技术
- EXI标准定义了XML文档的一种高度紧凑的编码方案,并容许快速和低内存占用的实现,以便用于资源受限的设备
- XML签名定义了数字签名的语法和处理规则,以便保证完整性
- XML加密规范指定了加密数据(标签、标签内容或其它)的XML表示
- XKMS标准指定了分发和注册公钥的协议
- XML Base重写默认URI
- 为XML文档关联样式表作为XSLT变换,供浏览器于格式化时用Stylesheets in XML
- XLink用于表示超文本
- xml:id用于指定一个元素或属性有在文档范围内惟一的标识符
- XInclude用于导入其它文本或XML文档的一部分,或者当前XML文档的重复部分
- XPointer用于指定指向XML文档的各种方法
- XForms用于表示表单
- XML事件规范指定基于DOM的系统如浏览器的控制器
- XML碎片
- XProc用于描述一组文档的处理顺序
应用
- 各类软件的配置信息
- 客户端与服务器端(又或前后台)间的通信,如XMLRPC和Web Services
- 办公文档,如OpenDocument(LibreOffice和OpenOffice等的首选格式)、OOXML(Microsoft office的首选格式)
- 向量图片,如SVG
现在各大程序设计语言和数据库系统都有对XML的支持。