(本系列文章是我學(xué)習(xí)的過程中,整理出來的筆記,如有錯(cuò)漏,看官請(qǐng)一定不吝回復(fù),讓我能認(rèn)識(shí)自己的不足,并改進(jìn)錯(cuò)誤。非常感謝!)
本章大概內(nèi)容:
1、為什么需要DTD
2、XML文檔如何使用DTD
    1)內(nèi)部定義DTD
    2)關(guān)聯(lián)外部DTD
3、DTD的結(jié)構(gòu)
    1)元素類型聲明
    2)屬性列表聲明
    3)實(shí)體聲明
    4)記號(hào)聲明

    對(duì)于一個(gè)格式良好的XML文檔,我們只能保證這個(gè)文檔的格式符合XML規(guī)范,但是元素與元素的關(guān)系,元素與屬性的關(guān)系,屬性的取值,我們就無法保證了。對(duì)于一個(gè)格式良好的文檔,如果只是在有限的應(yīng)用中使用,或者是用于存儲(chǔ)和傳輸,那么它也能能夠很好的滿足我們的應(yīng)用,但是如果要其它的用戶了解你所寫的XML文檔,或者與其它應(yīng)用進(jìn)行數(shù)據(jù)的交換,那么就有必要提供一種機(jī)制,來保證我們寫的XML文檔和別人所寫的XML文檔在結(jié)構(gòu)上是相同的,元素與元素之間的關(guān)系是正確的,屬性的取值也是符合要求的,那么這種機(jī)制在XML規(guī)范中已經(jīng)為我們提供了,那就是前一章中介紹過的文檔類型聲明中提到的DTD。

DTD(Document Type Definition),文檔類型定義。

    在XML標(biāo)準(zhǔn)中,描述了如何創(chuàng)建DTD,以及如何將它與根據(jù)它的規(guī)范所編寫的XML文檔相關(guān)聯(lián),并且還定義了XML處理器應(yīng)該如何對(duì)DTD進(jìn)行處理。有了DTD就可以檢測(cè)XML文檔的結(jié)構(gòu)是否正確。
DTD為XML文檔的編寫者與處理者提供了共同遵循的原則,使得與文檔相關(guān)的各種工作有了統(tǒng)一的標(biāo)準(zhǔn)。

如何在XML文檔中引入DTD

通過在XML文檔中包含文檔類型聲明,來建立當(dāng)前文檔和DTD的關(guān)聯(lián)。當(dāng)進(jìn)行有效性驗(yàn)證的XML處理器讀到該聲明時(shí),它獲取DTD,并根據(jù)其中定義的規(guī)則對(duì)文檔進(jìn)行檢驗(yàn)。文檔類型聲明必須位于XML聲明之后,且在根元素(文檔元素)之前。不過,在XML聲明和文檔類型聲明之間可以插入注釋和處理指令。
我們可以直接在XML文檔中定義DTD,也可以通過URI引用外部的DTD文件,或者同時(shí)采用這兩種方式。
上一章中,已經(jīng)學(xué)習(xí)過如何通過包含文檔類型聲明來建立與DTD的關(guān)聯(lián)。現(xiàn)在來分析一下這兩種包含方式。

在XML文檔內(nèi)部給出DTD的方式:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE OrganizationChart [
    <!ELEMENT OrganizationChart (Name,Office)
>
    
<!ELEMENT Name (#PCDATA)>
    
<!ELEMENT Office (#PCDATA)>
    ]>

<OrganizationChart>
<!--OrganizationChart是該XML文檔的document element-->
    
<Name>Toone,INC.</Name>
    
<Office>zhuhai</Office>
    
<!--因?yàn)镈TD中定義了Name,Office兩個(gè)元素的順序,Office元素不能放在Name元素的前面,否則不是有效的XML文檔-->
</OrganizationChart>
    文檔類型聲明由<!開始,后面緊跟一個(gè)關(guān)鍵字DOCTYPE,然后是文檔根元素的名字,接下來是標(biāo)記聲明塊,標(biāo)記聲明塊放在中括號(hào)[]之間,由一個(gè)或者多個(gè)標(biāo)記聲明構(gòu)成,最后由>結(jié)束。

    在DTD中,所有的關(guān)鍵字都是大寫的。不過,在DTD中定義的元素和屬性的大小寫是可以任意制定的,但是要注意,因?yàn)閄ML文檔是大小寫相關(guān)的,所以一旦給一個(gè)元素命名,那么在整個(gè)文檔中要使用相同的大小寫。例如,organizationchart和OrganizationChart是不同的兩個(gè)元素名。

    在XML文檔中定義DTD,比較直觀,修改也比較方便,而且不用擔(dān)心XML處理器找不到DTD,但是它也有一些缺點(diǎn):

    1、在文檔中定義DTD會(huì)導(dǎo)致文檔本身的長度增加,在傳輸數(shù)據(jù)時(shí),即使不需要驗(yàn)證文檔的有效性,這些聲明也要一起傳輸。

    2、如果多個(gè)XML文檔要共用同一個(gè)DTD,我們就需要在每一個(gè)文檔中加入DTD。


    引進(jìn)外部DTD方式:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE OrganizationChart SYSTEM "dtdTest.dtd" >
<OrganizationChart>
    
<Name>Toone,INC.</Name>
    
