一、何為DTD
DTD的全稱為Document Type Definition,是一種文件定義格式,它規定了XML文件結構為XML文件提供了語法與規則。在DTD中定義XML文件的結構,然後按照DTD的聲明來編寫XML文件。它就好像編程語言中的函數定義,在使用函數時要根據函數聲明的格式進行來引用。
二、DTD詳解
1、實例詳解
XML/HTML Code復制內容到剪貼板
- <?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)元素:
XML/HTML Code復制內容到剪貼板
- <!ELEMENT element_name element_definition>
(2)屬性列表:
XML/HTML Code復制內容到剪貼板
- <!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/HTML Code復制內容到剪貼板
- <?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/HTML Code復制內容到剪貼板
- <?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”的聲明
XML/HTML Code復制內容到剪貼板
- <!-- 聲明外部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/HTML Code復制內容到剪貼板
- <?xml version="1.0" encoding='utf-8'?>
- <影評>
- 這些影評都是由XXX公司出品,值得觀看!
- </影評>
清單3:使用dtd的xml文件中的內容。
XML/HTML Code復制內容到剪貼板
- <?xml version="1.0" encoding='utf-8'?>
- <影評>
- 這些影評都是由XXX公司出品,值得觀看!
- </影評>
清單3:使用dtd的xml文件中的內容。
XML/HTML Code復制內容到剪貼板
- <?xml version="1.0" encoding='utf-8'?>
- <!DOCTYPE 影片目錄 SYSTEM "./2.dtd" >
- <影片目錄>
- <影片 類別="武俠" 年份="2008">
- <片名>十面埋伏</片名>
- <主演>劉德華、金城武、章子怡</主演>
- <導演>張藝謀</導演>
- <簡介>&十面埋伏;</簡介>
- </影片>
- <影片 類別="武俠" 年份="2006">
- <片名>霍元甲</片名>
- <主演>李連傑</主演>
- <導演>於仁泰</導演>
- <簡介>&霍元甲;</簡介>
- </影片>
- &filmcomment;
- </影片目錄>
清單4:使用IE8打開清單3後的內容
XML/HTML Code復制內容到剪貼板
- <?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/HTML Code復制內容到剪貼板
- <?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/HTML Code復制內容到剪貼板
- <?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的規范呢。通過如下的代碼串:
Java Code復制內容到剪貼板
- 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。