DTD约束简介

概述

经过之前对XML的使用我们发现只要遵守XML的语法规定,编写一个结构良好的XML还是很轻松的,通过引入命名空间也可以为文档中的不同元素进行分组。但是我们之前所做的操作全都是对文档结构的要求,而没有在语法语义上对文档进行约束。

比如我们有这样一个文档,文档中保存学生信息:

<students>

<student id="1">

<name>孙悟空</name>

<age>18</age>

<gender>男</gender>

<address>花果山</address>

</student>

</students>

这个文档时比较简单的文档,students根标签,根标签中有一个student子标签。student子标签中又有三个子标签name、age、gender、address。在我们这个文档中我们要求student中的四个子标签按照name、age、gender、address的顺序出现,并且在student标签中不能出现其他子标签。但是以现在的情况看,即使我们不按照这个顺序写,或者student标签中还出现了其他标签,解析器都不会认为文档是错的,因为我们并没有对文档进行语法上的约束。

在标记语言里,语法检查是非常普遍的。一个XML文档的有效是指XML文档内容符合元素、属性和其他文档内容的定义。利用专用的文档类型定义(Document Type Definitions , DTD)和专用的解析器,可以验证一个XML文档的内容是否有效。

通过DTD可以比较轻松的对XML文档中的内容的语法语义进行约束。并且可以通过解析器对XML文档是否符合DTD的语法进行验证,这里我们使用的Eclipse内置的XML编辑器。接下来我们就需要学习如何使用DTD对XML文档进行约束。

先看看效果

在学习DTD之前我们现在看一个DTD约束使用的例子,这里我们使用Eclipse作为编辑器,Eclipse可以自动为XML语法进行验证,我们先看看文档的样子:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE students[

<!ELEMENT students (student)*>

<!ELEMENT student (name , age , gender , address)>

<!ATTLIST student id CDATA #REQUIRED>

]>

<students>

<student id="1">

<name>孙悟空</name>

<gender>男</gender>

<age>18</age>

<address>花果山</address>

</student>

</students>

这样一个文档我们上边写的声明就是对当前文档创建的一个DTD约束,这里我们的age标签写到了gender的下边实际上是不符合我们的语法规范的,如果没有DTD约束编辑器不会出现任何错误,但是当我们在文档中添加了一个DTD约束以后Eclipse会立即在文档中报出错误,如下:

这是Eclipse中截图,图中我画红圈的部分student标签下边多了一行红色的波浪线,这就代表我们的文档不符合DTD的约束。除了Eclipse自动给出提示以为,我们还可以在文档中点击右键选中Validate动对文档进行检查。

验证完毕后,Eclipse会在错误的行号做出标记

当将鼠标放到错误标记处还会有关于错误信息的具体描述:

这里的提示的错误意思是student标签中结构必须满足name、age、gender、address的顺序,而我们这里gender跑到了age的前边,不符合文档中DTD的定义。

我们会发现这里XML文档实际上比之前的多了一部分内容:

<!DOCTYPE students[

<!ELEMENT students (student)*>

<!ELEMENT student (name , age , gender , address)>

<!ATTLIST student id CDATA #REQUIRED>

]>

!DOCTYPE是一个文档类型声明,它告诉解析器,本XML文档需要与一个DTD文件一起使用。在XML文档中如果使用DTD文件,必须将!DOCTYPE放在文档的开头(可以是XML声明后边),不可以放在其他位置。!DOCTYPE开头必须是!。!DOCTYPE 后边紧跟的是当前文档的根标签名。XML中规定的,声明元素必须以!号开头。声明元素时DTD的一部分,它不允许出现在XML的主体内容里。

文档类型声明后边的是DTD定义的主体。在主体我们声明元素、属性、实体和注释。

<!ELEMENT students (student)*>

<!ELEMENT student (name , age , gender , address)>

<!ATTLIST student id CDATA #REQUIRED>

这里我们声明了两个元素和一个属性,它对当前文档中的内容做了一个约束,与DOCTYPE一样元素、属性等声明的第一个字符必须是!号