<Office>zhuhai</Office>
</OrganizationChart>
    對(duì)應(yīng)DTD內(nèi)容為:
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT OrganizationChart (Name,Office)>
<!ELEMENT Name (#PCDATA)>
<!ELEMENT Office (#PCDATA)>

在文檔類型聲明時(shí),用管間質(zhì)SYSTEM或PUBLIC來指出外部DTD文件的位置,使用SYSTEM關(guān)鍵字的聲明語法如下:

<!DOCTYPE 根元素的名字 SYSTEM "外部DTD文件的URI">

SYSTEM關(guān)鍵字表示文檔使用的是私有的DTD文件,“外部DTD文件的URI”可以是相對(duì)URI或者絕對(duì)URI。例如上面的例子使用的就是相對(duì)URI:

<!DOCTYPE OrganizationChart SYSTEM "dtdTest.dtd" >

使用PUBLIC關(guān)鍵字的聲明語法如下:

<!DOCTYPE 根元素的名字 PUBLIC "DTD的名字" "外部DTD文件的URI">

PUBLIC關(guān)鍵字用于聲明公共的DTD,并且這個(gè)DTD還有一個(gè)名稱,"DTD的名稱"也稱為公共標(biāo)識(shí)符(public identifier)。這個(gè)DTD可以存放在某個(gè)公共的地方,XML處理程序會(huì)根據(jù)名稱按照某種方式去檢索DTD,如果XML處理器不能根據(jù)名稱檢索到DTD,就會(huì)使用"外部DTD文件的URI"來查找該DTD。例如Java web開發(fā)的web.xml中的DTD聲明(版本不同會(huì)稍有不同,我們只關(guān)注它的結(jié)構(gòu)):

<!DOCTYPE web-app PUBLIC '-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN'
'http://java.sun.com/dtd/web-app_2_3.dtd'
>


DTD名稱與XML名稱略有不同,他們只能包含ASCII字母和數(shù)字符號(hào)、空格、回車符、換行符和一些標(biāo)點(diǎn)符號(hào):-'()+,/:=?;!#@*$_%.

公共DTD名稱要遵守一些約定。如果一項(xiàng)DTD是ISO標(biāo)準(zhǔn),它的名稱要以字符串"ISO"開始。如果是一個(gè)非ISO的標(biāo)準(zhǔn)組織批準(zhǔn)的DTD,它的名字以加號(hào)(+)開始。如果不是標(biāo)準(zhǔn)組織批準(zhǔn)的DTD,它的名稱以連字符(-)開始。這些開始字符或字符串后接雙斜杠(//)和DTD所有者的名字(比如上面例子的Sun Microsystems,Inc.),之后是另一個(gè)雙斜杠和DTD描述的文檔類型,接著優(yōu)勢(shì)一個(gè)雙斜杠后接ISO 639語言標(biāo)識(shí)符,如EN表示英語,ZH表示中文。例如:

<!DOCTYPE OrganizationChart PUBLIC "-//Jason Chen//DTD organization chart 1.0//ZH" "dtdTest.dtd">

在上一章我們提到,如果我們的文檔不依賴于外部文檔,在XML聲明中,可以通過standalone="yes"來聲明這個(gè)文檔是獨(dú)立的文檔。如果文檔依賴于外部文檔,可以通過standalone="no"來聲明。當(dāng)我們使用外部DTD文件時(shí),就需要將屬性standalone的值設(shè)置為"no"。
在實(shí)際應(yīng)用中,很少使用standalone屬性,它的主要用途是作為XML處理器行業(yè)其他應(yīng)用程序的標(biāo)志,表示是否需要獲取外部內(nèi)容。如果文檔依賴于外部文檔,即使我們不使用standalone屬性,XML處理器也能很好地進(jìn)行處理。

DTD的結(jié)構(gòu):

DTD的結(jié)構(gòu)一般由以下四種聲明構(gòu)成:
    1、元素類型聲明
    2、屬性列表聲明
    3、實(shí)體聲明
    4、記號(hào)聲明
一個(gè)典型的文檔類型定義文件會(huì)吧所要?jiǎng)?chuàng)建的XML文檔的元素結(jié)構(gòu)、屬性類型、實(shí)體引用等預(yù)先進(jìn)行定義。
下面分別介紹這四種聲明。

1、元素類型聲明:

一個(gè)DTD不僅要告訴XML處理器它所對(duì)應(yīng)的文檔根元素,而且還要告知處理器,文檔的內(nèi)容和結(jié)構(gòu),描述清楚文檔結(jié)構(gòu)中的每一個(gè)細(xì)節(jié)。
元素類型聲明不但說明了每一個(gè)文檔中可能存在的元素,給出了元素的名稱,而且給出了元素的具體類型。
一個(gè)XML元素可以為空,也可以只包含字符數(shù)據(jù),還可以有若干個(gè)子元素,而這些子元素同時(shí)又可以擁有它們的子元素。
元素類型聲明采用如下的語法格式:
<!ELEMENT 元素名稱 元素內(nèi)容說明>
元素內(nèi)容說明可以指明五種可能的元素內(nèi)容形式:#PCDATA、子元素、混合內(nèi)容、EMPTY和ANY。
下面詳細(xì)說明每一種元素內(nèi)容說明。

#PCDATA:

關(guān)鍵字#PCDATA說明元素包含字符數(shù)據(jù)。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE OrganizationChart [
    <!ELEMENT OrganizationChart (Name,Office)
>
    
<!ELEMENT Name (#PCDATA)>
    
<!ELEMENT Office (#PCDATA)>
    ]>
<OrganizationChart>
    
<Name>Toone,INC.</Name>
    
<Office>ZhuHai</Office>
</OrganizationChart>

子元素:

當(dāng)一個(gè)元素只包含子元素,而沒有字符數(shù)據(jù)時(shí),則稱此元素類型具有元素型內(nèi)容(element content)。
在該類型的元素聲明時(shí),通過內(nèi)容模型來指定在其內(nèi)容上的約束。內(nèi)容模型是決定子元素類型和子元素出現(xiàn)順序的一種簡單語法。