内部DTD
正如我们前面所提到的,所有的文件都是由序言和文件体构成的。序言中包含了XML声明,而文件体中则是具体的数据信息,还可以含有一些处理指示。实际上,我们在前面隐掉了重要的一点:在序言中还可以包含DTD定义。
最简单的使用DTD的方法是在XML文件的序言部分加入一个DTD描述,加入的位置是紧接在XML处理指示之后。一个包含DTD的XML文件的结构为:
| <?xml version = "1.0" encoding="GB2312" standalone = "yes"?> <!DOCTYPE 根元素名[ 元素描述 ]> 文件体....... |
这样,我们就定义了一个文件,它以DOCTYPE中规定的根元素名作为其根元素的名字。
回忆一下,在第一章中我们曾经举过一个包含客户联系方式信息的XML文件。在这个例子中,我们可以在序言中如下加入DTD定义:
| <?xml version = "1.0" encoding="GB2312" standalone = "yes"?> <!DOCTYPE 联系人列表[ 元素描述 ]> |
一个完整的XML文件为:
| client.xml <?xml version = "1.0" encoding="GB2312" standalone = "yes"?> <!DOCTYPE 联系人列表[ <!ELEMENT 联系人列表 (联系人)*> <!ELEMENT 联系人 (姓名,ID,公司,EMAIL,电话,地址)> <!ELEMENT 地址 (街道,城市,省份)> <!ELEMENT 姓名 (#PCDATA)> <!ELEMENT ID (#PCDATA)> <!ELEMENT 公司 (#PCDATA)> <!ELEMENT EMAIL (#PCDATA)> <!ELEMENT 电话 (#PCDATA)> <!ELEMENT 街道 (#PCDATA)> <!ELEMENT 城市 (#PCDATA)> <!ELEMENT 省份 (#PCDATA)> ]> <?xml-stylesheet type="text/xsl" href="mystyle.xsl"?> <联系人列表> <联系人> <姓名>张三</姓名> <ID>001</ID> <公司>A公司</公司> <EMAIL>zhang@aaa.com</EMAIL> <电话>(010)62345678</电话> <地址> <街道>五街1234号</街道> <城市>北京市</城市> <省份>北京</省份> </地址> </联系人> <联系人> <姓名>李四</姓名> <ID>002</ID> <公司>B公司</公司> <EMAIL>li@bbb.org</EMAIL> <电话>(021)87654321</电话> <地址> <街道>南京路9876号</街道> <城市>上海市</城市> <省份>上海</省份> </地址> </联系人> </联系人列表> |
不过,如果为每一个XML文件加入一段DTD定义,是相当繁琐的。而且,更多的情况下,我们会为一批XML文件定义一个相同的DTD。例如,对于报社中的每篇稿件,它们都有相同的格式,可以采用一个统一的DTD,为每一篇单独定义既麻烦,又不利于统一格式。好在XML规范为我们提供了解决这个问题的方法,它就是外部DTD。外部DTD
一个DTD既可以是内部的,包含在一个“形式良好的”XML文件中(standalone=“yes”),采用前面一节中的形式;也可以是外部的,作为一个外部文件被引用(standalone=“no”)。
外部DTD的好处是:它可以方便高效地被多个XML文件所共享。你只要写一个DTD文件,就可以被多个XML文件所引用。事实上,当许多组织需要统一它们的数据交换格式时,它们就是通过外部DTD来完成的。这样做不仅简化了输入工作,还保证当你需要对DTD做出改动时,不用一一去改每个引用了它的XML文件,只要改一个公用的DTD文件就足够了。不过需要注意,如果DTD的改动不是“向后兼容”的,这时原先写的那些XML文件可能就会出问题了!
为了引用一个外部DTD,必须修改XML声明和DOCTYPE声明。
XML声明中必须说明这个文件不是自成一体的,即standalone属性的属性值不再是yes了。
| <?xml version = "1.0" encoding="GB2312" standalone = "no"?> |
在DOCTYPE声明中,应该加入SYSTEM属性:
| <!DOCTYPE 根元素名 SYSTEM "外部DTD文件的URL"> |
例如:
| <!DOCTYPE 联系人列表 SYSTEM "http://www.mydomain.com/dtds/fclml.dtd "> |
上面的URL是一个绝对路径,除此以外,它还可以是一个相对路径,如:
| <!DOCTYPE 联系人列表 SYSTEM "fclml.dtd"> |
它说明这个DTD文件和引用它的XML文件在同一个目录下。或者,这个DTD文件还可能在XML文件的父目录的子目录DTD下,表示为:
| <!DOCTYPE 联系人列表 SYSTEM "../dtds/fclml.dtd"> |
使用这种方法,你可以方便地把DTD文件从你的XML文件中分离出来,粘贴到另一个文件fclml.dtd中。这样,你就得到一个DTD文件和一个有效的XML文件。
仍然回到前面那个包含客户联系方式信息的XML文件,如果使用外部DTD,其形式应该变为下面这个样子。
DTD文件fclml.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文件client.xml:
| <?xml version = "1.0" encoding="GB2312" standalone = "no"?> <!DOCTYPE 联系人列表 SYSTEM "fclml.dtd"> <?xml-stylesheet type="text/xsl" href="mystyle.xsl"?> <联系人列表> <联系人> <姓名>张三</姓名> <ID>001</ID> <公司>A公司</公司> <EMAIL>zhang@aaa.com</EMAIL> <电话>(010)62345678</电话> <地址> <街道>五街1234号</街道> <城市>北京市</城市> <省份>北京</省份> <ZIP>100001</ZIP> </地址> </联系人> <联系人> <姓名>李四</姓名> <ID>002</ID> <公司>B公司</公司> <EMAIL>li@bbb.org</EMAIL> <电话>(021)87654321</电话> <地址> <街道>南京路9876号</街道> <城市>上海</城市> <省份>上海</省份> <ZIP>200002</ZIP> </地址> </联系人> </联系人列表> |
在这一节里,我们将为每个XML文件定义的DTD推广到一个系统内可共享的DTD。在下一节里,我们还可以将这个推广进一步推而广之,扩大到行业内甚至公众使用的公用DTD。
公用DTD
在前面一节中我们讲过,使用外部DTD时,要在DOCTYPE中使用关键字SYSTEM。实际上,SYSTEM不是引用外部DTD的唯一方法,这个关键字主要用于引用一个作者或组织所编写的众多XML文件中通用的DTD。还存在一种外部DTD,它是一个由权威机构制订的,提供给特定行业或公众使用的DTD。因此,另一个引用外部DTD的办法是使用关键字PUBLIC,引用这一类公开给公众使用的DTD。
当使用关键字PUBLIC进行引用时,这个外部DTD还需要得到一个标识名。引用公共DTD的形式为:
| <!DOCTYPE 根元素 PUBLIC "DTD名称" "外部DTD的URL"> |
请见下面例子:
| <!DOCTYPE 联系人列表 PUBLIC "联系人DTD" "http://www.mydomain.com/dtds/fclml.dtd"> |
这个DTD标识的命名规则和XML文件的命名规则稍有不同。具体地说,DTD名称只能包含字母、数字、空格和下面的符号:_%$#@()+:=/!*;?。同时,DTD名称还必须符合一些标准的规定。例如,ISO标准的DTD以“ISO”三个字母开头;被改进的非ISO标准的DTD以加号“+”开头;未被改进的非ISO标准的DTD以减号“-”开头。
无论是哪一种情况,开始部分后面都跟着两个斜杠“//”及DTD所有者的名称。在这个名称之后又是两个斜杠“//”,再然后是DTD所描述的文件的类型。最后,在又一对斜杠之后是语言的种类(参见ISO 639)。例如下面这个公用DTD的引用:
| <!DOCTYPE 联系人列表 PUBLIC "-//Luna Dong//Contact Data//CN" "http://www.mydomain.com/dtds/fclml.dtd"> |
看上去的确比较复杂,不过没关系,对于DTD的命名通常不是它的引用者的任务,XML文件的编写者只要在自己的文件中把事先定义好的DTD名称放在相应的位置中就可以了。
一个元素的各个子元素之间可以以任意顺序出现,也可以强制遵循一定的顺序。如果要严格按照顺序,那么元素之间要用“,”来隔开。如果不按顺序,则不需要用“,”隔开。
4万+

被折叠的 条评论
为什么被折叠?



