Chinaunix首页 | 论坛 | 博客
  • 博客访问: 416641
  • 博文数量: 95
  • 博客积分: 5001
  • 博客等级: 大校
  • 技术积分: 1030
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-13 11:43
文章分类

全部博文(95)

文章存档

2007年(95)

我的朋友

分类: 系统运维

2007-05-22 10:24:51

    内部Dtd

    一个“有效的”文件首先应该是“形式良好”的。但这还远远不够,它还要往前更进一步。一个XML文件必须遵守文件类型描述Dtd(Document Type Definition)中定义的种种规定。所有的文件都是由序言和文件体构成的。序言中包含了XML声明,在序言中还可以包含Dtd定义。

    最简单的使用Dtd的方法是在XML文件的序言部分加入一个Dtd描述,加入的位置是紧接在XML处理指示之后。一个包含Dtd的XML文件的结构为:

    <?xml version = "1.0" encoding="Gb2312" standalone = "yes"?>

    <?DOCTYPE 根元素名[元素描述]>

    文件体……

    这样,我们就定义了一个文件,它以DOCTYPE中规定的根元素名作为其根元素的名字。

    如果为每一个XML文件加入一段Dtd定义,是相当繁琐的。而且,更多的情况下,我们会为一批XML文件定义一个相同的Dtd.例如,对于报社中的每篇稿 件,它们都有相同的格式,可以采用一个统一的Dtd,为每一篇单独定义既麻烦,又不利于统一格式。好在XML规范为我们提供了解决这个问题的方法,它就是 外部Dtd.

     外部Dtd的好处是:它可以方便高效地被多个XML文件所共享。你只要写一个Dtd 文件,就可以被多个XML文件所引用。事实上,当许多组织需要统一它 们的数据交换格式时,它们就是通过外部Dtd来完成的。这样做不仅简化了输入工作,还保证当你需要对Dtd做出改动时,不用一一去改每个引用了它的XML 文件,只要改一个公用的Dtd文件就足够了

为了引用一个外部Dtd,必须修改XML声明和DOCTYPE声明。

XML声明中必须说明这个文件不是自成一体的,即standalone属性的属性值不再是yes了:



 
 
在DOCTYPE声明中,应该加入SYSTEM属性:

例如:



 

    上面的URL是一个绝对路径,除此以外,它还可以是一个相对路径,如:  它说明这个Dtd文件和引用它的XML文件在同一个目录下。

    使用这种方法,你可以方便地把Dtd文件从你的XML文件中分离出来,粘贴到另一个文件fclml.dtd中。这样,你就得到一个Dtd文件和一个有效的XML文件。


公用Dtd

    使用外部Dtd时,要在DOCTYPE中使用关键字SYSTEM。实际上,SYSTEM不是引用外部Dtd的唯一方法,这个关键字主要用于引用一个作者或 组织所编写的众多 XML文件中通用的Dtd。还存在一种外部Dtd,它是一个由权威机构制订的,提供给特定行业或公众使用的Dtd。因此,另一个引用外 部Dtd的办法是使用关键字 PUbLIC,引用这一类公开给公众使用的Dtd。

    当使用关键字PUbLIC进行引用时,这个外部Dtd还需要得到一个标识名。引用公共Dtd的形式为:  

请见下面例子:



 


    这个Dtd标识的命名规则和XML文件的命名规则稍有不同。具体地说,Dtd名称只能包含字母、数字、空格和下面的符号:_%$#@()+:=/! *;?。同时,Dtd名称还必须符合一些标准的规定。例如,ISO标准的Dtd以“ISO”三个字母开头;被改进的非ISO 标准的Dtd以加号“+”开 头;未被改进的非ISO标准的Dtd以减号“-”开头。

    无论是哪一种情况,开始部分后面都跟着两个斜杠“//”及Dtd所有者的名称。在这个名称之后又是两个斜杠“//”,再然后是Dtd所描述的文件的类型。最后,在又一对斜杠之后是语言的种类(参见ISO 639)。例如下面这个公用Dtd的引用:



 

    看上去的确比较复杂,不过没关系,对于Dtd的命名通常不是它的引用者的任务,XML 文件的编写者只要在自己的文件中把事先定义好的Dtd名称放在相应的位置中就可以了。


