DTD約束簡介

概述

經(jīng)過之前對XML的使用我們發(fā)現(xiàn)只要遵守XML的語法規(guī)定,編寫一個結(jié)構(gòu)良好的XML還是很輕松的,通過引入命名空間也可以為文檔中的不同元素進行分組。但是我們之前所做的操作全都是對文檔結(jié)構(gòu)的要求,而沒有在語法語義上對文檔進行約束。

比如我們有這樣一個文檔,文檔中保存學(xué)生信息:

<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的順序出現(xiàn),并且在student標簽中不能出現(xiàn)其他子標簽。但是以現(xiàn)在的情況看,即使我們不按照這個順序?qū)?,或者student標簽中還出現(xiàn)了其他標簽,解析器都不會認為文檔是錯的,因為我們并沒有對文檔進行語法上的約束。

在標記語言里,語法檢查是非常普遍的。一個XML文檔的有效是指XML文檔內(nèi)容符合元素、屬性和其他文檔內(nèi)容的定義。利用專用的文檔類型定義(Document?Type Definitions , DTD)和專用的解析器,可以驗證一個XML文檔的內(nèi)容是否有效。

通過DTD可以比較輕松的對XML文檔中的內(nèi)容的語法語義進行約束。并且可以通過解析器對XML文檔是否符合DTD的語法進行驗證,這里我們使用的Eclipse內(nèi)置的XML編輯器。接下來我們就需要學(xué)習(xí)如何使用DTD對XML文檔進行約束。

先看看效果

在學(xué)習(xí)DTD之前我們現(xiàn)在看一個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>

這樣一個文檔我們上邊寫的聲明就是對當(dāng)前文檔創(chuàng)建的一個DTD約束,這里我們的age標簽寫到了gender的下邊實際上是不符合我們的語法規(guī)范的,如果沒有DTD約束編輯器不會出現(xiàn)任何錯誤,但是當(dāng)我們在文檔中添加了一個DTD約束以后Eclipse會立即在文檔中報出錯誤,如下:

這是Eclipse中截圖,圖中我畫紅圈的部分student標簽下邊多了一行紅色的波浪線,這就代表我們的文檔不符合DTD的約束。除了Eclipse自動給出提示以為,我們還可以在文檔中點擊右鍵選中Validate動對文檔進行檢查。

驗證完畢后,Eclipse會在錯誤的行號做出標記

當(dāng)將鼠標放到錯誤標記處還會有關(guān)于錯誤信息的具體描述:

這里的提示的錯誤意思是student標簽中結(jié)構(gòu)必須滿足name、age、gender、address的順序,而我們這里gender跑到了age的前邊,不符合文檔中DTD的定義。

我們會發(fā)現(xiàn)這里XML文檔實際上比之前的多了一部分內(nèi)容:

<!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?后邊緊跟的是當(dāng)前文檔的根標簽名。XML中規(guī)定的,聲明元素必須以!號開頭。聲明元素時DTD的一部分,它不允許出現(xiàn)在XML的主體內(nèi)容里。

文檔類型聲明后邊的是DTD定義的主體。在主體我們聲明元素、屬性、實體和注釋。

<!ELEMENT?students?(student)*>

<!ELEMENT?student?(name?,?age?,?gender?,?address)>

<!ATTLIST?student?id CDATA?#REQUIRED>

這里我們聲明了兩個元素和一個屬性,它對當(dāng)前文檔中的內(nèi)容做了一個約束,與DOCTYPE一樣元素、屬性等聲明的第一個字符必須是!號