用DTD驗證XML

1.內(nèi)部DTD
最簡單的使用DTD的方法是在XML文件的序言部分加入一個DTD描述曹步,加入的位置是緊接在XML處理指示之后战虏。一個包含DTD的XML文件的結(jié)構(gòu)為:

   <?xml version = "1.0" encoding="GB2312" standalone = "yes"?>
<!DOCTYPE 根元素名[
  元素描述
    ]>
文件體

一個完整的XML文件為:

<?xml version = "1.0" encoding="GB2312" standalone = "yes"?>
<!DOCTYPE 聯(lián)系人列表[
        <!ELEMENT 聯(lián)系人列表 (聯(lián)系人)*>
        <!ELEMENT 聯(lián)系人 (姓名,ID,公司,EMAIL,電話,地址)>
        <!ELEMENT 地址 (街道,城市,省份)>
        <!ELEMENT 姓名 (#PCDATA)>
        <!ELEMENT ID (#PCDATA)>
        <!ELEMENT 公司 (#PCDATA)>
        <!ELEMENT EMAIL (#PCDATA)>
        <!ELEMENT 電話 (#PCDATA)>
        <!ELEMENT 街道 (#PCDATA)>
        <!ELEMENT 城市 (#PCDATA)>
        <!ELEMENT 省份 (#PCDATA)>
    ]>
<?xml-stylesheet type="text/xsl" href="mystyle.xsl"?>

<聯(lián)系人列表>
  <聯(lián)系人>
    <姓名>張三</姓名>
    <ID>001</ID>
    <公司>A公司</公司>
    <EMAIL>zhang@aaa.com</EMAIL>
    <電話>(010)62345678</電話>
    <地址>
      <街道>五街1234號</街道>
      <城市>北京市</城市>
      <省份>北京</省份>
    </地址>
  </聯(lián)系人>

  <聯(lián)系人>
    <姓名>李四</姓名>
    <ID>002</ID>
    <公司>B公司</公司>
    <EMAIL>li@bbb.org</EMAIL>
    <電話>(021)87654321</電話>
    <地址>
      <街道>南京路9876號</街道>
      <城市>上海市</城市>
      <省份>上海</省份>
    </地址>
  </聯(lián)系人>
</聯(lián)系人列表>

2.外部DTD
一個DTD既可以是內(nèi)部的凛虽,包含在一個“形式良好的”XML文件中(standalone=“yes”)鉴未;也可以是外部的业汰,作為一個外部文件被引用(standalone=“no”)猾封。
外部DTD的好處是:它可以方便高效地被多個XML文件所共享。你只要寫一個DTD文件抛丽,就可以被多個XML文件所引用谤职。事實上,當(dāng)許多組織需要統(tǒng)一它們的數(shù)據(jù)交換格式時亿鲜,它們就是通過外部DTD來完成的允蜈。這樣做不僅簡化了輸入工作,還保證當(dāng)你需要對DTD做出改動時蒿柳,不用一一去改每個引用了它的XML文件饶套,只要改一個公用的DTD文件就足夠了.
為了引用一個外部DTD,必須修改XML聲明和DOCTYPE聲明垒探。XML聲明中必須說明這個文件不是自成一體的妓蛮,即standalone屬性的屬性值不再是yes了。

<?xml version = "1.0"
      encoding="GB2312"
      standalone = "no"?>

在DOCTYPE聲明中叛复,應(yīng)該加入SYSTEM屬性:

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

例如:

<!DOCTYPE 聯(lián)系人列表
SYSTEM "http://www.mydomain.com/dtds/fclml.dtd
">

上面的URL是一個絕對路徑仔引,除此以外扔仓,它還可以是一個相對路徑褐奥,如:

<!DOCTYPE 聯(lián)系人列表
SYSTEM "fclml.dtd">

它說明這個DTD文件和引用它的XML文件在同一個目錄下∏檀兀或者撬码,這個DTD文件還可能在XML文件的父目錄的子目錄DTD下,表示為:

<!DOCTYPE 聯(lián)系人列表
SYSTEM "../dtds/fclml.dtd">

使用這種方法版保,你可以方便地把DTD文件從你的XML文件中分離出來呜笑,粘貼到另一個文件fclml.dtd中。這樣彻犁,你就得到一個DTD文件和一個有效的XML文件叫胁。
仍然回到前面那個包含客戶聯(lián)系方式信息的XML文件,如果使用外部DTD汞幢,其形式應(yīng)該變?yōu)橄旅孢@個樣子驼鹅。DTD文件fclml.dtd:

<?xml version="1.0" encoding="GB2312"?>

<!ELEMENT 聯(lián)系人列表 (聯(lián)系人)*>
<!ELEMENT 聯(lián)系人 (姓名,ID,公司,EMAIL,電話,地址)>
<!ELEMENT 地址 (街道,城市,省份)>
<!ELEMENT 姓名 (#PCDATA)>
<!ELEMENT ID (#PCDATA)>
<!ELEMENT 公司 (#PCDATA)>
<!ELEMENT EMAIL (#PCDATA)>
<!ELEMENT 電話 (#PCDATA)>
<!ELEMENT 街道 (#PCDATA)>
<!ELEMENT 城市 (#PCDATA)>
<!ELEMENT 省份 (#PCDATA)>

XML文件client.xml:

<?xml version = "1.0" encoding="GB2312" standalone = "no"?>
<!DOCTYPE 聯(lián)系人列表
    SYSTEM "fclml.dtd">
<?xml-stylesheet type="text/xsl" href="mystyle.xsl"?>

<聯(lián)系人列表>
<聯(lián)系人>
<姓名>張三</姓名>
<ID>001</ID>
<公司>A公司</公司>
<EMAIL>zhang@aaa.com</EMAIL>
<電話>(010)62345678</電話>
<地址>
<街道>五街1234號</街道>
<城市>北京市</城市>
<省份>北京</省份>
<ZIP>100001</ZIP>
</地址>
</聯(lián)系人>

<聯(lián)系人>
<姓名>李四</姓名>
<ID>002</ID>
<公司>B公司</公司>
<EMAIL>li@bbb.org</EMAIL>
<電話>(021)87654321</電話>
<地址>
<街道>南京路9876號</街道>
<城市>上海</城市>
<省份>上海</省份>
<ZIP>200002</ZIP>
</地址>
</聯(lián)系人>
</聯(lián)系人列表>

3. 公用DTD
使用外部DTD時,要在DOCTYPE中使用關(guān)鍵字SYSTEM。實際上输钩,SYSTEM不是引用外部DTD的唯一方法豺型,這個關(guān)鍵字主要用于引用一個作者或組織所編寫的眾多XML文件中通用的DTD。還存在一種外部DTD买乃,它是一個由權(quán)威機構(gòu)制訂的姻氨,提供給特定行業(yè)或公眾使用的DTD。因此剪验,另一個引用外部DTD的辦法是使用關(guān)鍵字PUBLIC肴焊,引用這一類公開給公眾使用的DTD。 引用公共DTD的形式為:

<!DOCTYPE 根元素 PUBLIC "DTD名稱" "外部DTD的URL">

4.元素的定義
一個DTD不僅要告訴語法分析器它所關(guān)聯(lián)的XML文件的根元素是什么功戚,而且還要告訴語法分析器文件的內(nèi)容和結(jié)構(gòu)抖韩,說清文件結(jié)構(gòu)中的每一個細節(jié)。為了定義這些細節(jié)疫铜,我們必須展開DTD中元素說明部分茂浮,使用元素類型聲明(ETD)來聲明所有有效的文件元素。ETD應(yīng)該采用如下的結(jié)構(gòu):

<!ELEMENT 元素名 元素內(nèi)容描述>

一個具體例子:

<?xml version = "1.0" encoding="GB2312" standalone = "yes"?>
<!DOCTYPE 聯(lián)系人列表[
    <!ELEMENT 聯(lián)系人列表 ANY>
    <!ELEMENT 聯(lián)系人(姓名)>
    <!ELEMENT 姓名(#PCDATA)>
    ]>

<聯(lián)系人列表>
    <聯(lián)系人>
        <姓名>張三</姓名>
    </聯(lián)系人>
</聯(lián)系人列表>

元素定義是由它們的元素內(nèi)容模型(ECM)來描述的壳咕,也就是說席揽,是由緊跟元素后面的括號中的內(nèi)容來定義的。元字符的定義:

元 字 符 含 義
+ 出現(xiàn)一次或多次
* 出現(xiàn)零次或多次
谓厘? 可選幌羞,不出現(xiàn)或出現(xiàn)一次
() 一組要共同匹配的表達式
OR,或
竟稳, AND属桦,要求嚴(yán)格遵從順序要求
元素A元素B元素C 元素列表,無須遵從順序要求

注意:在一個組中他爸,只允許使用一種連接符(例如“聂宾,”或“|”)。因此诊笤,像下面這樣定義的DTD是不合法的:

<!ELEMENT 聯(lián)系人(姓名系谐,電話|EMAIL)>

要想使用多種連接符,只有通過創(chuàng)建子組的方式讨跟,使用:

<!ELEMENT 聯(lián)系人(姓名纪他,(電話|EMAIL))>

5.元素的屬性
 在DTD中定義屬性時,我們使用下面的格式:

<!ATTLIST 元素名 (屬性名 屬性類型 缺省值)*>
  • 必須賦值的屬性

關(guān)鍵字REQUIRED說明XML文件中必須為這個屬性給出一個屬性值晾匠。例如茶袒,假設(shè)你想定義一個"頁面作者"元素,并把這個元素加入所有網(wǎng)站中的每一個頁面凉馆。之所以定義這個元素薪寓,是為了頁面編輯者能夠提供他的聯(lián)系信息乾巧,以便當(dāng)發(fā)現(xiàn)頁面錯誤或無效鏈接時,可以及時地通知他预愤。在這種情況下沟于,每個頁面作者都有不同的個人信息,所以你無法事先知道應(yīng)該用什么作為缺省值植康,但你又的確需要提供每個人的信息旷太。這時候,你就可以把與聯(lián)系信息相關(guān)的屬性定義為必須的(REQUIRED)销睁,而且不用提供缺省值供璧。

  • 屬性值可有可無的屬性
    當(dāng)使用IMPLIED關(guān)鍵字時,文法解釋器不再強行要求你在XML文件中給該屬性賦值冻记,而且也無須在DTD中為該屬性提供缺省值睡毒。可以說冗栗,這是對屬性值有無的最低要求演顾,現(xiàn)實中經(jīng)常用到。
  • 固定取值的屬性
    還有一種特殊情況隅居,你需要為一個特定的屬性提供一個缺省值钠至,并且不希望XML文件的編寫者把你的缺省值替代掉。這時候胎源,就應(yīng)該使用FIXED關(guān)鍵字棉钧,同時為該屬性提供一個缺省值。
  • 定義缺省值的屬性
    如果不使用上面任何一種關(guān)鍵字的話涕蚤,該種屬性就是屬于這種類型宪卿。對于這種屬性,你需要在DTD中為它提供一個缺省值万栅。而在XML文件中可以為該屬性給出新的屬性值來覆蓋事先定義的缺省值佑钾,也可以不另外給出屬性值,后一種情況下它就默認為采用DTD中給出的缺省值申钩。
      視實際情況而選擇次绘,給出一個實際的例子:
<!ATTLIST 頁面作者
        姓名 #CDATA #IMPLIED
        年齡 #CDATA #IMPLIED
        聯(lián)系信息 #CDATA #REQUIRED
        網(wǎng)站職務(wù) #CDATA #FIXED "頁面作者"
        個人愛好 #CDATA "上網(wǎng)">

另外還有屬性的類型:

  • CDATA
  • Enumerated
  • ID
  • IDREF
  • IDREFS
  • ENTITY
  • ENTITIES
  • NMTOKEN
  • NMTOKENS
  • NOTATION

參數(shù)實體專門用在DTD中瘪阁。定義方式是:

<!ENTITY % 實體名 "實體內(nèi)容">
或
<!ENTITY % 實體名 SYSTEM "外部文件名">

引用方式為: %實體名撒遣;
使用參數(shù)實體,可以方便元素和屬性的聲明管跺。例如:

<!ENTITY % TAG_NAMES "姓名 | EMAIL | 電話 | 地址">
<!ELEMENT 個人聯(lián)系信息 (%TAG_NAMES; | 生日)>
<!ELEMENT 客戶聯(lián)系信息 (%TAG_NAMES; | 公司名)>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末义黎,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子豁跑,更是在濱河造成了極大的恐慌廉涕,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異狐蜕,居然都是意外死亡宠纯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門层释,熙熙樓的掌柜王于貴愁眉苦臉地迎上來婆瓜,“玉大人,你說我怎么就攤上這事贡羔×祝” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵乖寒,是天一觀的道長猴蹂。 經(jīng)常有香客問我,道長楣嘁,這世上最難降的妖魔是什么磅轻? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮逐虚,結(jié)果婚禮上瓢省,老公的妹妹穿的比我還像新娘。我一直安慰自己痊班,他們只是感情好勤婚,可當(dāng)我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著涤伐,像睡著了一般馒胆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凝果,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天祝迂,我揣著相機與錄音,去河邊找鬼器净。 笑死型雳,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的山害。 我是一名探鬼主播纠俭,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼浪慌!你這毒婦竟也來了冤荆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤权纤,失蹤者是張志新(化名)和其女友劉穎钓简,沒想到半個月后乌妒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡外邓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年撤蚊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片损话。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡拴魄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出席镀,到底是詐尸還是另有隱情匹中,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布豪诲,位于F島的核電站顶捷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏屎篱。R本人自食惡果不足惜服赎,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望交播。 院中可真熱鬧重虑,春花似錦、人聲如沸秦士。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽隧土。三九已至提针,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間曹傀,已是汗流浹背辐脖。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留皆愉,地道東北人嗜价。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像幕庐,于是被迫代替她去往敵國和親久锥。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 1. XML簡介 以下內(nèi)容來自于http://www.w3school.com.cn/xml 基本知識 XML 和...
    WebSSO閱讀 1,924評論 1 7
  • 經(jīng)過兩天的奮戰(zhàn)翔脱,終于把xml簡略的過了一遍奴拦。 1.1XML介紹 xml是Extensible Markup lan...
    Ystrator閱讀 821評論 0 2
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,848評論 6 342
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)届吁,斷路器错妖,智...
    卡卡羅2017閱讀 134,699評論 18 139
  • 今天看了簡報術(shù)第5章圖表的制作技巧34-36小節(jié)。 日常工作中難免要涉及數(shù)據(jù)分析和報告呈現(xiàn)疚沐,為了讓觀看者能一目了然...
    大棉閱讀 1,010評論 0 0