元素类型声明1

    一个Dtd不仅要告诉语法分析器它所关联的XML文件的根元素是什么,而且还要告诉语法分析器文件的内容和结构,说清文件结构中的每一个细节。为了定义这些细节,我们必须展开Dtd中元素说明部分,使用元素类型声明(Etd)来声明所有有效的文件元素。

    Etd不但说明了每个文件中可能存在的元素,给出了元素的名字,而且给出了元素的具体类型。一个XML元素可以为空,也可以是一段纯文本,还可以有若干个 子元素,而这些子元素同时又可以有它们的子元素。Dtd正是通过元素之间的父子关系,描述了整个文件的结构关系。

Etd应该采用如下的结构:  

因此,在前面的例子里,可以在文件序言中通过如下方式定义“联系人列表”这个元素:




]>

<联系人列表>
...

 


    这个Dtd定义了一个XML文件,它只有一个根元素,名为“联系人列表”,这个元素可以有任何类型的子元素,也可以是纯文本,还可以为空。

    但是需要注意,尽管元素“联系人列表”被定义为“可以”包含其它元素,但实际上这个 Dtd除了“联系人列表”元素本身外没有定义任何其它元素,所以也就 没有其它元素可以用作“联系人列表”的子元素。“有效的”XML文件规定文件中所使用的任何元素都必须在Dtd中给出定义。 

    在“ANY”定义下使用任何纯文本都是无须另加说明的,这一点与元素不同。故而,在相同的Dtd定义下,下面一段XML文件则是合法的:




]>

<联系人列表>
纯文本信息说明联系人信息



元素类型声明2

    为了使元素“联系人列表”中还可以包含其它元素,从而使前面的那个文件是“有效 的”,我们还需要定义元素“联系人”和“姓名”。






]>

