将DTD引入“有效的”XML文件中 然而,即便你已经可以保证写的XML文件是一个“形式良好的”XML文件了,它仍然未必能够体现XML的精髓。XML的精髓是什么呢?对,就是我们前面讲 到的基于信息描述的、能够体现数据信息之间逻辑关系的、可以确保文件的易读性和易搜索性的自定义标记!从这一章中你将看到,使得你的XML文件遵循所谓 “形式良好”要求的种种语法规则,这只是“万里长征走了第一步”。一个完全意义上的XML文件不仅应该是“形式良好的”,而且还应该是使用了这些自定义标 记的“有效”的XML文件。 一个“有效的”文件首先应该是“形式良好”的。但这还远远不够,它还要往前更进一步。一个XML文件必须遵守文件类型描述DTD (Document Type Definition)中定义的种种规定。DTD实际上是“元标记”这个概念的产物,它描述了一个置标语言的语法和词汇 表,也就是定义了文件的整体结构以及文件的语法。简而言之,DTD规定了一个语法分析器为了解释一个“有效的”XML文件所需要知道的所有规则的细节。 这个“规则”可以非常简单,仅仅列出所有有效的元素,例如元素、标记、属性、实体;也可以非常复杂,不但列出这些元素,还指出这些元素之间的内在联系,例如说明元素X元素中必须还包含元素Y或元素Z,但不能同时包含两个元素。 “我们前面强调了XML是大小写敏感的,这对于HTML的老手可能有点麻烦。例如,XML的处理指示 中所有单词必须都是小写的;可是所有DTD中的关键字都必须是大写的,例如ELEMENT、ATTLIST、#REQUIRED、#IMPLIED、 NMTOKEN、ID等等。幸运的是,你自己的元素和属性的大小写可以由你任意指定,但一旦指定了,你必须从一而终,在整个文件中使用相同的大小写。例 如,如果你给一个元素起名叫“BOOKS”,那么这个元素和“Books”并不相同。 ——Ken Sall” 一般习惯里,除非使用中文标记,否则我们或者全部都使用大写字母,或者象在VC中常用的那样,元素名字的第一个字母是大写,后面每个单词的第一个字母为大 写,如BookList;属性字母的第一个字母为小写,但后面每个单词的第一个字母仍都采用大写,如listAuthor。请看下面例子: <!ELEMENT BookList (Book)+ > 棕色 扑向 正如你所见,所有的单词和标点都符合中文的词法,甚至说都是有明确语意的词汇,它们代表了“形式良好的”元素。但是,你明白我要表达的意思吗?在这种混乱 的顺序之下,可能那些明确的单词和标点对你也失去了应有的意义。连人都难于理解一段“形式良好的”话,更不要说什么计算机了。 为了使这句话成为能读得懂的话,上面那些词汇的组织必须遵守中文句子的语法规定,譬如符合主、谓、宾的顺序,修饰语放在中心词之前等等。修改一下,上面的句子应该成为下面的形式: 一只动作敏捷的棕色狐狸扑向一只懒惰的狗。 好了,现在知道这句话想表达什么意思了吧? 在XML所描述的置标语言中,DTD便提供了语法规定,以便给各个语言要素赋予一定的顺序。为了说明特定的语法规则,DTD采用了一系列正则式,语法分析 器将这些正则式与XML文件内部的数据模式相匹配,从而判别一个文件是否是有效的。匹配被严格执行,因此,如果XML文件中有任何信息不符合DTD的规 定,都不会通过。 还记得我们曾说过XML脱胎于SGML文件吗?其实,一个“有效的”XML文件就是一个“形式良好的”SGML文件,也就是说,符合DTD中定义的语法是 SGML文件的基本要求。从这个意义上说,XML把合法文件的范围扩大了,既包括“有效的”XML,也可包括“形式良好的”XML。 好了,相信大家现在已经明白什么叫DTD了。下面我们就开始详细学习XML中这个不可或缺、大显身手的部分。 内部DTD 正如我们前面所提到的,所有的文件都是由序言和文件体构成的。序言中包含了XML声明,而文件体中则是具体的数据信息,还可以含有一些处理指示。实际上,我们在前面隐掉了重要的一点:在序言中还可以包含DTD定义。 最简单的使用DTD的方法是在XML文件的序言部分加入一个DTD描述,加入的位置是紧接在XML处理指示之后。一个包含DTD的XML文件的结构为: <?xml version = "1.0" encoding="GB2312" standalone = "yes"?> 这样,我们就定义了一个文件,它以DOCTYPE中规定的根元素名作为其根元素的名字。 回忆一下,在第一章中我们曾经举过一个包含客户联系方式信息的XML文件。在这个例子中,我们可以在序言中如下加入DTD定义: <?xml version = "1.0" encoding="GB2312" standalone = "yes"?> client.xml <联系人列表> <联系人> 外部DTD 外部DTD的好处是:它可以方便高效地被多个XML文件所共享。你只要写一个DTD文件,就可以被多个XML文件所引用。事实上,当许多组织需要统一它们 的数据交换格式时,它们就是通过外部DTD来完成的。这样做不仅简化了输入工作,还保证当你需要对DTD做出改动时,不用一一去改每个引用了它的XML文 件,只要改一个公用的DTD文件就足够了。不过需要注意,如果DTD的改动不是“向后兼容”的,这时原先写的那些XML文件可能就会出问题了! 为了引用一个外部DTD,必须修改XML声明和DOCTYPE声明。 XML声明中必须说明这个文件不是自成一体的,即standalone属性的属性值不再是yes了。 <?xml version = "1.0" 在DOCTYPE声明中,应该加入SYSTEM属性: <!DOCTYPE 根元素名 例如: <!DOCTYPE 联系人列表 上面的URL是一个绝对路径,除此以外,它还可以是一个相对路径,如: <!DOCTYPE 联系人列表 它说明这个DTD文件和引用它的XML文件在同一个目录下。或者,这个DTD文件还可能在XML文件的父目录的子目录DTD下,表示为: 使用这种方法,你可以方便地把DTD文件从你的XML文件中分离出来,粘贴到另一个文件fclml.dtd中。这样,你就得到一个DTD文件和一个有效的XML文件。 仍然回到前面那个包含客户联系方式信息的XML文件,如果使用外部DTD,其形式应该变为下面这个样子。 DTD文件fclml.dtd: <?xml version="1.0" encoding="GB2312"?> <!ELEMENT 联系人列表 (联系人)*> XML文件client.xml: <?xml version = "1.0" encoding="GB2312" standalone = "no"?> <联系人列表> <联系人> 公用DTD 当使用关键字PUBLIC进行引用时,这个外部DTD还需要得到一个标识名。引用公共DTD的形式为: <!DOCTYPE 根元素 PUBLIC "DTD名称" "外部DTD的URL"> 请见下面例子: <!DOCTYPE 联系人列表 PUBLIC "联系人DTD" "http://www./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" 实体属性类型与参数实体 实体最根本的作用是帮助你为一大段文本创建一个别名,这样,在文件的另一个位置需要引用这段文本时,仅需要指向它的别名就可以了。可想而知,这样一来,用 于重新输入这段文本的大量时间就被节约下来了。它还意味着一旦需要修改,仅需要在一个地方作改动,就完成了全局的改动。 我们还提到,实体分为一般实体和参数实体两种类型,它们都可以定义为内部的也可以用关键字SYSTEM定义为外部的。实体的定义必须出现在引用之前,而且要注意正确嵌套,不能出现循环引用的情况。在DTD中,这两种类型的实体都得到了广泛的应用。 实体属性类型 <!ENTITY 实体名 "实体内容"> 或利用SYSTEM定义外部实体,方式为: <!ENTITY 实体名 SYSTEM "外部文件名"> 引用方式为: &实体名; 使用关键字ENTITY,则声明一个属性是实体类型,它的取值为已定义的实体。请看下面例子: <?xml version = "1.0" <文件> 参数实体 <!ENTITY % 实体名 "实体内容"> 或: <!ENTITY % 实体名 SYSTEM "外部文件名"> 引用方式为: %实体名; 使用参数实体,可以方便元素和属性的声明。例如: <!ENTITY % TAG_NAMES "姓名 | EMAIL | 电话 | 地址"> 转帖网址:http://bbs./dispbbs.asp?boardID=1&ID=22530 |
|