DTD約束簡介
概述
經過之前對XML的使用我們發現只要遵守XML的語法規定,編寫一個結構良好的XML還是很輕松的,通過引入命名空間也可以為文檔中的不同元素進行分組。但是我們之前所做的操作全都是對文檔結構的要求,而沒有在語法語義上對文檔進行約束。
比如我們有這樣一個文檔,文檔中保存學生信息:
<students> <student?id="1"> <name>孫悟空</name> <age>18</age> <gender>男</gender> <address>花果山</address> </student> </students> |
這個文檔時比較簡單的文檔,students根標簽,根標簽中有一個student子標簽。student子標簽中又有三個子標簽name、age、gender、address。在我們這個文檔中我們要求student中的四個子標簽按照name、age、gender、address的順序出現,并且在student標簽中不能出現其他子標簽。但是以現在的情況看,即使我們不按照這個順序寫,或者student標簽中還出現了其他標簽,解析器都不會認為文檔是錯的,因為我們并沒有對文檔進行語法上的約束。
在標記語言里,語法檢查是非常普遍的。一個XML文檔的有效是指XML文檔內容符合元素、屬性和其他文檔內容的定義。利用專用的文檔類型定義(Document?Type Definitions , DTD)和專用的解析器,可以驗證一個XML文檔的內容是否有效。
通過DTD可以比較輕松的對XML文檔中的內容的語法語義進行約束。并且可以通過解析器對XML文檔是否符合DTD的語法進行驗證,這里我們使用的Eclipse內置的XML編輯器。接下來我們就需要學習如何使用DTD對XML文檔進行約束。
先看看效果
在學習DTD之前我們現在看一個DTD約束使用的例子,這里我們使用Eclipse作為編輯器,Eclipse可以自動為XML語法進行驗證,我們先看看文檔的樣子:
<?xml?version="1.0"?encoding="UTF-8"?> <!DOCTYPE?students[ <!ELEMENT?students?(student)*> <!ELEMENT?student?(name?,?age?,?gender?,?address)> <!ATTLIST?student?id CDATA?#REQUIRED> ]> <students> <student?id="1"> <name>孫悟空</name> <gender>男</gender> <age>18</age> <address>花果山</address> </student> </students> |
這樣一個文檔我們上邊寫的聲明就是對當前文檔創建的一個DTD約束,這里我們的age標簽寫到了gender的下邊實際上是不符合我們的語法規范的,如果沒有DTD約束編輯器不會出現任何錯誤,但是當我們在文檔中添加了一個DTD約束以后Eclipse會立即在文檔中報出錯誤,如下:
這是Eclipse中截圖,圖中我畫紅圈的部分student標簽下邊多了一行紅色的波浪線,這就代表我們的文檔不符合DTD的約束。除了Eclipse自動給出提示以為,我們還可以在文檔中點擊右鍵選中Validate動對文檔進行檢查。
驗證完畢后,Eclipse會在錯誤的行號做出標記
當將鼠標放到錯誤標記處還會有關于錯誤信息的具體描述:
這里的提示的錯誤意思是student標簽中結構必須滿足name、age、gender、address的順序,而我們這里gender跑到了age的前邊,不符合文檔中DTD的定義。
我們會發現這里XML文檔實際上比之前的多了一部分內容:
<!DOCTYPE?students[ <!ELEMENT?students?(student)*> <!ELEMENT?student?(name?,?age?,?gender?,?address)> <!ATTLIST?student?id CDATA?#REQUIRED> ]> |
!DOCTYPE是一個文檔類型聲明,它告訴解析器,本XML文檔需要與一個DTD文件一起使用。在XML文檔中如果使用DTD文件,必須將!DOCTYPE放在文檔的開頭(可以是XML聲明后邊),不可以放在其他位置。!DOCTYPE開頭必須是!。!DOCTYPE?后邊緊跟的是當前文檔的根標簽名。XML中規定的,聲明元素必須以!號開頭。聲明元素時DTD的一部分,它不允許出現在XML的主體內容里。
文檔類型聲明后邊的是DTD定義的主體。在主體我們聲明元素、屬性、實體和注釋。
<!ELEMENT?students?(student)*> <!ELEMENT?student?(name?,?age?,?gender?,?address)> <!ATTLIST?student?id CDATA?#REQUIRED> |
這里我們聲明了兩個元素和一個屬性,它對當前文檔中的內容做了一個約束,與DOCTYPE一樣元素、屬性等聲明的第一個字符必須是!號