<联系人列表>
<联系人>
<姓名>张三


 
    现在我们已经定义了一个XML文件,它的根元素名为“联系人列表”。“联系人列表” 中可以包含任何纯文本数据,也可以含有子元素(这即是ANY的含 义)。根据后面的定义,我们知道,“联系人列表”中可以包含子元素“联系人”,也可以直接包含子元素“姓名”;“联系人”元素又可以包含自己的子元素,名 为“姓名”;而“姓名”则只能包含纯文本数据(即(#PCDATA))

注意: 


除了根元素外,在定义其它元素时使用关键字ANY都是不好的习惯。 
在定义元素时,Etd的顺序是无关紧要的。 
还有一点要注意,不能对不同的元素使用相同的元素名,即便这些元素的内容、包含的子元素不同也不行,因为它只会引起文件各个元素的混淆,使文件的可读性大打折扣。 
元 素名的第一个字母必须是字母、或下划线(_)、或冒号(:),后跟字母、数字、句号(.)、冒号、下划线、连结号(-)的组合,并且不能包含空白符,不能 以 “xml”开头。尽管XML1.0标准允许使用任何长度的文件名,但是实际的XML处理器常常会限制标记名的长度。 

定义元素及其子元素

对于以下的例子:






]>

<联系人列表>
<联系人>
<姓名>张三


 


    准确的说法是,元素“联系人”必须包含一个,且只能包含一个子元素“姓名”。可如果子元素是“EMAIL地址”怎么办?联系人可能根本没有自己的EMAIL邮箱,也可能有好几个EMAIL帐号。

    使用正则表达式,我们就可以解决上述问题,描述父元素与子元素之间非常复杂的关系。例如,你可以对一个元素作如下任何一种类型的定义:它有一个子元素,有 一个或多个子元素,有零个或多个子元素,至少有一个子元素。你还可以定义复合关系,比如“元素X是有效的,如果它含有一个或多个子元素Y,或一个子元素 Z”。

    元素定义是由它们的元素内容模型(ECM)来描述的,也就是说,是由紧跟元素后面的括号中的内容来定义的。因此,正如我们前面见到的,元素“联系人”的ECM被描述为子元素“姓名”:  

ECM中的内容采取一组正则表达式的形式。在下表中,我们列出了正则表达式中可能出现的元字符: 
元字符 含义 
+ 出现一次或多次 
* 出现零次或多次 
? 可选,不出现或出现一次 
() 一组要共同匹配的表达式 
| OR,或,AND 要求严格遵从顺序要求 


下面几节中,我们将通过一些例子具体讲解这些元字符的用法,对使用正则表达式来定义ECM的方法获得一些感性认识。


有顺序的子元素

一个元素的各个子元素之间可以以任意顺序出现,也可以强制遵循一定的顺序。

考虑下面的Dtd定义:





 

遵从这个Dtd的XML文件可以为:


<联系人>
<姓名>张三
zhang@aaa.com

 

同样,下面这个XML文件也是有效的:


<联系人>
zhang@aaa.com
<姓名>张三

 

由于我们在Dtd定义中仅仅用空白符分隔了元素“联系人”的两个子元素,这说明我们并没有严格要求两个元素出现的顺序,因此上面两种写法都是允许的。如果我们使用逗号“,”来分隔两个子元素,那么XML文件中,元素“姓名”就必须出现在元素“EMAIL”前面。
 

重复元素

让我们再把上节的例子作一个小小的改动:





 

    让我们看看前面给出的正则表达式的元字符集列表,它说明一个“联系人”元素中必须含有一个“姓名”元素,后面接一个或多个“EMAIL”元素。这样,下面的这段XML 文件是“有效的”。


<联系人>
<姓名>张三
zhang@aaa.com
zhang@hotmail.com
zhang@yahoo.com

 
那么下面这段XML文件不是有效的,因为它没有“EMAIL”元素,而“+”代表了“一个或多个”


<联系人>
<姓名>张三

 
如果你需要表示“零个或多个”,那么应该使用字符“*”。例如:





 

成组元素

子元素可以使用括号并为一组。因此,下面的Dtd片段说明,一个“联系人”元素中可以有一个或多个“姓名/EMAIL”子元素对,并且在每个子元素对中,“姓名”都放在“EMAIL”之前。





 


符合这个Dtd的XML文件可以是:


<联系人>
<姓名>张三
zhang@aaa.com

<姓名>李四
li@bbb.org

<姓名>王五
wang@ccc.org

 


注意,仅仅是因为“+”由括号里面移到括号外面,元素“联系人”的内容就大大不同了


OR或

号“|”描述了一个OR操作。因此,下面的Dtd片段所规定的XML元素是:所有的 “联系人”元素应该有一个“姓名”子元素,同时,在此之后还应该有一个“电话”或一个“EMAIL”元素,但不能同时有“电话”和“EMAIL”两个元素。


|EMAIL))>




一个符合上述Dtd定义的“有效的”XML文件的定义应该是:


<联系人>
<姓名>张三
<电话>12345678

 


或者是:


<联系人>
<姓名>张三
zhang@yahoo.com

 

注意:在一个组中,只允许使用一种连接符(例如“,”或“|”)。因此,象下面这样定义的Dtd是不合法的:

要想使用多种连接符,只有通过创建子组的方式,使用


可选子元素

字 符“?”说明一个子元素是可选的,它可以出现,也可以不出现。因此,在下面的Dtd 中,我们规定,每一个“联系人”都必须有一个“姓名”子元素,同时或 者有一个“电话” 子元素,或者有一个“EMAIL”子元素,此外,它还可以包含一个“地址”子元素,也可以不包含这种元素。










 

根据这个Dtd描述,下面的XML片段是“有效的”:


<联系人>
<姓名>张三
zhang@aaa.com
<地址>
<街道>五街1234号
<城市>北京市
<省份>北京


 

同样,下面这段不包含“地址”元素的XML片段也是“有效的”:


<联系人>
<姓名>张三
zhang@aaa.com

 
 

阅读(1503) | 评论(0) | 转发(0) |
0

上一篇:MVC模式

下一篇:Dtd【2】

给主人留下些什么吧!~~