XML中的DTD文檔類型定義完全解析

一、何為DTD
DTD的全稱為Document Type Definition,是一種文件定義格式,它規(guī)定了XML文件結(jié)構(gòu)為XML文件提供了語法與規(guī)則。在DTD中定義XML文件的結(jié)構(gòu),然后按照DTD的聲明來編寫XML文件。它就好像編程語言中的函數(shù)定義,在使用函數(shù)時要根據(jù)函數(shù)聲明的格式進行來引用。
二、DTD詳解
1、實例詳解
- <?xml version='1.0' encoding='utf-8'?>
- <!-- 聲明內(nèi)部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)內(nèi)部聲明:<!DOCTYPE [具體的DTD語句]>
(2)外部聲明:<!DOCTYPE 引用的DTD的根元素 關(guān)鍵字(SYSTEM/PUBLIC) "dtd文件名稱/dtd文件的網(wǎng)絡地址">
對于外部聲明有多種形式,主要分為SYSTEM和PUBLIC類型的文件。
SYSTEM:一個作者或組織編寫的眾多XML文檔中通用的DTD;
PUBLIC:由權(quán)威機構(gòu)制定,提供給特定行業(yè)或公眾使用的DTD。
1.2 其它聲明
(1)元素:
- <!ELEMENT element_name element_definition>
(2)屬性列表:
- <!ATTLIST Element_Name
- Attribute_Name Type [added_declare]
- Attribute_Name Type [added_declare]
- ......
- >
(3)實體
內(nèi)部
一般:<!ENTITY Entity_Name Entity_Value>
參數(shù):<!ENTITY Entity_Name SYSTEM Entity_URL>
外部
一般:<!ENTITY % Entity_Name Entity_Value>
參數(shù):<!ENTITY % Entity_Name SYSTEM Entity_URL>
2、內(nèi)容詳解
2.1 元素聲明
在元素聲明中需要注意的主要是幾種特殊的元素聲明和子元素出現(xiàn)的次數(shù)、選擇性、混合型,它們的作用類似于編程語言中的算數(shù)和邏輯運算符。如下,為具有多種元素的DTD實例。
- <?xml version='1.0' encoding='utf-8'?>
- <!DOCTYPE 影片目錄 [
- <!ELEMENT 影片目錄 (影片,其它,說明)+> <!-- 使用“+”號表明影片目錄中的子元素出現(xiàn)至少一次 -->
- <!ELEMENT 其它 EMPTY> <!-- 使用EMPTY關(guān)鍵字聲明空元素 -->
- <!ELEMENT 說明 ANY> <!-- 使用ANY關(guān)鍵字聲明任何內(nèi)容的元素 -->
- <!ELEMENT 影片(片名,主演,導演,簡介)> <!-- 含有子元素的元素聲明格式 -->
- <!ATTLIST 影片
- 名稱 ID #FIXED "十面埋伏"
- 類別 CDATA "動作"
- 年份 CDATA #REQUIRED
- 票房 CDATA #IMPLIED
- > <!-- 屬性聲明 -->
- <!ENTITY introduction "漫天大雪,三人在雪中決斗">
- <!ELEMENT 片名(#PCDATA)>
- <!ELEMENT 主演(#PCDATA)>
- <!ELEMENT 導演(#PCDATA)>
- <!ELEMENT 簡介(#PCDATA)>
- ]>
想要深入了解元素聲明的基本語法,請下載該導圖。
2.2 命名沖突
在一個復雜的XML文檔中有的時候會出現(xiàn)同名的元素,為了避免這種現(xiàn)象引入了命名空間和前綴標識。
2.2.1 命名空間
使用xmlns來引入命名空間,告訴用戶哪一部分是屬于該空間內(nèi)的。在作用上它和其它編程語言中的命名空間有點類似,確保了元素的唯一性,避免發(fā)生沖突。
- <?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 前綴標識
在元素名和屬性名前增加一個標識,以唯一區(qū)分當前元素或?qū)傩詠碜阅囊粋€DTD,它常常和命名空間聯(lián)合使用,如上例中的<h:table>和<c:table>。
三、實體詳解
有了元素為什么還要引入實體呢?要想?yún)^(qū)分兩者,首先要看實體引入的目的。實體機制是一種節(jié)省大量時間的工具,將多種不同類型的數(shù)據(jù)并入XML文檔的方法。它就好像是面向?qū)ο蟮某橄箢愐粯?,把?jīng)常使用的抽象成一個實體,在使用它的地方可以直接引用,避免了重復。
詳細的說
(1)代替無法輸入的字符,鍵盤只有26個字母和一些簡單的標點符號,而字符集中有成N多各種符號是無法在鍵盤中輸入的。
(2)代替一些與xml規(guī)范保留字相沖突的內(nèi)容,如:< > 等等。
(3)代替大段的重復的文本。
實體引用按照引用的位置分為內(nèi)部和外部兩種,按照引用的內(nèi)容分為一般和參數(shù)引用兩種。下面看一個外部實體引用的實例:
清單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的內(nèi)容
- <?xml version="1.0" encoding='utf-8'?>
- <影評>
- 這些影評都是由XXX公司出品,值得觀看!
- </影評>
清單3:使用dtd的xml文件中的內(nèi)容。
- <?xml version="1.0" encoding='utf-8'?>
- <影評>
- 這些影評都是由XXX公司出品,值得觀看!
- </影評>
清單3:使用dtd的xml文件中的內(nèi)容。
- <?xml version="1.0" encoding='utf-8'?>
- <!DOCTYPE 影片目錄 SYSTEM "./2.dtd" >
- <影片目錄>
- <影片 類別="武俠" 年份="2008">
- <片名>十面埋伏</片名>
- <主演>劉德華、金城武、章子怡</主演>
- <導演>張藝謀</導演>
- <簡介>&十面埋伏;</簡介>
- </影片>
- <影片 類別="武俠" 年份="2006">
- <片名>霍元甲</片名>
- <主演>李連杰</主演>
- <導演>于仁泰</導演>
- <簡介>&霍元甲;</簡介>
- </影片>
- &filmcomment;
- </影片目錄>
清單4:使用IE8打開清單3后的內(nèi)容
- <?xml version="1.0" encoding="utf-8" ?>
- <!DOCTYPE 影片目錄 (View Source for full doctype...)>
- - <影片目錄>
- - <影片 類別="武俠" 年份="2008">
- <片名>十面埋伏</片名>
- <主演>劉德華、金城武、章子怡</主演>
- <導演>張藝謀</導演>
- <簡介>漫天大雪,三人在雪中決斗</簡介>
- </影片>
- - <影片 類別="武俠" 年份="2006">
- <片名>霍元甲</片名>
- <主演>李連杰</主演>
- <導演>于仁泰</導演>
- <簡介>民族英雄,與西方帝國主義抗爭</簡介>
- </影片>
- <影評>這些影評都是由XXX公司出品,值得觀看!</影評>
- </影片目錄>
內(nèi)部和外部很容易理解,主要看一般和參數(shù)兩種引用的區(qū)別。
1.參數(shù)實體
清單1:test.dtd,在此該內(nèi)容單獨存在了一個dtd文件中是因為在內(nèi)部DTD子集中。
參數(shù)實體引用不能在標記聲明內(nèi)部出現(xiàn),可以在標記聲明允許出現(xiàn)的地方出現(xiàn)。然而,對于外部DTD子集,則沒有這個限制。
XML/HTML Code復制內(nèi)容到剪貼板
- <!-- 聲明外部DTD,并保存為test.dtd -->
- <!-- 個人信息實體聲明的是參數(shù)類型的,可以再各個元素中共同使用該參數(shù) -->
- <!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的內(nèi)容后
- <?xml version="1.0" encoding="utf-8" ?>
- - <!--
- 聲明內(nèi)部DTD
- -->
- <!DOCTYPE 學校信息 (View Source for full doctype...)>
- - <!--
- 由DTD獲得的XML
- -->
- - <學校信息>
- - <學生信息>
- <姓名>張三</姓名>
- <性別>男</性別>
- <出生日期>2013-10-12</出生日期>
- </學生信息>
- - <教師信息>
- <姓名>張三</姓名>
- <性別>男</性別>
- <出生日期>2013-10-12</出生日期>
- </教師信息>
- - <員工信息>
- <姓名>張三</姓名>
- <性別>男</性別>
- <出生日期>2013-10-12</出生日期>
- </員工信息>
- </學校信息>
2. 一般實體
可在XML元素中加以引用,也可以在DTD中引用,但參數(shù)實體只能在DTD中引用,并且通常情況下只能在外部DTD文檔中引用。
3. 對比升華
參數(shù)實體與一般實體的區(qū)別如下:
(l)在定義參數(shù)實體時,實體名前必須加一個“%”號。
(2)參數(shù)實體引用以“%”開始,而不是一般實體引用的“&”。
(3)參數(shù)實體的內(nèi)容不僅可以包含文本,還可以包含標記。
(4)參數(shù)實體只能應用于DTD,而不能在文檔本體中引用。即參數(shù)實體只能用來構(gòu)成DTD的內(nèi)容,而不能構(gòu)成文檔內(nèi)容。
(5)參數(shù)實體只能在外部DTD文檔中使用,無法應用于內(nèi)部DTD。
外部參數(shù)實體與外部一般實體的區(qū)別如下:
(1)外部參數(shù)實體應用于獨立的DTD文檔,外部一般實體應用于XML文檔。
(2)外部參數(shù)實體應用于將多個獨立的DTD文檔組合為一個大的DTD文檔,外部一般實體用于將多個獨立的XML文檔組合成一個大的XML文檔。
四、驗證XML文件的合法性
DTD定義了XML文件的使用格式,它從結(jié)構(gòu)和形式上限制了XML文檔,通過引用DTD可以形成統(tǒng)一的規(guī)范化的XML文檔,另外通過使用實體簡化了DTD和XML文檔的內(nèi)容。使用DTD驗證的XML文檔才能稱為規(guī)范化文檔,那如何驗證所寫的XML文檔是否符合DTD的規(guī)范呢。通過如下的代碼串:
- 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和規(guī)范DTD包含在jar中
- try{
- DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance(); //創(chuàng)建一個文檔構(gòu)造工廠
- dbf.setValidating(true);
- DocumentBuilder builder=dbf.newDocumentBuilder();
- builder.parse(new InputSource("xml-2-2.xml")); //需要驗證的XML名稱
- }catch(Exception e){
- e.printStackTrace();
- }
- }
- }
上面代碼中的類和結(jié)構(gòu)主要完成了XML文檔的解析,并且在解析之前驗證當前XML文件是否符合某個DTD的定義。在上面的代碼運行前需要將需要驗證的XML和提供規(guī)范化的DTD文檔引入到當前ValidateDTD項目中,后運行上面的代碼實例,該項目會在項目文件中自動查找規(guī)范的DTD,然后驗證xml文件。
五、結(jié)語
至此,有關(guān)文件定義格式的內(nèi)容已經(jīng)基本上討論了一遍,從最初的元素聲明到復雜多變的實體類型,DTD的引入無疑為XML的使用指定了一個統(tǒng)一的標準,這種標準是由提供方規(guī)定好,使用方遵守的一種規(guī)則,并在最后討論了如何驗證引用DTD的XML合法與否。另外描述XML文檔結(jié)構(gòu)的不僅僅只有DTD,DTD是一種早期的定義格式,它有很多缺點,如不支持數(shù)據(jù)類型,不易于擴展等,為了避免這種缺點后來又引入了Schema,它是DTD的繼任者,下篇博客將著重討論Schema。
相關(guān)文章
- 這篇文章主要介紹了XML中的DTD文檔類型定義,是XML入門學習中的基礎知識,需要的朋友可以參考下2016-02-15
WAP教程(10):WML參考手冊、WML實例和WML DTD-XML/XSLT-網(wǎng)頁制作-網(wǎng)頁教
WAP 協(xié)議用于在無線客戶端(比如移動電話)上展示因特網(wǎng)內(nèi)容。 WAP 協(xié)議用于在無線客戶端(比如移動電話)上展示因特網(wǎng)內(nèi)容。 Deck / Card 元2009-04-02XML入門教程:文檔類型聲明-XML/XSLT-網(wǎng)頁制作-網(wǎng)頁教學網(wǎng)
要使用DTD進行有效性檢驗,就要使用文檔類型定義聲明指定DTD。文檔類型聲明位于XML聲明之后,根元素之前。如果dtd文檔位于本機,可用路徑名直接指出dtd文檔的位置。2009-04-02Trillian XML解析器DTD文件緩沖區(qū)溢出漏洞
受影響系統(tǒng): Cerulean Studios Trillian 3.1.9.0 描述: -------------------------------------------------------------------------------- BUGTRAQ ID: 28742008-10-08