我們編寫文檔來(lái)束縛1個(gè)XML文檔的書寫規(guī)范,這稱之為XML束縛。
經(jīng)常使用的束縛技術(shù)有:
- XML DTD
- XML Schema
DTD的基本概念:
document type definition 文檔類型定義
DTD文件1般和XML文件配合使用,主要是為了束縛XML文件。
XML文件引入DTD文件,這樣X(jué)ML可以自定義標(biāo)簽,但又遭到DTD文件的束縛。比如上1節(jié)使用XML描寫1個(gè)班級(jí)的信息,如果我們給每個(gè)學(xué)生定義1個(gè)<面積>
標(biāo)簽,語(yǔ)法上也是沒(méi)有毛病的,但是不符合語(yǔ)義,學(xué)生怎樣能夠用面積來(lái)描寫呢?這時(shí)候候我們就需要用到DTD文件來(lái)束縛這個(gè)XML。
<?xml version="1.0" encoding="gb2312"?>
<class>
<stu id="001">
<name>楊過(guò)</name>
<sex>男</sex>
<age>20</age>
<面積>100</面積>
</stu>
</class>
基本語(yǔ)法:
<!ELEMENT 元素名 類型>
我們還以班級(jí)為例,編寫以下DTD文件,myClass.dtd:
<!ELEMENT 班級(jí) (學(xué)生+)>
<!ELEMENT 學(xué)生 (名字,年齡,介紹)>
<!ELEMENT 名字 (#PCDATA)>
<!ELEMENT 年齡 (#PCDATA)>
<!ELEMENT 介紹 (#PCDATA)>
第1行表示根元素為班級(jí),并且有學(xué)生這個(gè)子元素,子元素為1或多個(gè)。
第2行表示學(xué)生的子元素為名字,年齡,介紹
名字下面沒(méi)有子元素了,那末#PCDATA表示名字里面可以放任意文本。
年齡和介紹也是類似。
編寫myClass.xml文件并引入DTD文件以下:
<?xml version="1.0" encoding="utf⑻"?>
<!--引入dtd文件,束縛這個(gè)xml-->
<!DOCTYPE 班級(jí) SYSTEM "myClass.dtd">
<班級(jí)>
<學(xué)生>
<名字>周小星</名字>
<年齡>23</年齡>
<介紹>學(xué)習(xí)刻苦</介紹>
</學(xué)生>
<學(xué)生>
<名字>林曉</名字>
<年齡>25</年齡>
<介紹>是1個(gè)好學(xué)生</介紹>
</學(xué)生>
</班級(jí)>
引入中寫的:SYSTEM,表示當(dāng)前的DTD文件是本地的
如果寫的是PUBLIC,則表示引入的DTD文件是來(lái)自于網(wǎng)絡(luò)的.
這時(shí)候候引入的DTD文件是沒(méi)有產(chǎn)生作用的,如果我們?cè)趯W(xué)生元素中添加子元素<面積>
,打開這個(gè)XML文件,閱讀器仍然不會(huì)報(bào)錯(cuò)。
<?xml version="1.0" encoding="utf⑻"?>
<!--引入dtd文件,束縛這個(gè)xml-->
<!DOCTYPE 班級(jí) SYSTEM "myClass.dtd">
<班級(jí)>
<學(xué)生>
<名字>周小星</名字>
<年齡>23</年齡>
<介紹>學(xué)習(xí)刻苦</介紹>
<面積>100平米</面積>
</學(xué)生>
<學(xué)生>
<名字>林曉</名字>
<年齡>25</年齡>
<介紹>是1個(gè)好學(xué)生</介紹>
</學(xué)生>
</班級(jí)>
我們需要編程校驗(yàn)XML文檔的正確性。
IE5以上的閱讀器內(nèi)置了XML解析工具:Microsoft.XMLDOM,開發(fā)人員可以編寫JavaScript代碼,利用這個(gè)解析工具裝載XML文件,并對(duì)XML文件進(jìn)行DTD驗(yàn)證。
我們編寫myXmlTools.html來(lái)對(duì)這個(gè)XML進(jìn)行校驗(yàn),以下:
<html>
<head>
<!--自己編寫1個(gè)簡(jiǎn)單的解析工具,去解析XML DTD是不是配套-->
<script language="javascript">
// 創(chuàng)建xml文檔解析器對(duì)象
var xmldoc = new ActiveXObject("Microsoft.XMLDOM");
// 開啟xml校驗(yàn)
xmldoc.validateOnParse = "true";
// 裝載xml文檔,即指定校驗(yàn)?zāi)囊粋€(gè)XML文件
xmldoc.load("myClass.xml");
document.writeln("毛病信息:"+xmldoc.parseError.reason+"<br>");
document.writeln("毛病行號(hào):"+xmldoc.parseError.line);
</script>
</head>
<body>
</body>
</html>
用IE閱讀器打開這個(gè)html文件,可以看到運(yùn)行結(jié)果:
可以看到第9行正是我們添加的<面積>
這1行。
1.內(nèi)部DTD文檔
<!DOCTYPE 根元素 [定義內(nèi)容]>
2.外部DTD文檔
引入外部的DTD文檔分為兩種:
(1)當(dāng)援用的DTD文件是本地文件的時(shí)候,用SYSTEM標(biāo)識(shí),并寫上”DTD的文件路徑”,以下:
<!DOCTYPE 根元素 SYSTEM "DTD文件路徑">
(2)如果援用的DTD文件是1個(gè)公共的文件時(shí),采取PUBLIC標(biāo)識(shí),以下方式:
<!DOCTYPE 根元素 PUBLIC "DTD名稱" "DTD文件的URL">
比以下例:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems,Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<!ELEMENT NAME CONTENT>
其中:
- ELEMENT是關(guān)鍵字,是不能修改的
- NAME表示元素名稱
- CONTENT是元素類型,必須要大寫!CONTENT的內(nèi)容有3種寫法:
(1)EMPTY——表示該元素不能包括子元素和文本,但可以有屬性。
(2)ANY——表示該元素可以包括任何在該DTD中定義的元素內(nèi)容
(3)#PCDATA——可以包括任何字符數(shù)據(jù),但是不能在其中包括任何子元素
DTD中這樣規(guī)定:
<!ELEMENT 家庭(人+,家電*)>
這個(gè)DTD規(guī)定了家庭元素中可以有1到多個(gè)”人”這個(gè)子元素,也能夠有0到多個(gè)”家電”這個(gè)子元素。其中的加號(hào)”+”和星號(hào)”*”的含義與正則表達(dá)式中的含義1致。
XML這樣寫:
<家庭>
<人 名字="張曉明" 性別="男" 年齡="25"/>
<人 名字="李小鋼" 性別="男" 年齡="36" 愛(ài)好="作個(gè)教育家和巨人"/>
<家電 名稱="彩電" 數(shù)量="3"/>
</家庭>
關(guān)于組合類型,有下述的的修飾符可使用:
符號(hào) | 用處 | 示例 | 示例說(shuō)明 |
---|---|---|---|
() | 用來(lái)給元素分組 | (古龍|金庸),(王朔|余杰) | 分成兩組 |
| | 在列出的對(duì)象當(dāng)選擇1個(gè) | (男人|女人) | 表示男人或女人必須出現(xiàn),二者最少選其1 |
+ | 該對(duì)象必須出現(xiàn)1次或?qū)掖?/td> | (成員+) | 表示成員必須出現(xiàn),而卻可以出現(xiàn)多個(gè)成員 |
* | 該對(duì)象允許出現(xiàn)0次或?qū)掖?/td> | (愛(ài)好*) | 愛(ài)好可以出現(xiàn)兩次到屢次 |
? | 該對(duì)象必須出現(xiàn)0次或1次 | (菜鳥?) | 菜鳥可以出現(xiàn),也能夠不出現(xiàn),如果出現(xiàn)的話,最多只能出現(xiàn)1次 |
, | 對(duì)象必須按指定的順序出現(xiàn) | (西瓜,蘋果,香蕉) | 表示西瓜、蘋果、香蕉必須出現(xiàn),并且按這個(gè)順序出現(xiàn) |
DTD中屬性的定義是這樣的:
<!ATTLIST 元素名稱
屬性名稱 類型 屬性特點(diǎn)
屬性名稱 類型 屬性特點(diǎn)......
>
其中,屬性的類型有下面5種:
(1) CDATA
(2) ID
(3) IDREF/IDREFS
(4) Enumerated
(5) ENTITY/ENTITIES
屬性的特點(diǎn)有以下4種:
(1) #REQUIRED,表示這個(gè)屬性必須給,不給就報(bào)錯(cuò)
(2) #IMPLIED,表示這個(gè)屬性可以給也能夠不給
(3) #FIXED value,表示這個(gè)屬性必須給1個(gè)固定的value值
(4) Default value,表示這個(gè)屬性如果沒(méi)有值,就分配1個(gè)默許的value值
比如,我們想在學(xué)生這個(gè)子元素上加上地址這個(gè)屬性,而且這個(gè)屬性是必須的,示例以下:
<?xml version="1.0" encoding="utf⑻"?>
<!DOCTYPE 班級(jí) SYSTEM "myClass.dtd">
<班級(jí)>
<學(xué)生 地址="香港">
<名字>周小星</名字>
<年齡>23</年齡>
<介紹>學(xué)習(xí)刻苦</介紹>
</學(xué)生>
<學(xué)生 地址="澳門">
<名字>林曉</名字>
<年齡>25</年齡>
<介紹>是1個(gè)好學(xué)生</介紹>
</學(xué)生>
</班級(jí)>
這個(gè)時(shí)候相應(yīng)的DTD文件也要更新,不然就會(huì)報(bào)錯(cuò),以下:
<!ELEMENT 班級(jí) (學(xué)生+)>
<!ELEMENT 學(xué)生 (名字,年齡,介紹)>
<!ATTLIST 學(xué)生
地址 CDATA #REQUIRED
>
<!ELEMENT 名字 (#PCDATA)>
<!ELEMENT 年齡 (#PCDATA)>
<!ELEMENT 介紹 (#PCDATA)>
(1)屬性類型-CDATA,表示屬性值可以是任何字符(包括中文和數(shù)字)
<!ATTLIST 木偶
姓名 CDATA #REQUIRED
>
<木偶 姓名="匹諾曹"/>
<木偶 姓名="PiNuocao"/>
<木偶 姓名="123"/>
(2)屬性類型-ID,表明該屬性的取值必須是唯1的,但是屬性的值不能是以數(shù)字開頭!
<!ELEMENT 公司職員 ANY>
<!ATTLIST 公司職員
編號(hào) ID #REQUIRED
姓名 CDATA #REQUIRED
>
<公司職員 編號(hào)="Z001" 姓名="張3"/>
<公司職員 編號(hào)="Z002" 姓名="李思"/>
(3)屬性類型-IDREF/IDREFS
- IDREF屬性的值指向文檔中其它地方聲明的ID類型的值
- IDREFS同IDREF,但是可以具有由空格分開的多個(gè)援用。
<!ELEMENT 家庭(人+)>
<!ELEMENT 人 EMPTY>
<!ATTLIST 人
relID ID #REQUIRED
paraentID IDREFS #IMPLIED
name CDATA #REQUIRED
>
<家庭>
<人 relID="P_1" name="爸爸"/>
<人 relID="P_2" name="媽媽"/>
<人 relID="P_3" parentID="P_1 P_2" name="兒子"/>
</家庭>
(4)屬性類型-Enumerated,事前定義好1些值,屬性的值必須在所列出的值的范圍內(nèi)。
<!ATTLIST person
婚姻狀態(tài) (single|married|divorced|widowed) #IMPLIED
>
<!ATTLIST person
性別 (男|女) #REQUIRED
>
(5)屬性類型-ENTITY,實(shí)體
實(shí)體定義:
- 實(shí)體用于為1段內(nèi)容創(chuàng)建1個(gè)別名,以后在XML文檔中就能夠使用別名援用這段內(nèi)容了。
- 在DTD定義中,1條!ENTITY語(yǔ)句用于定義1個(gè)實(shí)體。
- 實(shí)體可分為兩種類型:援用實(shí)體和參數(shù)實(shí)體。援用實(shí)體是被XML文檔利用的,而參數(shù)實(shí)體是被DTD文件本身利用的。
①援用實(shí)體:
- 援用實(shí)體主要在XML文檔中被利用
語(yǔ)法格式以下,援用實(shí)體的定義內(nèi)容最好放在DTD文件的最后。
<!ENTITY 實(shí)體名稱 "實(shí)體內(nèi)容">
援用方式:&實(shí)體名稱; 末尾要帶上分號(hào),這個(gè)援用將直接轉(zhuǎn)變成實(shí)體內(nèi)容
舉例以下:
<!ENTITY copyright "I am a programmer">
....
©right;
②參數(shù)實(shí)體:
參數(shù)實(shí)體被DTD文件本身使用
語(yǔ)法格式為:
<!ENTITY % 實(shí)體名稱 "實(shí)體內(nèi)容">
援用方式為:%實(shí)體名稱
舉例:
<!ENTITY % TAG_NAME "姓名|EMAIL|電話|地址">
<!ELEMENT 個(gè)人信息 (%TAG_NAME;|生日)>
<!ELEMENT 客戶信息 (%TAG_NAME;|公司名)>
學(xué)習(xí)DTD的目標(biāo)在于:
(1)要求我們能夠看得懂DTD文件,
(2)我們可以根據(jù)給出的DTD寫出對(duì)應(yīng)的XML文件
下面我們看1個(gè)案例,下述的DTD文件是從W3School在線教程中的DTD案例中拿過(guò)來(lái)的,細(xì)看每行,我們都應(yīng)當(dāng)能夠看得懂。
<!ENTITY AUTHOR "John Doe">
<!ENTITY COMPANY "JD Power Tools, Inc.">
<!ENTITY EMAIL "jd@jd-tools.com">
<!ELEMENT CATALOG (PRODUCT+)>
<!ELEMENT PRODUCT
(SPECIFICATIONS+,OPTIONS?,PRICE+,NOTES?)>
<!ATTLIST PRODUCT
NAME CDATA #IMPLIED
CATEGORY (HandTool|Table|Shop-Professional) "HandTool"
PARTNUM CDATA #IMPLIED
PLANT (Pittsburgh|Milwaukee|Chicago) "Chicago"
INVENTORY (InStock|Backordered|Discontinued) "InStock">
<!ELEMENT SPECIFICATIONS (#PCDATA)>
<!ATTLIST SPECIFICATIONS
WEIGHT CDATA #IMPLIED
POWER CDATA #IMPLIED>
<!ELEMENT OPTIONS (#PCDATA)>
<!ATTLIST OPTIONS
FINISH (Metal|Polished|Matte) "Matte"
ADAPTER (Included|Optional|NotApplicable) "Included"
CASE (HardShell|Soft|NotApplicable) "HardShell">
<!ELEMENT PRICE (#PCDATA)>
<!ATTLIST PRICE
MSRP CDATA #IMPLIED
WHOLESALE CDATA #IMPLIED
STREET CDATA #IMPLIED
SHIPPING CDATA #IMPLIED>
<!ELEMENT NOTES (#PCDATA)>
然后我們可以根據(jù)該DTD編寫以下最簡(jiǎn)單的XML文件:
<?xml version="1.0" encoding="utf⑻"?>
<!DOCTYPE CATALOG SYSTEM "product.dtd">
<CATALOG>
<PRODUCT NAME="康帥傅礦泉水" CATEGORY="Table" PARTNUM="12" PLANT="Chicago">
<SPECIFICATIONS WEIGHT="20" POWER="18">這里是細(xì)節(jié)</SPECIFICATIONS>
<PRICE>25</PRICE>
<PRICE>28</PRICE>
</PRODUCT>
</CATALOG>
然后我們用Microsoft.XMLDOM校驗(yàn)該XML,會(huì)發(fā)現(xiàn)沒(méi)有任何毛病。但是要注意編碼。