XML配置DTD約束檔案
DTD是Document Type Definition(文件型別定義)的縮寫。它通過定義元素、屬性、標記以及文件中的實體及其相互關係等規則來保證XML文件的合法性。
1.DTD的宣告方式分為內部宣告與外部宣告
內部宣告的格式是:
<!DOCTYPE 根元素 [ <!ELEMENT 根元素 (元素1,元素2)> <!ELEMENT 元素1 (#PCDATA)> <!ELEMENT 元素2 (#PCDATA)> ]>
外部宣告的格式分兩種,對應的關鍵字為”SYSTEM”與”PUBLIC”
<!DOCTYPE 根元素 SYSTEM "外部DTD檔案"> <!-- 這裡的外部DTD檔案,若不指明 絕對路徑,則必須是和xml檔案在同一目錄,否則無效 -->
“PUBLIC”宣告的DTD檔案通常是一個由權威機構制訂的,提供給特定行業或公眾使用的DTD
<!DOCTYPE 根元素 PUBLIC "外部DTD的標示名" "外部DTD檔案路徑">
2.元素型別宣告
<!ELEMENT 元素名 元素內容描述>
DTD中使用的元素內容型別有:EMPTY、ANY、Mixed、Elements
EMPTY是指元素不能有任何的內容,但可以有屬性:
<!-- DTD宣告部分 --><!ELEMENT 元素1 EMPTY> <!ATTLIST 元素1 性別 (男|女) "男"> <!-- XML檔案部分 --> <元素1 性別="女" /> <!-- 這裡若是以<元素1></元素1>的形式出現,即使裡面沒有任何資料,也會產生錯誤 -->
ANY說明元素可以有任何型別的子元素,也可以是純文字,還可以為空
<!ELEMENT 元素2 ANY>
這裡需要特別注意的是,雖然用ANY定義的元素可以包含其它元素,但必須遵循XML檔案的”有效的”原則,即XML檔案規定檔案中所使用的任何元素都必須在DTD中給出定義。
看下面這段非法的檔案:
<?xml version="1.0" encoding="gb2312"?> <!DOCTYPE 圖書資訊 [ <!ELEMENT 圖書資訊 ANY> ]> <圖書資訊> <書名>新概念英語</書名> </圖書資訊>
編譯器會提示這樣一條錯誤資訊:
“This file is not valid: Element ‘書名’ has not been declared.”
就是提示”書名”這個元素沒有經過定義,要糾正這個錯誤,只要在DTD定義部分加入定義語句”<!ELEMENT 書名 (#PCDATA)>”就可以了。
Mixed允許混合內容使得字元資料和其他元素能在元素內共存,它並不是以關鍵字的形式存在的:
<!ELEMENT 元素3 (#PCDATA|子元素1|子元素2)>
<?xml version="1.0" encoding="gb2312"?> <!DOCTYPE 圖書資訊 [ <!ELEMENT 圖書資訊 (#PCDATA|書名|價格)*> <!ELEMENT 書名 (#PCDATA)> <!ELEMENT 價格 (#PCDATA)> ]> <圖書資訊> 今日新到圖書: <書名> XML實用教程 </書名> <價格> ¥26.00 </價格> </圖書資訊>
Elements規定特定子元素必須按規則與順序出現,子元素後可以用各種元字元來說明出現的次數。
<!ELEMENT 元素4 (子元素1,子元素2,子元素3)>
可能出現的元字元:
元字元 | 含義 |
+ | 出現1次或多次 |
* | 出現0次或多次 |
? | 出現0次或1次 |
無符號 | 只能出現1次 |
下面的例子中,”IT求職”的各項子元素必須按順序和元字元說明的次數來出現:
<?xml version="1.0" encoding="gb2312"?> <!DOCTYPE IT求職 [ <!ELEMENT IT求職 (招聘資訊)+> <!ELEMENT 招聘資訊 (公司名,招聘職位+,公司網站?,聯絡方式*)> <!ELEMENT 公司名 (#PCDATA)> <!ELEMENT 招聘職位 (#PCDATA)> <!ELEMENT 公司網站 (#PCDATA)> <!ELEMENT 聯絡方式 (#PCDATA)> ]> <IT求職> <招聘資訊> <公司名>中興通訊</公司名> <!--這裡招聘職位出現了2次--> <招聘職位>1.Java高階工程師</招聘職位> <招聘職位>2.C++高階工程師</招聘職位> <!--這裡公司網站出現了1次--> <公司網站>http://www.zte.com.cn/</公司網站> <!--這裡聯絡方式出現了2次--> <聯絡方式>地址:深圳市南山區高新技術產業園科技南路中興通訊大廈</聯絡方式> <聯絡方式>電話:0755-26770000</聯絡方式> </招聘資訊> <招聘資訊> <公司名> 阿里巴巴 </公司名> <!--這裡招聘職位出現了1次--> <招聘職位>軟體測試工程師</招聘職位> <!--沒有出現公司網站--> <!--沒有出現聯絡方式--> </招聘資訊> </IT求職>
3.定義有效的元素屬性
在DTD中定義屬性時,我們採用下面的格式:
<!ATTLIST 元素名 屬性名 (屬性值 屬性型別 預設值)*>
例如:
<!ATTLIST 作者 姓名 CDATA #REQUIRED 性別 (男|女) "男" 聯絡方式 CDATA #IMPLIED >
根據XML檔案是否必須為一個屬性提供取值,屬性的預設值又可以分為以下四類:
- 必須賦值的屬性REQUIRED
- 屬性值可有可無的屬性IMPLIED
- 固定取值的屬性FIXED
- 自定義的預設值
下面用一個例子來說明這四類預設屬性:
<?xml version="1.0" encoding="gb2312"?> <!DOCTYPE 圖書資訊 [ <!ELEMENT 圖書資訊 (書名,作者,價格)*> <!ELEMENT 書名 (#PCDATA)> <!ELEMENT 作者 (#PCDATA)> <!ELEMENT 價格 (#PCDATA)> <!ATTLIST 作者 姓名 CDATA #REQUIRED 性別 (男|女) "男" 聯絡方式 CDATA #IMPLIED 分類 CDATA #FIXED "WEB程式設計技術" > ]> <圖書資訊> <書名>ASP.NET案例開發集錦</書名> <作者 姓名="趙輝、楊麗敏"/> <價格>37.00</價格> <書名>C#高階程式設計</書名> <作者 姓名="wrox" 聯絡方式="http://www.wrox.com"/> <價格>128.00</價格> <書名>HTML XHTML CSS基礎教程(第6版)</書名> <作者 姓名="Elizabeth Castro" 分類="WEB程式設計技術"/> <價格>50.00</價格> <書名>ASP.NET 2.0 應用開發技術</書名> <作者 姓名="孟憲會(net_lover)" 性別="男"/> <價格>59.00</價格> </圖書資訊>
上面的例子為子元素”作者”定義了4個屬性,分別是”姓名”(#REQUIRED型別)、”聯絡方式”(#IMPLIED型別)、”分類”(#FIXED型別)、”性別”(自定義型別)。
在第一本書《ASP.NET案例開發集錦》中,只出現了”姓名”,但其實際屬性有兩項,還有一個是#FIXED型別的”分類”。
在第二本書《C#高階程式設計》中,除了必須出現的”姓名”,還出現了#IMPLIED型別的”聯絡方式”,算上#FIXED型別的”分類”,實際屬性有三項。
在第三本書《HTML XHTML CSS基礎教程(第6版》中,除了”姓名”,還顯式出現了#FIXED型別的”分類”,它的實際屬性與第一本書相同。
在第四本書《ASP.NET 2.0 應用開發技術》中,”姓名”後出現了自定義屬性”性別”,它只有兩個值”男”和”女”,預設為”男”,出現其他值將顯示錯誤。
屬性型別分為以下10種:
- CDATA
- Enumerated
- ID
- IDREF
- IDREFS
- ENTITY
- ENTITIES
- NMTOKEN
- NMTOKENS
- NOTATION
CDATA和Enumerated(列舉型別)在上面的例子中已有所說明,主要研究一下其他的屬性型別:
ID屬性型別
每個ID型別的屬性必須有不同的值,大多數ID屬性使用#REQUIRED,且ID型別和#FIXED不相容.屬性不能既是固定的,又有ID型別.這是因為#FIXED屬性只能有一個值。
看下面的錯誤示例:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE 職員資訊 [ <!ELEMENT 職員資訊 (普通職員)*> <!ELEMENT 普通職員 (#PCDATA)> <!ATTLIST 普通職員 編號 ID #REQUIRED> ]> <職員資訊> <普通職員 編號="8">張三</普通職員> <普通職員 編號="E8">李四</普通職員> <普通職員 編號="E8">王五</普通職員> </職員資訊>
上面的檔案有2個錯誤,一個是 編號=”8” 這裡,ID屬性不能是純數字,必須要以字母或下劃線開頭;另一個是出現了兩個”E8”的編號,這與ID屬性的定義是相違背的。
IDREF屬性型別
具有IDREF型別的屬性的值是文件中另一個元素的ID。
<?xml version="1.0" encoding="gb2312"?> <!DOCTYPE 武將資訊 [ <!ELEMENT 武將資訊 (姓名)*> <!ELEMENT 姓名 (#PCDATA)> <!ATTLIST 姓名 編號 ID #REQUIRED> <!ATTLIST 姓名 君主 IDREF #IMPLIED> ]> <武將資訊> <姓名 編號="P1">曹操</姓名> <姓名 編號="P2">劉備</姓名> <姓名 編號="P3">孫權</姓名> <姓名 編號="P4" 君主="P1">許楮</姓名> <姓名 編號="P5" 君主="P2">關羽</姓名> <姓名 編號="P6" 君主="P3">甘寧</姓名> </武將資訊>
上面的例子中,由於”君主”屬性指定為IDREF,所以其內容必須為ID屬性的”編號”裡的值。
IDREFS屬性型別
IDREF屬性的值只能為一個.但如果要描述一對多的關係,例如三國裡所有人都只有一個君主,但卻會有多個子女.這時候就要用到IDREFS屬性了
<?xml version="1.0" encoding="gb2312"?> <!DOCTYPE 武將資訊 [ <!ELEMENT 武將資訊 (姓名)*> <!ELEMENT 姓名 (#PCDATA)> <!ATTLIST 姓名 編號 ID #REQUIRED> <!ATTLIST 姓名 子女 IDREFS #IMPLIED> ]> <武將資訊> <姓名 編號="C1">關平</姓名> <姓名 編號="C2">關興</姓名> <姓名 編號="C3">孫策</姓名> <姓名 編號="C4">孫權</姓名> <姓名 編號="C5">孫尚香</姓名> <姓名 編號="F1" 子女="C1 C2">關羽</姓名> <姓名 編號="F2" 子女="C3 C4 C5">孫堅</姓名> </武將資訊>
ENTITY屬性型別
ENTITY型別屬性使人們能把外部二進位制資料(即外部未解析的普通實體)連結到文件,ENTITY屬性的典型例子是一幅影象,該影象由來自與另一個URL的二進位制資料組成
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE 影象 [ <!ELEMENT 影象 EMPTY> <!ATTLIST 影象 來源 ENTITY #REQUIRED> <!ENTITY Logo SYSTEM "logo.gif"> ]> <影象 來源="&Logo;"/>
ENTITIES屬性型別
ENTITIES是ENTITY的複數形式.ENTITIES型別的屬性值由空格分隔多個未解析的實體名稱組成.每個實體名稱引用一個外部的非XML資料來源.這個方法的一個用途是輪流顯示不同圖片的幻燈片,如下所示:
<?xml version="1.0" encoding="gb2312"?> <!DOCTYPE 幻燈片 [ <!ELEMENT 幻燈片 EMPTY> <!ATTLIST 幻燈片 來源 ENTITY #REQUIRED> <!ENTITY PIC1 SYSTEM "picture1.jpg"> <!ENTITY PIC2 SYSTEM "picture2.gif"> <!ENTITY PIC3 SYSTEM "picture3.jpg"> ]> <幻燈片 來源="&PIC1; &PIC2; &PIC3;"/>
NMTOKEN屬性型別
NMTOKEN屬性型別限制有效的XML名稱記號的屬性值,除了空格,任何字元都被認為是有效的。
<?xml version="1.0" encoding="gb2312"?> <!DOCTYPE 客戶資料 [ <!ELEMENT 客戶資料 (聯絡地址)*> <!ELEMENT 聯絡地址 (#PCDATA)> <!ATTLIST 聯絡地址 城市 NMTOKEN #REQUIRED> ]> <客戶資料> <聯絡地址 城市="London">張三</聯絡地址> <聯絡地址 城市="010北京">李四</聯絡地址> <聯絡地址 城市="New York">王五</聯絡地址> </客戶資料>
上面的例子,”010北京”雖然是以數字開頭,但由於是NMTOKEN型別,所以它也是合法的.但最後的”New York”為非法,因為NMTOKEN型別限制了空格的使用。
NMTOKENS屬性型別
NMTOKENS是NMTOKEN的複數形式,它允許出現一組值,同NMTOKEN的規則一樣,不限制符號的使用。它可以出現空格,但空格的作用是分割不同的記號
<?xml version="1.0" encoding="gb2312"?> <!DOCTYPE 註冊資訊 [ <!ELEMENT 註冊資訊 (使用者資料)*> <!ELEMENT 使用者資料 (#PCDATA)> <!ATTLIST 使用者資料 愛好 NMTOKENS #REQUIRED> ]> <註冊資訊> <使用者資料 愛好="足球 籃球">張三</使用者資料> <使用者資料 愛好="唱歌 跳舞">李四</使用者資料> <使用者資料 愛好="Play the Piano">王五</使用者資料> </註冊資訊>
上面的例子雖然沒有錯誤,但最後的”play the piano”本來想表達的意思是”彈鋼琴”,但由於NMTOKENS的限制,被拆解成了”play”、”the”、”Piano”三個部分。所以在遇到NMTOKENS型別屬性時,要特別注意空格的使用。
NMTOKENS屬性型別
NOTATION對於使用非XML格式的資料非常有用。現實世界中存在很多無法或不易用XML格式組織的資料,例如圖象、聲音、影象等等。對於這些資料,XML應用程式常常並不提供直接的應用支援。通過為它們設定NOTATION型別的屬性,可以嚮應用程式指定一個外部的處理程式
<?xml version="1.0" encoding="gb2312"?> <!DOCTYPE 檔案 [ <!ELEMENT 檔案 (聲音檔案)> <!ELEMENT 聲音檔案 (#PCDATA)> <!NOTATION MP SYSTEM "mplayer32.exe"> <!NOTATION ST SYSTEM "soundtool"> <!NOTATION SM SYSTEM "Sound Machine"> <!ATTLIST 聲音檔案 處理程式 NOTATION (MP|SM|ST) #REQUIRED> ]> <檔案> <聲音檔案 處理程式="MP">Lydia.mp3</聲音檔案> </檔案>