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一样元素、属性等声明的第一个字符必须是!号