1.DTD简介
xml文件分为两种类型,一种是形式良好的,即well-formed,另一种是合法有效的,即valid。
XML文件遵循所谓“形式良好”要求的种种语法规则,这只是“万里长征走了第一步”。一个完全意义上的XML文件不仅应该是“形式良好的”,而且还应该是使用了这些自定义标记的“有效”的XML文件。
一个XML文件必须遵守文件类型描述DTD(DocumentType Definition)中定义的种种规定。DTD实际上是“元标记”这个概念的产物,它描述了一个置标语言的语法和词汇表,也就是定义了文件的整体结构以及文件的语法。简而言之,DTD规定了一个语法分析器为了解释一个“有效的”XML文件所需要知道的所有规则的细节。
文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。
DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
1.1. 内部的 DOCTYPE 声明
假如 DTD 被包含在您的 XML 源文件中,它应当通过下面的语法包装在一个 DOCTYPE 声明中:
<!DOCTYPE 根元素 [元素声明]> |
带有 DTD 的 XML 文档实例(可以用浏览器打开查看源码)
学生名册.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE 学生名册[ <!ELEMENT 学生名册 (学生+)> <!ELEMENT 学生 (姓名,性别,年龄)> <!ATTLIST 学生 学号 ID #required> <!ELEMENT 姓名 (#PCDATA)> <!ELEMENT 性别 (#PCDATA)> <!ELEMENT 年龄 (#PCDATA)> ]> <学生名册> <学生 学号="a001"> <姓名>张三</姓名> <性别>男</性别> <年龄>27</年龄> </学生> <学生 学号="a002"> <姓名>李四</姓名> <性别>男</性别> <年龄>27</年龄> </学生> <学生 学号="a003"> <姓名>王五</姓名> <性别>男</性别> <年龄>27</年龄> </学生> </学生名册> |
解释:
<!DOCTYPE 学生名册[ à指定根元素为学生名册
<!ELEMENT学生名册 (学生+)> à指定根元素下有一个或多个学生元
<!ELEMENT学生 (姓名,年龄)> à
<!ATTLIST学生 学号 ID #required> à指定学生的属性学号,数据类型为ID,必须
<!ELEMENT姓名 (#PCDATA)> à指定姓名元素下的内容为普通字符串类型
<!ELEMENT性别 (#PCDATA)>
<!ELEMENT年龄 (#PCDATA)>
]>
1.2. 外部文档声明
假如 DTD 位于 XML 源文件的外部,那么它应通过下面的语法被封装在一个 DOCTYPE 定义中:
<!DOCTYPE 根元素 SYSTEM "文件名"> |
联系人.dtd
<?xml version="1.0" encoding="GB2312"?> <!ELEMENT 联系人列表 (联系人)> <!ELEMENT 联系人 (姓名,ID,公司,EMAIL,电话,地址)> <!ELEMENT 地址 (街道,城市,省份)> <!ELEMENT 姓名 (#PCDATA)> <!ELEMENT ID (#PCDATA)> <!ELEMENT 公司 (#PCDATA)> <!ELEMENT EMAIL (#PCDATA)> <!ELEMENT 电话 (#PCDATA)> <!ELEMENT 街道 (#PCDATA)> <!ELEMENT 城市 (#PCDATA)> <!ELEMENT 省份 (#PCDATA)> |
联系人.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE 联系人列表 SYSTEM "联系人列表.dtd"> <联系人列表> <联系人> <姓名>张三</姓名> <ID>001</ID> <公司>微软</公司> <EMAIL>Morris131@163.com</EMAIL> <电话>15873001206</电话> <地址> <街道>芙蓉街</街道> <城市>长沙</城市> <省份>湖南</省份> </地址> </联系人> </联系人列表> |
解释:
<!DOCTYPE 联系人列表 SYSTEM "联系人列表.dtd">将外部dtd文件引入。
1.3. 为什么使用 DTD?
1.通过 DTD,您的每一个 XML 文件均可携带一个有关其自身格式的描述。
2.通过 DTD,独立的团体可一致地使用某个标准的 DTD 来交换数据。
3.使用某个标准的 DTD 来验证从外部接收到的数据。
4.使用 DTD 来验证您自身的数据。
2.XML 构建模块
所有的 XML 文档(以及 HTML 文档)均由以下简单的构建模块构成:
l 元素
l 属性
l 实体
l PCDATA
l CDATA
下面是每个构建模块的简要描述。
2.1. 元素
元素是 XML 以及 HTML 文档的主要构建模块。
HTML 元素的例子是"body" 和 "table"。XML 元素的例子是 "note" 和 "message" 。元素可包含文本、其他元素或者是空的。空的 HTML 元素的例子是 "hr"、"br" 以及 "img"。
实例
<body>body text in between</body> <message>some message in between</message> |
2.1.1.声明一个元素
在 DTD 中,XML 元素通过元素声明来进行声明。元素声明使用下面的语法:
<!ELEMENT 元素名称 类别>
或者
2.1.2.空元素
空元素通过类别关键词EMPTY进行声明:
<!ELEMENT 元素名称 EMPTY>
例子:
<!ELEMENT br EMPTY>
XML例子:
<br />
2.1.3.只有 PCDATA 的元素
只有 PCDATA 的元素通过圆括号中的 #PCDATA 进行声明:
<!ELEMENT 元素名称 (#PCDATA)>
例子:
<!ELEMENT from (#PCDATA)>
2.1.4.带有任何内容的元素
通过类别关键词 ANY 声明的元素,可包含任何可解析数据的组合:
<!ELEMENT 元素名称 ANY>
例子:
<!ELEMENT note ANY>
2.1.5.带有子元素(序列)的元素
带有一个或多个子元素的元素通过圆括号中的子元素名进行声明:
或者
<!ELEMENT 元素名称 (子元素名称 1,子元素名称2,.....)>
例子:
<!ELEMENT note(to,from,heading,body)>
当子元素按照由逗号分隔开的序列进行声明时,这些子元素必须按照相同的顺序出现在文档中。在一个完整的声明中,子元素也必须被声明,同时子元素也可拥有子元素。"note" 元素的完整声明是:
<!ELEMENT note(to,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
2.1.6.声明只出现一次的元素
例子:
<!ELEMENT note (message)>
上面的例子声明了:message 子元素必须出现一次,并且必须只在 "note" 元素中出现一次。
2.1.7.声明最少出现一次的元素
例子:
<!ELEMENT note (message+)>
上面的例子中的加号声明了:message 子元素必须在 "note" 元素内出现至少一次。
2.1.8.声明出现零次或多次的元素
例子:
<!ELEMENT note (message*)>
上面的例子中的星号声明了:子元素 message 可在 "note" 元素内出现零次或多次。
2.1.9.声明出现零次或一次的元素
例子:
<!ELEMENT note (message?)>
上面的例子中的问号声明了:子元素 message 可在 "note" 元素内出现零次或一次。
2.1.10.声明“非.../既...”类型的内容
例子:
<!ELEMENT note(to,header,(message|body))>
上面的例子声明了:"note" 元素必须包含 "to" 元素、"from" 元素、"header" 元素,以及非 "message" 元素既 "body" 元素。
声明混合型的内容
例子:
<!ELEMENT note(#PCDATA|to|from|header|message)*>
上面的例子声明了:"note" 元素可包含出现零次或多次的 PCDATA、"to"、"from"、"header" 或者 "message"。
<TBODY>元 字符 |
含 义 |
+ |
出现一次或多次 |
* |
出现零次或多次 |
? |
可选,不出现或出现一次 |
() |
一组要共同匹配的表达式 |
| |
OR,或 |
, |
AND,要求严格遵从顺序要求 |
元素A |
元素列表,无须遵从顺序要求</TBODY> |
2.2. 属性
属性可提供有关元素的额外信息。
属性总是被置于某元素的开始标签中。属性总是以名称/值的形式成对出现的。下面的 "img" 元素拥有关于源文件的额外信息:
<img src="computer.gif" /> |
<img src="computer.gif" />元素的名称是"img"。属性的名称是 "src"。属性的值是 "computer.gif"。由于元素本身为空,它被一个 "/" 关闭。
在DTD 中,属性通过ATTLIST 声明来进行声明。
2.2.1.声明属性
属性声明拥使用下列语法:
DTD 实例:
<!ATTLIST payment type CDATA"check">
XML 实例:
<payment type="check" />
以下是属性类型的选项:
类型 |
描述 |
CDATA |
值为字符数据 (character data) |
(en1|en2|..) |
此值是枚举列表中的一个值 |
ID |
值为唯一的 id |
IDREF |
值为另外一个元素的 id |
IDREFS |
值为其他 id 的列表 |
NMTOKEN |
值为合法的 XML 名称 |
NMTOKENS |
值为合法的 XML 名称的列表 |
ENTITY |
值是一个实体 |
ENTITIES |
值是一个实体列表 |
NOTATION |
此值是符号的名称 |
xml: |
值是一个预定义的 XML 值 |
默认值参数可使用下列值:
值 |
解释 |
值 |
属性的默认值 |
属性值是必需的 |
|
#IMPLIED |
属性不是必需的 |
#FIXED value |
属性值是固定的 |
2.2.2.规定一个默认的属性值
DTD:
<!ELEMENT square EMPTY>
<!ATTLIST square width CDATA"0">
合法的 XML:
<square width="100" />
在上面的例子中,"square" 被定义为带有 CDATA 类型的 "width" 属性的空元素。如果宽度没有被设定,其默认值为0 。
2.2.3.#IMPLIED
语法
<!ATTLIST 元素名称 属性名称 属性类型 #IMPLIED>
例子
DTD:
<!ATTLIST contact fax CDATA #IMPLIED>
合法的 XML:
<contact fax="555-667788"/>
合法的 XML:
<contact />
假如您不希望强制作者包含属性,并且您没有默认值选项的话,请使用关键词 #IMPLIED。
2.2.4.#required
语法
<!ATTLIST 元素名称 属性名称 属性类型 #required>
例子
DTD:
<!ATTLIST person number CDATA#required>
合法的 XML:
<person number="5677" />
非法的 XML:
<person />
假如您没有默认值选项,但是仍然希望强制作者提交属性的话,请使用关键词 #required。
2.2.5.#FIXED
语法
<!ATTLIST 元素名称 属性名称 属性类型 #FIXED"value">
例子
DTD:
<!ATTLIST sender company CDATA #FIXED"Microsoft">
合法的 XML:
<sender company="Microsoft"/>
非法的 XML:
<sender company="W3School"/>
如果您希望属性拥有固定的值,并不允许作者改变这个值,请使用 #FIXED 关键词。如果作者使用了不同的值,XML 解析器会返回错误。
2.2.6.列举属性值
语法:
<!ATTLIST 元素名称 属性名称 (en1|en2|..) 默认值>
DTD 例子:
<!ATTLIST payment type (check|cash)"cash">
XML 例子:
<payment type="check" />
或者
<payment type="cash" />
如果您希望属性值为一系列固定的合法值之一,请使用列举属性值。
2.3. 实体
实体是用于定义用于定义引用普通文本或特殊字符的快捷方式的变量。
实体引用是对实体的引用。
实体可在内部或外部进行声明。
2.3.1.一个内部实体声明
实体是用来定义普通文本的变量。实体引用是对实体的引用。
大多数同学都了解这个 HTML 实体引用:" "。这个“无折行空格”实体在 HTML 中被用于在某个文档中插入一个额外的空格。
当文档被 XML 解析器解析时,实体就会被展开。
下面的实体在 XML 中被预定义:
实体引用 |
字符 |
< |
< |
> |
> |
& |
& |
" |
" |
' |
' |
语法:
<!ENTITY 实体名称 "实体的值">
例子:
DTD 例子:
<!ENTITY writer "BillGates">
<!ENTITY copyright "CopyrightW3School.com.cn">
XML 例子:
<author>&writer;©right;</author>
注释: 一个实体由三部分构成: 一个和号 (&),一个实体名称,以及一个分号 (;)。
2.3.2.一个外部实体声明
语法:
<!ENTITY 实体名称 SYSTEM"URI/URL">
例子:
DTD 例子:
<!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
<!ENTITY copyright SYSTEM"http://www.w3school.com.cn/dtd/entities.dtd">
XML 例子:
<author>&writer;©right;</author>
2.4. PCDATA
PCDATA 的意思是被解析的字符数据(parsedcharacter data)。
可把字符数据想象为 XML 元素的开始标签与结束标签之间的文本。
PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。
不过,被解析的字符数据不应当包含任何 &、< 或者 > 字符;需要使用 &、< 以及 > 实体来分别替换它们。
2.5. CDATA
CDATA 的意思是字符数据(characterdata)。
CDATA 是不会被解析器解析的文本。在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开。
3.实例
3.1. 动物园实例
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!DOCTYPE 动物园 [ <!ELEMENT 动物园 (爬行类,两栖类,鸟类,哺乳类,鱼类)> <!ELEMENT 爬行类 (动物+)> <!ELEMENT 两栖类 (动物+)> <!ELEMENT 鸟类 (动物+)> <!ELEMENT 哺乳类 (动物+)> <!ELEMENT 鱼类 (动物+)> <!ELEMENT 动物 (#PCDATA)> <!ATTLIST 动物 > ]> <动物园> <爬行类> <动物 数量="2">螃蟹</动物> </爬行类> <两栖类> <动物 数量="10">青蛙</动物> </两栖类> <鸟类> <动物 数量="2">乌鸦</动物> <动物 数量="10">鸽子</动物> </鸟类> <哺乳类> <动物 数量="3">绵羊</动物> </哺乳类> <鱼类> <动物 数量="12">鲫鱼</动物> </鱼类> </动物园> |
3.2. 出版社实例
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE 出版社[ <!ENTITY LH "李红"> <!ENTITY ZHL "张宏良"> <!ELEMENT 出版社 (图书+)> <!ELEMENT 图书 (作者+,图片*,内容+,新章节*)> <!ATTLIST 图书 图书号 ID #required> <!ELEMENT 作者 (#PCDATA)> <!ELEMENT 图片 (#PCDATA)> <!ELEMENT 内容 (章节,描述)> <!ELEMENT 章节 (#PCDATA)> <!ATTLIST 章节 数目 CDATA #required> <!ELEMENT 描述 (目录,简介)> <!ELEMENT 目录 (#PCDATA)> <!ELEMENT 简介 (#PCDATA)> <!ELEMENT 新章节 (章节,描述)> <!ATTLIST 新章节 添加 (是|不是) "是"> ]> <出版社> <图书 图书号="a01"> <作者>&LH;&ZHL;</作者> <内容> <章节 数目="20"></章节> <描述> <目录></目录> <简介></简介> </描述> </内容> <新章节 添加="是"> <章节 数目="1"></章节> <描述> <目录></目录> <简介></简介> </描述> </新章节> </图书> </出版社> |