XML标签的自定义功能非常强大,比如本文将要讲解的DTD(Document Type Definition)就带给人们一种面向对象般的感觉,well,下面就来看一下XML中的DTD文件类型定义完全解析

一、何为DTD
DTD的全称为Document Type Definition,是一种文件定义格式,它规定了XML文件结构为XML文件提供了语法与规则。在DTD中定义XML文件的结构,然后按照DTD的声明来编写XML文件。它就好像编程语言中的函数定义,在使用函数时要根据函数声明的格式进行来引用。

二、DTD详解
1、实例详解

<?xml version='1.0' encoding='utf-8'?> 
    <!-- 声明内部DTD --> 
    <!DOCTYPE 目录[ 
     <!ELEMENT 目录 ()+> <!-- 声明XML顶层元素的子元素“”,“+”表示有一个或多个子元素 --> 
     <!ELEMENT  (片名,主演,导演,简介)> <!-- 声明“”元素的子元素 --> 
     <!ATTLIST  类别 CDATA "动作" 年份 CDATA #REQUIRED> <!-- 声明“”元素的属性,两属性分别为“类别”和“年份”,CDATA说明属性的类型为字符型 --> 
     <!ENTITY 十面埋伏 "漫天大雪,三人在雪中决斗"> <!-- 实体的声明,类型为字符型,在下面使用“&实体名称;”直接引用 --> 
     <!ENTITY 霍元甲 "民族英雄,与帝国抗争"> 
     <!ELEMENT 片名 (#PCDATA)> 
     <!ELEMENT 主演 (#PCDATA)> 
     <!ELEMENT 导演 (#PCDATA)> 
     <!ELEMENT 简介 (#PCDATA)> 
    ]> 
    <!-- 由DTD获得的XML --> 
    <目录> 
     < 类别="武侠" 年份="2008"> 
     <片名>十面埋伏</片名> 
     <主演>刘德华、金城武、章子怡</主演> 
     <导演>张艺谋</导演> 
     <简介>&十面埋伏;</简介> 
     </> 
     < 类别="武侠" 年份="2006"> 
     <片名>霍元甲</片名> 
     <主演>李连杰</主演> 
     <导演>于仁泰</导演> 
     <简介>&霍元甲;</简介> 
     </> 
    </目录>

1.1 DTD声明开始语句

(1)内部声明:<!DOCTYPE [具体的DTD语句]>
(2)外部声明:<!DOCTYPE 引用的DTD的根元素 关键字(SYSTEM/PUBLIC) "dtd文件名称/dtd文件的网络地址">
对于外部声明有多种形式,主要分为SYSTEM和PUBLIC类型的文件。
SYSTEM:一个作者或组织编写的众多XML文档中通用的DTD;
PUBLIC:由权威机构制定,提供给特定行业或公众使用的DTD。
1.2 其它声明
(1)元素:

<!ELEMENT element_name element_definition>

(2)属性列表:

<!ATTLIST Element_Name 
     Attribute_Name Type [added_declare] 
     Attribute_Name Type [added_declare] 
     ...... 
    >

(3)实体
内部
一般:<!ENTITY Entity_Name Entity_Value>
参数:<!ENTITY Entity_Name SYSTEM Entity_URL>
外部
一般:<!ENTITY % Entity_Name Entity_Value>
参数:<!ENTITY % Entity_Name SYSTEM Entity_URL>

2、内容详解
2.1 元素声明

在元素声明中需要注意的主要是几种特殊的元素声明和子元素出现的次数、选择性、混合型,它们的作用类似于编程语言中的算数和逻辑运算符。如下,为具有多种元素的DTD实例。

<?xml version='1.0' encoding='utf-8'?> 
    <!DOCTYPE 目录 [ 
    <!ELEMENT 目录 (,其它,说明)+> <!-- 使用“+”号表明目录中的子元素出现至少一次 --> 
    <!ELEMENT 其它 EMPTY> <!-- 使用EMPTY关键字声明空元素 --> 
    <!ELEMENT 说明 ANY> <!-- 使用ANY关键字声明任何内容的元素 --> 
    <!ELEMENT (片名,主演,导演,简介)><!-- 含有子元素的元素声明格式 -->  
    <!ATTLIST   
    名称 ID #FIXED "十面埋伏" 
    类别 CDATA "动作"  
    年份 CDATA #REQUIRED 
    票房 CDATA #IMPLIED 
     
    ><!-- 属性声明 --> 
    <!ENTITY introduction "漫天大雪,三人在雪中决斗"> 
    <!ELEMENT 片名(#PCDATA)> 
    <!ELEMENT 主演(#PCDATA)> 
    <!ELEMENT 导演(#PCDATA)> 
    <!ELEMENT 简介(#PCDATA)> 
    ]>

想要深入了解元素声明的基本语法,请下载该导图。
2.2 命名冲突

在一个复杂的XML文档中有的时候会出现同名的元素,为了避免这种现象引入了命名空间和前缀标识。
2.2.1 命名空间
使用xmlns来引入命名空间,告诉用户哪一部分是属于该空间内的。在作用上它和其它编程语言中的命名空间有点类似,确保了元素的唯一性,避免发生冲突。

<?xml version="1.0" encoding='utf-8'?> 
    < xmlns:h='http://www.abc.edu' xmlns:c='http://www.123.edu'><!-- 使用xmlns:来引用命名空间 --> 
    <db> 
    <h:table>werer</h:table><!-- 告诉用户,此table是在http://www.abc.edu中定义的 --> 
    <c:table>fdfdsfsdf</c:table><!-- 告诉用户,此table是在http://www.123.edu中定义的 --> 
    </db> 
    </

 

作用:标准化元素和属性,并为它们加上唯一标志;确保元素名称中没有冲突,并阐明了它们的来源。
2.2.2 前缀标识
在元素名和属性名前增加一个标识,以唯一区分当前元素或属性来自哪一个DTD,它常常和命名空间联合使用,如上例中的<h:table>和<c:table>。

三、实体详解

有了元素为什么还要引入实体呢?要想区分两者,首先要看实体引入的目的。实体机制是一种节省大量时间的工具,将多种不同类型的数据并入XML文档的方法。它就好像是面向对象的抽象类一样,把经常使用的抽象成一个实体,在使用它的地方可以直接引用,避免了重复。
详细的说
(1)代替无法输入的字符,键盘只有26个字母和一些简单的标点符号,而字符集中有成N多各种符号是无法在键盘中输入的。
(2)代替一些与xml规范保留字相冲突的内容,如:< > 等等。
(3)代替大段的重复的文本。
实体引用按照引用的位置分为内部和外部两种,按照引用的内容分为一般和参数引用两种。下面看一个外部实体引用的实例:

清单1:“2.dtd”的声明

<!-- 声明外部DTD,并保存为2.dtd --> 
      
    <!ELEMENT 目录 ()+> 
    <!ELEMENT  (片名,主演,导演,简介)> 
    <!ATTLIST  类别 CDATA "动作" 年份 CDATA #REQUIRED> 
    <!ENTITY 十面埋伏 "漫天大雪,三人在雪中决斗"> 
    <!ENTITY 霍元甲 "民族英雄,与帝国抗争"> 
    <!ELEMENT 片名 (#PCDATA)> 
    <!ELEMENT 主演 (#PCDATA)> 
    <!ELEMENT 导演 (#PCDATA)> 
    <!ELEMENT 简介 (#PCDATA)> 
    <!ENTITY filmcomment SYSTEM "影评.xml"> <!-- 引用外部通用实体,文件名称为“影评.xml” -->

清单2:影评.xml的内容

<?xml version="1.0" encoding='utf-8'?> 
    <影评> 
     这些影评都是由XXX公司出品,值得观看! 
    </影评>

清单3:使用dtd的xml文件中的内容。

<?xml version="1.0" encoding='utf-8'?> 
    <!DOCTYPE 目录 SYSTEM "./2.dtd" > 
    <目录> 
    < 类别="武侠" 年份="2008"> 
    <片名>十面埋伏</片名> 
    <主演>刘德华、金城武、章子怡</主演> 
    <导演>张艺谋</导演> 
    <简介>&十面埋伏;</简介> 
    </> 
    < 类别="武侠" 年份="2006"> 
    <片名>霍元甲</片名> 
    <主演>李连杰</主演> 
    <导演>于仁泰</导演> 
    <简介>&霍元甲;</简介> 
    </> 
     &filmcomment; 
    </目录>

 
清单4:使用IE8打开清单3后的内容

<?xml version="1.0" encoding="utf-8" ?> 
    <!DOCTYPE 目录 (View Source for full doctype...)> 
    - <目录> 
    - < 类别="武侠" 年份="2008"> 
     <片名>十面埋伏</片名> 
     <主演>刘德华、金城武、章子怡</主演> 
     <导演>张艺谋</导演> 
     <简介>漫天大雪,三人在雪中决斗</简介> 
    </> 
    - < 类别="武侠" 年份="2006"> 
     <片名>霍元甲</片名> 
     <主演>李连杰</主演> 
     <导演>于仁泰</导演> 
     <简介>民族英雄,与帝国抗争</简介> 
    </> 
    <影评>这些影评都是由XXX公司出品,值得观看!</影评> 
    </目录>

内部和外部很容易理解,主要看一般和参数两种引用的区别。

1.参数实体

清单1:test.dtd,在此该内容单独存在了一个dtd文件中是因为在内部DTD子集中。
参数实体引用不能在标记声明内部出现,可以在标记声明允许出现的地方出现。然而,对于外部DTD子集,则没有这个限制。
XML/HTML Code复制内容到剪贴板

<!-- 声明外部DTD,并保存为test.dtd --> 
    <!-- 个人信息实体声明的是参数类型的,可以再各个元素同使用该参数 --> 
    <!ENTITY % 个人信息 "(姓名,性别,出生日期)"> 
    <!ELEMENT 学生信息 %个人信息;> 
    <!ELEMENT 教师信息 %个人信息;> 
    <!ELEMENT 员工信息 %个人信息;>


清单2:学校信息.xml文件,引用了外部的test.dtd文件

<?xml version='1.0' encoding='utf-8'?> 
    <!-- 学校信息.xml文件 -->  
    <!-- 引用外部DTD --> 
    <!DOCTYPE 学校信息 SYSTEM './test.dtd'> 
    <!-- 由DTD获得的XML --> 
    <学校信息> 
     <学生信息> 
    <姓名>张三</姓名> 
    <性别>男</性别> 
    <出生日期>2013-10-12</出生日期> 
     </学生信息> 
     <教师信息> 
    <姓名>张三</姓名> 
    <性别>男</性别> 
    <出生日期>2013-10-12</出生日期> 
     </教师信息> 
     <员工信息> 
    <姓名>张三</姓名> 
    <性别>男</性别> 
    <出生日期>2013-10-12</出生日期> 
     </员工信息> 
    </学校信息>

 
清单3:使用IE8打开清单2的内容后

<?xml version="1.0" encoding="utf-8" ?> 
    - <!--   
     声明内部DTD  
    --> 
    <!DOCTYPE 学校信息 (View Source for full doctype...)> 
    - <!--   
     由DTD获得的XML  
    --> 
    - <学校信息> 
    -<学生信息> 
     <姓名>张三</姓名> 
     <性别>男</性别> 
     <出生日期>2013-10-12</出生日期> 
     </学生信息> 
    -<教师信息> 
    <姓名>张三</姓名> 
    <性别>男</性别> 
    <出生日期>2013-10-12</出生日期> 
     </教师信息> 
    -<员工信息> 
    <姓名>张三</姓名> 
    <性别>男</性别> 
    <出生日期>2013-10-12</出生日期> 
     </员工信息> 
    </学校信息>

 
2. 一般实体

可在XML元素中加以引用,也可以在DTD中引用,但参数实体只能在DTD中引用,并且通常情况下只能在外部DTD文档中引用。

3. 对比升华

参数实体与一般实体的区别如下:

(l)在定义参数实体时,实体名前必须加一个“%”号。

(2)参数实体引用以“%”开始,而不是一般实体引用的“&”。

(3)参数实体的内容不仅可以包含文本,还可以包含标记。

(4)参数实体只能应用于DTD,而不能在文档本体中引用。即参数实体只能用来构成DTD的内容,而不能构成文档内容。

(5)参数实体只能在外部DTD文档中使用,无法应用于内部DTD。


外部参数实体与外部一般实体的区别如下:

(1)外部参数实体应用于独立的DTD文档,外部一般实体应用于XML文档。

(2)外部参数实体应用于将多个独立的DTD文档组合为一个大的DTD文档,外部一般实体用于将多个独立的XML文档组合成一个大的XML文档。


四、验证XML文件的合法性

DTD定义了XML文件的使用格式,它从结构和形式上限制了XML文档,通过引用DTD可以形成统一的规范化的XML文档,另外通过使用实体简化了DTD和XML文档的内容。使用DTD验证的XML文档才能称为规范化文档,那如何验证所写的XML文档是否符合DTD的规范呢。通过如下的代码串:

import javax.xml.parsers.DocumentBuilder; 
    import javax.xml.parsers.DocumentBuilderFactory; 
     
    import org.xml.sax.InputSource; 
     
    public class ValidateDTD 
    { 
    public static void main(String[] args){ 
     
    //在验证前需要把需要验证的XML和规范DTD包含在jar中 
    try{ 
    DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();//创建一个文档构造工厂 
    dbf.setValidating(true); 
    DocumentBuilder builder=dbf.newDocumentBuilder(); 
    builder.parse(new InputSource("xml-2-2.xml"));//需要验证的XML名称 
    }catch(Exception e){ 
    e.printStackTrace(); 
    } 
    } 
    }

上面代码中的类和结构主要完成了XML文档的解析,并且在解析之前验证当前XML文件是否符合某个DTD的定义。在上面的代码运行前需要将需要验证的XML和提供规范化的DTD文档引入到当前ValidateDTD项目中,后运行上面的代码实例,该项目会在项目文件中自动查找规范的DTD,然后验证xml文件。

五、结语
至此,有关文件定义格式的内容已经基本上讨论了一遍,从最初的元素声明到复杂多变的实体类型,DTD的引入无疑为XML的使用指定了一个统一的标准,这种标准是由提供方规定好,使用方遵守的一种规则,并在最后讨论了如何验证引用DTD的XML合法与否。另外描述XML文档结构的不仅仅只有DTD,DTD是一种早期的定义格式,它有很多缺点,如不支持数据类型,不易于扩展等,为了避免这种缺点后来又引入了Schema,它是DTD的继任者,下篇博客将着重讨论Schema。

最新资讯
马斯克称不在乎求职者学历 但招聘信息出卖了他

马斯克称不在乎求职者

特斯拉CEO埃隆·马斯克(Elon Musk)本月初曾表示,他不在乎
阿里发爱心助农五条准则:以净重为准 品质差将拦截

阿里发爱心助农五条准

阿里巴巴集团向平台商家发布公告,强调平台会持续从商家
小米高管任命:王川任CSO 李肖爽任大家电部总经理

小米高管任命:王川任CS

小米集团刚刚宣布新的架构调整,任命小米集团联合创始人
北京网约车开装“安全舱”,3月2日前8000辆车配齐

北京网约车开装“安全

记者获悉,北京所有的滴滴网约车正陆续装上一层前后排塑
特斯拉德国超级工厂第一阶段将雇佣12000人

特斯拉德国超级工厂第

特斯拉在官网披露的信息显示,德国超级工厂的第一阶段,计
小鹏汽车发生工商变更 中金资本等退出其股东行列

小鹏汽车发生工商变更

广州橙行智动汽车科技有限公司发生工商变更,河南省战新
最新文章
Xml简介_动力节点Java学院整理

Xml简介_动力节点Java

XML 只是基于普通文本,但却提供了几乎可以在任何两个应
详解XML中的模式Schema

详解XML中的模式Schem

XML中拥有Schema特性,能够比DTD更加强大地引入元素结
XML基本概念入门学习指南

XML基本概念入门学习

这篇文章主要介绍了XML基本概念入门学习指南,包括其与
XML中的DTD文档类型定义完全解析

XML中的DTD文档类型定

XML标签的自定义功能非常强大,比如本文将要讲解的DTD(
用Asp与XML实现交互的一个实例源码

用Asp与XML实现交互的

XML是标准扩展语言,是未来Web编程的标准,asp是现在广为
关联数据入门——RDF应用

关联数据入门——RDF

语义网也不仅仅是把数据放在互联网上,而是试图将数据联