XML教程——DTD
?
这样,我们就定义了一个文件,它以DOCTYPE中规定的根元素名作为其根元素的名字。
如果为每一个XML文件加入一段Dtd定义,是相当繁琐的。而且,更多的情况下,我们会为一批XML文件定义一个相同的Dtd。例如,对于报社中的每篇稿件,它们都有相同的格式,可以采用一个统一的Dtd,为每一篇单独定义既麻烦,又不利于统一格式。好在XML规范为我们提供了解决这个问题的方法,它就是外部Dtd。
?
在DOCTYPE声明中,应该加入SYSTEM属性:<!DOCTYPE 根元素名 SYSTEM "外部Dtd文件的URL">
例如:
请见下面例子:
?
这个Dtd标识的命名规则和XML文件的命名规则稍有不同。具体地说,Dtd名称只能包含字母、数字、空格和下面的符号:_%$#@()+:=/!*;?。同时,Dtd名称还必须符合一些标准的规定。例如,ISO标准的Dtd以“ISO”三个字母开头;被改进的非ISO 标准的Dtd以加号“+”开头;未被改进的非ISO标准的Dtd以减号“-”开头。
无论是哪一种情况,开始部分后面都跟着两个斜杠“//”及Dtd所有者的名称。在这个名称之后又是两个斜杠“//”,再然后是Dtd所描述的文件的类型。最后,在又一对斜杠之后是语言的种类(参见ISO 639)。例如下面这个公用Dtd的引用:
?
看上去的确比较复杂,不过没关系,对于Dtd的命名通常不是它的引用者的任务,XML 文件的编写者只要在自己的文件中把事先定义好的Dtd名称放在相应的位置中就可以了。
?
这个Dtd定义了一个XML文件,它只有一个根元素,名为“联系人列表”,这个元素可以有任何类型的子元素,也可以是纯文本,还可以为空。
但是需要注意,尽管元素“联系人列表”被定义为“可以”包含其它元素,但实际上这个 Dtd除了“联系人列表”元素本身外没有定义任何其它元素,所以也就没有其它元素可以用作“联系人列表”的子元素。“有效的”XML文件规定文件中所使用的任何元素都必须在Dtd中给出定义。
在“ANY”定义下使用任何纯文本都是无须另加说明的,这一点与元素不同。故而,在相同的Dtd定义下,下面一段XML文件则是合法的:
?
?
现在我们已经定义了一个XML文件,它的根元素名为“联系人列表”。“联系人列表” 中可以包含任何纯文本数据,也可以含有子元素(这即是ANY的含义)。根据后面的定义,我们知道,“联系人列表”中可以包含子元素“联系人”,也可以直接包含子元素“姓名”;“联系人”元素又可以包含自己的子元素,名为“姓名”;而“姓名”则只能包含纯文本数据(即(#PCDATA))。
注意:
?
准确的说法是,元素“联系人”必须包含一个,且只能包含一个子元素“姓名”。可如果子元素是“EMAIL地址”怎么办?联系人可能根本没有自己的EMAIL邮箱,也可能有好几个EMAIL帐号。
使用正则表达式,我们就可以解决上述问题,描述父元素与子元素之间非常复杂的关系。例如,你可以对一个元素作如下任何一种类型的定义:它有一个子元素,有一个或多个子元素,有零个或多个子元素,至少有一个子元素。你还可以定义复合关系,比如“元素X是有效的,如果它含有一个或多个子元素Y,或一个子元素Z”。
元素定义是由它们的元素内容模型(ECM)来描述的,也就是说,是由紧跟元素后面的括号中的内容来定义的。因此,正如我们前面见到的,元素“联系人”的ECM被描述为子元素“姓名”: <!ELEMENT 联系人(姓名)>
ECM中的内容采取一组正则表达式的形式。在下表中,我们列出了正则表达式中可能出现的元字符:
?
注意,由于在“(姓名|电话|EMAIL|#PCDATA)”之外有“*”,所以在元素“联系人”中可以包含零个或多个“姓名”、电话、EMAIL和纯文本字段。
还有一种情况没有说,那就是,一个元素中不包含任何子元素,也不包含纯文本。对于这种情况,我们可以定义一个空标记。当然,定义这样一个标记很简单,你只需要使用关键字EMPTY就可以了,例如:<!ELEMENT HR EMPTY> 这样,在你的XML文件中,就可以使用一个空元素<HR/>。
在Dtd中定义属性时,我们使用下面的格式: <!ATTLIST 元素名 (属性名 属性类型 缺省值)*>
元素名是属性所属的元素的名字,在上面例子中,元素名是“商品”;属性名是属性的命名,例子中,“类型”和“颜色”是属性名;缺省值说明在XML文件中,如果没有特别说明属性的取值,语法分析器默认它具有的取值;属性类型则用来指定该属性是属于十个有效属性类型中的哪种类型。
注意:由于ATTLIST是一个属性的列表,它可以包含很多属性,在实际应用中,一个元素也经常有多个属性。
上面例子中的属性可以如下定义:
?
?
回页首
NOTATION类型
NOTATION类型允许属性值为一个Dtd中声明的符号,这个类型对于使用非XML格式的数据非常有用。
现实世界中存在着很多无法或不易用XML格式组织的数据,例如图象、声音、影象等等。对于这些数据,XML应用程序常常并不提供直接的应用支持。通过为它们设定 NOTATION类型的属性,可以向应用程序指定一个外部的处理程序。例如,当你想要为一个给定的文件类型指定一个演示设备时,可以用NOTATION类型的属性作为触发。
要使用NOTATION类型作为属性的类型,首先要在Dtd中为可选用的记号作出定义。定义的方式有两种,一种是使用MIME类型,形式是:
<!NOTATION 记号名 SYSTEM "MIME类型">
再有一种是使用一个URL路径,指定一个处理程序的路径。
<!NOTATION 记号名 SYSTEM "URL路径名">
在下面这个例子中,为"电影"元素指定了两种可选设备:一种是movPlayer.exe,用来播映.mov文件,另一种则用来绘制GIF图象。
<?xml version = "1.0"encoding="Gb2312"standalone = "yes"?><!DOCTYPE 文件[<!ELEMENT 文件 ANY><!ELEMENT 电影 EMPTY><!ATTLIST 电影 演示设备 NOTATION ( mp | gif ) #REQUIRED><!NOTATION mp SYSTEM "movPlayer.exe"><!NOTATION gif SYSTEM "Image/gif">]><文件><电影 演示设备 = "mp"/></文件>
?
回页首
实体属性类型与参数实体
实体在XML中充当着宏或别名的角色。实体最根本的作用是帮助你为一大段文本创建一个别名,这样,在文件的另一个位置需要引用这段文本时,仅需要指向它的别名就可以了。它还意味着一旦需要修改,仅需要在一个地方作改动,就完成了全局的改动。
我们还提到,实体分为一般实体和参数实体两种类型,它们都可以定义为内部的也可以用关键字SYSTEM定义为外部的。实体的定义必须出现在引用之前,而且要注意正确嵌套,不能出现循环引用的情况。在Dtd中,这两种类型的实体都得到了广泛的应用。
实体属性类型
实体类型的属性值属于一般实体,如前所述,它的定义方式是: <!ENTITY 实体名 "实体内容">
或利用SYSTEM定义外部实体,方式为: <!ENTITY 实体名 SYSTEM "外部文件名">
引用方式为: &实体名;
使用关键字ENTITY,则声明一个属性是实体类型,它的取值为已定义的实体。请看下面例子:
<?xml version = "1.0"encoding="Gb2312"standalone = "yes"?><!DOCTYPE 文件[<!ELEMENT 文件 ANY><!ELEMENT 电影 EMPTY><!ATTLIST 电影 来源 ENTITY #REQUIRED><!ENTITY bladeRunner SYSTEM "dvds/bR/br.mov">]><文件><电影 来源 = "&bladeRunner;"></文件>
?
参数实体参数实体专门用在Dtd中。定义方式是: <!ENTITY % 实体名 "实体内容">
或: <!ENTITY % 实体名 SYSTEM "外部文件名">
引用方式为: %实体名;使用参数实体,可以方便元素和属性的声明。例如:
<!ENTITY % TAG_NAMES "姓名 | EMAIL | 电话 | 地址"><!ELEMENT 个人联系信息 (%TAG_NAMES; | 生日)><!ELEMENT 客户联系信息 (%TAG_NAMES; | 公司名)>
?
最后提醒大家注意,不要以为实体属性类型的定义与Dtd有关,所以它使用的就是参数实体。参数实体只能在Dtd中使用,而对于任何元素属性值的指定(除了缺省值外),都是在XML文件正文中进行的,因此实体属性值仍属于一般实体。
<!-- CMA ID: 162349 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file: dw-article-6.0-beta.xsl -->
?