1. 程式人生 > >在XML中使用DTD

在XML中使用DTD

使用DTD知識總結

DTD介紹

  • DTD( Document Type Definition)文件型別定義。在XML標準中,描述瞭如何建立DTD,以及如何將它與根據它的規則所編寫的XML文件相關聯,並且還定義了XML處理器應該如何對DTD進行處理,有了DTD就可以檢測XML文件的結構是否正確。
  • DTD在實際應用中的作用主要包括:
    • 可以驗證XML文件資料的有效性
    • 可以為某類XML文件提供統一的格式和相同的結構
    • 可以保證在一定範圍內,XML文件資料的交流和共享
    • 一個程式設計人員根據DTD就能夠知道對應的XML文件邏輯結構,從而編寫出相應的處理應用程式
  • 第一個DTD例子:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE 根元素名稱 [
	<!ELEMENT 根元素名稱(第一個子元素, 第二個子元素)>
	<!ELEMENT 第一個子元素(#PCDATA)>
	<!ELEMENT 第二個子元素(#PCDATA)>
	<!ATTLIST 第一個子元素 屬性一 CDATA #REQUIRED>
]>
<根元素名稱>
	<第一個子元素 屬性一="任意內容">
		文字內容1
	</第一個子元素>
	<第二個子元素>
		文字內容1
	</第二個子元素>
</根元素名稱>

DTD的基本語法

  1. DTD內部可以包含下列語句:
  • 元素型別宣告語句<!ELEMENT ......>
  • 屬性列表宣告語句<!ATTLIST ......>
  • 實體宣告語句<!ENTITY .......>
  • 符號宣告語句<!NOTATION ......>
  • 註釋語句
  1. 一個DTA即可以是獨立的文件,該文件的副檔名為.dtd。DTD也可以存在於文件內部,如果存在於XML文件內部,則DTD的內容放置於
  2. 例如:demodtd.dtd如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!-- root元素中包含了兩個子元素 --!>
<!ELEMENT root (sub1, sub2)>
<!ELEMENT sub1(#PCDATA)>
<!ELEMENT sub2(#PCDATA)>
<!ATTLIST root param1 NOTATION(Jpeg | Png) # REQUIRED
				param2 CDATA # IMPLIED>
<!ENTITY NAME "ENTITY VALUE">
<!NOTATION Jpeg SYSTEM "Image/jpeg">
<!NOTATION Png SYSTEM "Image/png">

引入在XML文件中,程式碼如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYE root SYSTEM "demodtd.dtd">
<root param1 = "Jpeg">
<sub1>&NAME;</sub1>
<sub2>any word </sub2>
</root>

直接內置於XML文件中時,程式碼如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root[
<!--root元素中包含了2個子元素-->
<!ELEMENT root (sub1,sub2)>
<!ELEMENT sub1 (#PCDATA)>
<!ELEMENT sub2 (#PCDATA)>
<!ATTLIST root param1 CDATA #REQUIRED
			   param2 CDATA #IMPLIED>
<!ENTITY NAME1 "ENTITY VALUE">
<!ENTITY PIC SYSTEM "Sunset.jpg" NDATA jpr>
<!NOTATION jpr SYSTEM "mspaint.exe">
]>
<root param1="PIC">
	<sub1>&NAME1;</sub1>
	<sub2>any word</sub2>
</root>

引入DTD的方式

  1. 外部DTD
    外部DTD的引用須事先已有一個dtd檔案,將DTD的約束寫到檔案中,然後在XML文件中按以下語法格式新增:
    <!DOCTYPE (根元素名稱) SYSTEM "外部DTD的URL地址">
    SYSTEM關鍵字表示文件使用的是私有DTD檔案,“外部DTD檔案的URI”可以是相對URI或者絕對URI,相對URI是相對於文件型別宣告所在文件的位置。“外部DTD檔案的URI”這部分也被稱為系統識別符號(system identifier).
  2. 內部DTD
    使用DTD的最簡單的方式,內部DTD就是指將語義約束與XML文件的內容放在同一個XML文件中。緊跟在XML宣告和處理指令之後,以<!DOCTYPE[開始,以]>結束語法格式如下:
    <!DOCTYPE 根元素名稱 [ 元素描述 ]>
  3. 公用DTD
    公用DTD與外部DTD類似,但是該DTD引用公用的DTD的語法格式如下:
    <!DOCTYPE (根元素名稱) PUBLIC "DTD的標識名" "公用DTD的URL地址">
    公共DTD名稱要遵循一些約定。如果一項DTD是ISO標準,它的名字要以字串“ISO”開始,如果是一個非ISO的標準組織批准的DTD,它的名字以“+”開始。如果不是標準組織批准的DTD,它的名字以連字元“-”開始。這些開始字元或字串後面接//和DTD所有者的名字,之後是另一個雙斜槓和DTD描述的文件型別,接著又是一個雙斜槓後接ISO 639語言識別符號,如EN表示英語,ZH表示中文。
    例如:
  • 自定義的dtd
    //tanglin //DTD STUDENT1.0/ZH
    <!DOCTYPE HR PUBLIC "//tanglin //DTD STUDENT1.0/ZH " "http://city.dlut.edu.cn/xml/dtds/students.dtd">

  • HTML網頁的文件型別宣告
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

DTD中的元素

  1. 元素定義語法
    語法如下所示:
    <!ELEMENT 元素名 元素型別描述>
    語法詳細說明:
  • 元素名:即文件中元素的名稱。
  • 元素型別描述:元素型別描述用於指定元素本身是否為對空元素,如果不為空元素元素的內容包括哪些。
  1. 元素型別
    元素型別具體包括以下5類:
  • 字串型別:即#PCDATA,表示該元素的內容只能是字串。

  • 空元素:EMPTY,表示該元素只能是空元素。

  • 包含子元素:表示該元素內部巢狀其它元素,具體包含子元素可能有:有序子元素、無序互斥子元素、無序組合子元素。子元素出現的次數也會根據實際的定義而不同。

  • 混合型別:即內容中即包括字串型別又包括子元素,但混合型別在實際應用中不建議使用。

  • 任意型別:即ANY,表示該標記對於元素內容沒有限制,該標記的內容可以是字串型別、也可以包含子元素、即包含字串又包括自元素的混合型別、該標記也可以是空元素。在實際應用中儘量避免。

  • 子元素如下:

  1. 有序子元素
    用逗號分隔,表示子元素的出現順序必須與宣告時一致,並且不能被省略。
  2. 無序互斥子元素
    用豎線(|)分隔,表示任選其一,即多個子元素在文件定義中只能出現一個。
  3. 無序組合子元素
    子元素出現頻率可以根據不同的符號進行設定這些符號的含義如表2-2所示:
    子元素出現頻率符號及其含義
    修飾符 含義
    + 一次或多次
    ? 0次或一次
    * 0次或多次
    預設 一次
    這些修飾符可以限制元素出現的次數,也可以結合圓括號( )批量設定
  • 混合型別
    混合型別定義的子元素即可以包含字串又可以包含子元素,其定義方法稍微複雜一些,典型的混合型別定義方法形如<!ELEMENT root (#PCDATA|sub1|sub2)*>。但在實際用該型別使用較少,也不建議使用。
  1. DTD中的屬性
    在DTD中宣告元素屬性的語法:
    <!ATTLIST 元素名稱 [屬性名 屬性型別 [約束] [預設值]]+>
    在一個ATTLIST 中可以定義同一個元素下的一個或多個屬性。如果包含多個屬性宣告,屬性宣告之間使用空格間隔。
  • 元素名稱:屬性所屬的元素名稱
  • 屬性名:屬性名稱
  • 屬性型別:屬性的值型別,
  • 約束:元素對屬性的約束
修飾符 含義
#REQUIRED 表示該屬性是必需的,不能沒有
#IMPLIED 表示該屬性可以有也可以沒有
#FIXED 表示在XML文件中只會給出一個元素屬性所定義的固定值。只有當約束為該值時,才能給出預設值,注意預設值必須給出
  • 定義示例:
<? xml version="1.0" encoding="UTF-8"?>
<! DOCTYPE root[
<!ELEMENT root (#PCDATA)>
<!ATTLIST root reqParam CDATA #REQUIRED>
<!ATTLIST root impParam CDATA #IMPLIED
			fixParam CDATA #FIXED "default value">
]>
<root reqParam = "required value">
</root>

屬性型別

  1. DTD中的ENTITY實體
  • ENTITY 實體,在一個甚至多個XML文件中頻繁使用某一條資料,我們可以預先定義一個這條資料的“別名”,即一個ENTITY,然後在這些文件中需要該資料的地方呼叫它。
  • 實體分類關係圖
    實體分類關係圖
    1. 通用內部解析實體
      內部實體是最簡單的一種實體,該實體的內容為字串的文字內容。所有的內部實體都是解析實體。內部實體的語法格式如下:<!ENTITY 實體名稱 "實體內容"> 例如:
      <!ENTITY one "one">
      <!ENTITY two "&one; I am two">

      • 實體名稱:實體名稱由DTD程式設計師自己定義,但必須滿足唯一性,即不能重名。同時滿足XML的命名規範。
      • 實體內容:所需要表達的文字內容。
    2. 通用外部解析實體
      定義外部解析實體的語法如下:
      <!ENTITY 實體名稱 SYSTEM|PUBLIC ["公共實體識別符號"] "URI/URL">

      • URI/URL:所引用的外部檔案的路徑地址,被引用的外部檔案必須是可以被解析的,副檔名沒有限制。
      • 實體為PUBLIC時才會有相應的“公共實體識別符號” ,如果為SYSTEM則沒有“公共實體識別符號”.
        例項如下:
        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE aa[
        	<!ELEMENT aa (#PCDATA)>
        	<!ELEMENT copyright SYSTEM "outer.txt">
        ]>
        <aa>&copyright; </aa>
        
    3. 通用外部未解析實體:
      <!ENTITY 實體名稱 SYSTEM “URL/URL” NDATA 標記名>
      URI/URL:所引用的外部檔案的路徑地址
      標記名:被定義的符號的名稱。
      例項程式碼:
      <!ENTITY PICTURE SYSTEM 'pic.jpg' NDATA msp>

    4. 引數內部解析實體
      引數實體和普通實體只能在XML文件中引用,如果需要在DTD中使用實體則必須使用引數實體
      宣告引數內部解析實體的語法:
      <!ENTITY % 引數實體名稱 "實體內容">
      引數實體名稱:實體名稱由DTD程式設計師自己定義,但必須滿足唯一性,即不能重名。同時滿足XML的命名規範。
      實體內容:所需要表達的文字內容。

    5. 引數外部解析實體
      宣告引數外部解析實體的語法:
      <!ENTITY % 引數實體名稱 SYSTEM “URL/URL”>
      URI/URL:所引用的外部檔案的路徑地址
      引用引數實體的語法:
      %引數實體名稱;

  1. DTD符號
    普通符號的語法格式:
    <!NOTATION 符號名稱 SYSTEM | PUBLIC ["公共符號識別符號"] "URI\URL">
  • 符號名稱:名稱由DTD程式設計師自己定義,但必須滿足唯一性,即不能重名。同時滿足XML的命名規範
  • URI\URL:外部來處理這些未解析資料的程式路徑
  • 符號為PUBLIC時才會有相應的“公共符號識別符號” ,如果為SYSTEM則沒有“公共符號識別符號”

DTD定義格式缺點

  • DTD本身是基於正則表示式的,描述能力相對較弱。
  • DTD不支援資料型別,對資料的約束不夠準確。
  • DTD約束能力不足,無法對語義作出更精細的語義限制。
  • DTD的結構不夠好,可重用性較差。