在上一篇筆記中,將文檔類型分類時,曾經根據文檔是否使用並遵照了DTD或Schema來區分爲格式良好的XML和有效的XML,那麼什麼是DTD和Schema呢?DTD和Schema都是用來規範XML文檔的,對XML文檔進行語義約束的,DTD簡單易用,Schema則功能強大。在這篇筆記中,首先學習一下DTD(Document Type Definition,文檔類型定義)。java
一、在XML文檔中怎麼使用DTDweb
導入方式 | 語法格式 | 說明 |
內部DTD |
<!DOCTYPE 根元素名[ 元素描述 ]> |
將DTD定義放在XML文檔內部,緊跟在XML聲明和處理指令後面app 如:<!DOCTYPE 模型列表[學習 <!ELEMENT 模型列表(模型)*>spa ]>code |
外部DTD |
<!DOCTYPE 根元素名 SYSTEM "外部DTD的URI"> |
將DTD單獨定義在一個文件內,而後經過關鍵字SYSTEM導入DTDxml 如:<!DOCTYPE 模型列表 SYSTEM "模型列表DTD文件的相對路徑或絕對路徑">blog |
公用DTD |
<!DOCTYPE 根元素名 PUBLIC "DTD的標識名" "公用DTD的URI"> |
公用DTD,這種DTD通常是由某個權威機構指定,供特定行業或公衆使用,經過關鍵字PUBLIC導入圖片 如:<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">文檔 |
二、 DTD的結構
DTD文檔自己不是XML文檔,而只是爲XML定義語義約束的文檔,DTD文檔的語法很是簡單,大體有以下結構:
(1)第一行是DTD文檔的聲明,語法和XML的聲明相同
(2)0到多個註釋部分,DTD註釋與XML註釋語法相同
(3)0到多個<!ELEMENT...>定義,每一個<!ELEMENT...>定義一個XML元素
(4)0到多個<!ATTLIST...>定義,每一個<!ATTLIST...>爲XML元素定義一個屬性
(5)0到多個<!ENTITY...>定義,每一個<!ENTITY...>定義一個實體
(6)0到多個<!NOTATION...>定義,每一個<!NOTATION...>定義一個符號
其中<!ELEMENT...>、<!ATTLIST...>、<!ENTITY...>、<!NOTATION...>4個定義彼此徹底獨立,無須互相嵌套,下面就逐一說明這四種定義。
三、定義元素
(1)元素類型定義,Element Type Definition,簡稱ETD
(2) 元素類型
元素類型 | 定義格式 | 說明 |
任意類型 | <!ELEMENT 元素名稱 ANY> | 元素能夠是字符串,能夠是空元素,也能夠包含子元素 |
字符串值 | <!ELEMENT 元素名稱 (#PCDATA)> | 元素值只能是字符串,不能夠是空元素,也不能包含子元素 |
空元素 | <!ELEMENT 元素名稱 EMPTY> | |
包含子元素 | 比較複雜,須要詳細定義子元素之間的順序以及子元素出現的次數等 | |
混合類型 | <!ELEMENT 元素名稱 (#PCDATA|子元素1|子元素2|...)*> | 指定值只能是幾個肯定的類型,比任意類型有更強的約束,但功能至關,應儘可能使用混合類型 |
關於混合類型的定義,說明幾點:
A:#PCDATA必須放在最前面
B:#PCDATA和各子元素之間只能用豎線(|)分隔,不要使用逗號分隔
C:不要在子元素以後使用?、*、+等表示頻率的修飾符
(3)定義子元素
定義子元素的語法 | 說明 | 子元素的出現頻率修飾詞 | 說明 |
(子元素1,子元素2,...) | 使用英文逗號定義有序的子元素 | 默認(沒有修飾詞) | 出現一次,且只能出現一次 |
(子元素1|子元素2|...) | 使用豎線定義互斥的子元素 | ? | 出現0或1次 |
((子元素1,子元素2)|(子元素3,子元素4)) | 使用括號將子元素分組 | + | 出現1或屢次 |
(子元素1|子元素2|...)+ | 使用豎線互斥,而後使用頻率修飾實現定義無序的子元素 | * | 出現0或屢次 |
四、定義屬性
在XML中,屬性不能單獨存在,所以定義屬性時必須指定屬於哪一個元素。定義屬性的語法格式以下:
<!ATTLIST 屬性所屬的元素名稱 屬性名稱 屬性類型 [元素對屬性的約束] [默認值]>
(1)屬性類型
類型 | 說明 |
CDATA | 該屬性值只能是字符串數據 |
(en1|en2|en3) | 該屬性值必須是一系列枚舉值之一 |
ID | 該屬性值必須是有些的標識符,且該屬性值可用於標識該元素,所以必須在此XML文檔中惟一 |
IDREF | 該屬性值必須是引用另外一個已有的ID類型的屬性值 |
IDREFS | 該屬性值必須是引用已有的一個或多個ID類型的屬性值,多個ID類型的屬性值之間使用空格分隔 |
NMTOKEN | 該屬性值必須是合法的XML名稱,必須是字符串數據,比CDATA約束更強,只能由字母、數字、下劃線、中劃線,點號和冒號組成 |
NMTOKENS | 該屬性值必須是一個或多個NMTOKEN類型的屬性值,多個使用空格分隔 |
ENTITY | 該屬性值是一個外部實體,好比圖片 |
ENTITIES | 該屬性值是一個或多個ENTITY類型的屬性值,多個使用空格分隔 |
NOTATION | 該屬性值是在DTD中聲明過的符號(NOTATION),這是個將要過時的規範,儘可能避免使用 |
xml: | 該屬性值是一個預約義的XML值 |
(2)元素對屬性的約束與默認值的關係
元素對屬性的約束 | 說明 | 默認值 |
未指定 | 必須指定默認值 | |
#REQUIRED | 必須的屬性,必須爲相應元素提供該屬性 | 不能指定默認值 |
#IMPLIED | 該屬性無關緊要 | 不能指定默認值 |
#FIXED | 該屬性值是固定的,定義時必須指定固定值 | 必須指定默認值 |
五、定義實體
實體引用就是用一個字符串代替另外一個字符串,相似於C語言中的宏,上一篇筆記中已經提到過XML中內置的5個實體引用,在這裏接着看看怎麼自定義實體引用。
實體類型 | 使用場所 | 定義語法 | 使用語法 | 說明 |
普通實體 | XML | <!ENTITY 實體名 "實體值"> | &實體名; | |
參數實體 | DTD | <!ENTITY % 實體名 "實體值"> | %實體名; | 必須在使用前先定義 |
外部實體 | XML | <!ENTITY 實體名 SYSTEM "實體值所在文件的URI"> | &實體名; | 這裏外部文件必須是知足XML文檔結構的文本文檔 |
公用外部實體 | XML | <!ENTITY 實體名 PUBLIC "公用實體標識名" "實體值所在文件的URI"> | &實體名; | |
外部參數實體 | DTD | <!ENTITY % 實體名 SYSTEM "實體值所在文件的URI"> | %實體名; | |
公用外部參數實體 | DTD | <!ENTITY % 實體名 PUBLIC "公用實體標識名" "實體值所在文件的URI"> | %實體名; | |
未解析實體 | XML | <!ENTITY % 實體名 SYSTEM "實體值所在文件的URI" NDATA 符號名> | 須要經過ENTITY等類型的屬性調用 | 未解析實體不能由XML文檔解析,而須要根據相應的符號名去解析 |
公用未解析實體 | XML | <!ENTITY % 實體名 PUBLIC "公用實體標識名" "實體值所在文件的URI" NDATA 符號名> |
六、定義符號
定義符號也有兩種語法格式,分別定義普通符號和公用符號:
符號類型 | 定義語法 |
普通符號 | <!NONATION 符號名 SYSTEM "符號值"> |
公用符號 | <!NONATION 符號名 PUBLIC "公用符號標識名" "符號值"> |
符號值一般有兩種形式:
(1)MIME:通用MIME類型的文件老是由相應的程序負責處理
(2)外部程序所在路徑:直接指定某個外部程序負責處理XML文檔中的外部數據
符號一般有兩種用途:
(1)如上,符號能夠用來定義未解析實體
(2)符號能夠做爲ENTITY或ENTITIES類型的屬性值
(3)符號還能夠做爲NOTATION類型的屬性的值,定義NOTATION類型的屬性時,語法以下:
<!ATTLIST 屬性所屬的元素 屬性名 NOTATION (值1|值2|...) 約束 默認值>
比通常的屬性定義多一個值的列表。