參考連結
4. XML語法
XML的語法十分簡單易學,您只需要了解其中一些簡單的規則,就可以輕易上手。雖然它也有一些比較複雜的規則,但是這些規則並不會很難理解,比大部分的Internet技術簡單多了。
XML的文件可以分為兩種: 格式正確的 (Well-Formed)和 有效合法的 (Valid)。
格式正確的XML文件表示該文件符合XML規範中所有格式相關的條件限制。然而,何謂有效合法的XML文件呢?引用XML規範中的定義,即為「如果XML文件由 文件類別宣告 (Document Type Declaration,DTD)加以定義,並且遵從DTD所定義的規則來表現和限制資料,則該XML文件則為有效合法的文件」。您將會在本章的後續討論中學到這些相關知識。
格式正確的XML文件
首先為您介紹格式正確的XML文件中有哪些較常用的規則。筆者將在後續的各節中為您詳細說明這些規則。
•每一個元素都必須有一個開始標籤和結束標籤。
•一份文件中必須有單一、唯一的根元素。
•元素必須是正確的巢狀排列(也就是說,元素之間不得交叉)。
•某些特定的保留字元不能使用(可以藉由使用其他字元來代替)。
•屬性值必須以引號包含。
•空元素必須遵守特定的格式。
XML宣告
格式正確的XML文件必須由選擇性的XML宣告開始。該宣告會為XML剖析器定義該文件為XML文件,也提供了剖析器相關於文件的資訊。XML宣告如下所示:
<?xml version="1.0"?>
雖然XML 1.0是目前唯一的版本,但是您仍然要宣告版本屬性。請注意屬性值 1.0 包含於引號中,您可以使用單引號或雙引號。
文字編碼宣告位於版本屬性之後,如下所示:
encoding="SHIFT_JIS"
文字編碼宣告指出文件是使用何種字元集建立。預設值XML文件是以Unicode編碼(UTF-8或UTF-16)。如果您使用這兩種編碼方式中的任一個來建立文件,您就不需要指定文字編碼屬性。
獨立文件宣告位於文字編碼宣告之後,如下所示:
standalone="yes"
獨立文件宣告使用的屬性值可以為 yes 或 no 。屬性值使用 yes 會指示剖析器所有相關於文件的資訊都已經包含在文件中了,這表示文件中沒有指定外部的實體(entity),也沒有使用外部的架構(external schema)來指定文件中的預設屬性值;屬性值使用 no 會指示應用程式需要取得文件以外的資訊以完成文件剖析。
在XML宣告之中必須包含文字編碼宣告和獨立文件宣告。聯合使用這些屬性之後,XML宣告如下所示:
<?xml version="1.0" encoding="EBCDIC" standalone="no"?>
XML宣告必須在格式正確文件的第一行,而且其中的文字是區分大小寫的。
開始標籤和結束標籤
一份文件會包含文字和標記(markup),標記指出文件的結構以供應用程式處理該文件。標記是由用於描述文件中資料的標籤(tag)所組成。標籤必須包含在左右各一個角括弧中,成對的標籤中包含了文字資料,並成對使用以分隔資料。
元素(element)是使用來辨別的特殊資料物件,元素也會有屬性,屬性當中最重要的就是元素名稱(元素名稱是一個已知資料類型的描述性名稱)。您必須使用標籤來指出元素的開始和結束,在XML文件中的每一個元素都必須以開始標籤的識別項開始,並且要有一個相對的結束標籤結束。結束標籤看起來跟開始標籤十分相似,唯一的區別是結束標籤中的元素名稱之前還包含了斜線(/)。在開始和結束標籤中的資料即為元素的內容,內容可以為文字或是其他元素(該元素具有自己的標籤)。範例如下所示:
<prologue>We the people</prologue>
開始標籤為 <prologue> 、內容為「We the people」、結束標籤為 </prologue> 。三個部分加起來構成一個元素。
元素名稱必須以字母或底線開始,在第一個字元後面可以是其他字元、數字、底線或連字號。
--------------------------------------------------------------------------------
說明
許多XML 1.0剖析器可以讓您使用冒號為元素名稱,但是筆者建議您不要使用冒號-冒號是W3C建議標準(稱為「Namespaces in XML」)的保留字,而XML 1.0建議標準採納「Namespaces in XML」為補增標準。本章稍後將詳細討論名稱空間。
--------------------------------------------------------------------------------
根元素
XML文件必須有單一、唯一的根元素:該元素在文件的頂端有開始標籤,並且在文件的末端有結束標籤。文件中遇到的第一個開始標籤就視為根元素,如果遇到了該元素的結束標籤,則文件就結束了。如果剖析器在這之後遇到了另一個開始標籤,它將會顯示錯誤訊息-因為在根層級只能有一個元素,如果根元素的開始標籤不在根層級,則會產生錯誤。
區分大小寫
在HTML文件中,元素和屬性名稱是不區分大小寫的。換句話說,您可以使用下列所有的標籤建立表格: <TABLE> 、 <table> 、甚至 <TaBlE> 。HTML剖析器將它們都視為一樣的標籤。
所有的XML元素和屬性都區分大小寫。如果您使用開始標籤 <List-item> ,則您必須使用 </List-item> 為結束標籤,而並非 <LIST-ITEM> 或 </list-item> 為結束標籤。
正確的巢狀排列
在格式正確文件中的元素必須有正確的樹狀結構,子元素的結束標籤必須在父元素的結束標籤之前。大多數的瀏覽器都會忽略這個規則-舉例來說,您可以在HTML的網頁中撰寫如下的程式碼:
<P>The rights <B>of the <I>individual person</B>
outweigh</I> the rights of the collective.
請注意 B 元素開始,然後接著 I 元素開始。但是 B 元素卻在 I 元素之前結束了。程式碼被瀏覽器解譯為下列結果:
The rights of the individual persons outweigh the rights of the collective.
這就是不正確的巢狀排列,這種格式的XML文件會被剖析器立即拒絕。要使用正確的巢狀XML文件到達上述的相同效果,程式碼應該如下所示:
<P>The rights <B>of the <I>individual person</I></B>
<I>outweigh</I> the rights of the collective.</P>
特殊字元
剖析器基於少量的字元判斷哪些屬於XML文件的內容,哪些屬於標記。藉由不斷的搜尋特定的字元,剖析器可以判斷標記和內容的差異。在本章中我們已經使用了三種字元- 左角括弧(<) 、 右角括弧(>) 和 斜線(/) 。如果您想在XML文件的內容中使用特殊字元,又不想讓剖析器將其視為標記的話,您必須使用實體參照(entity reference),實體參照其實是字串,但是剖析器讀取到實體參照字串時會將其解譯為其他的字元。舉例來說,如果您在格式正確的XML文件資料的某處放了一個左角括弧,剖析器會因為無法解譯該符號而產生錯誤訊息。讀到了該左角括弧後,剖析器無法判斷該符號為開始標籤或是結束標籤,請您看看下列的範例:
<P>Paul used the caculation A<B, but I don't agree.</P>
剖析器將會推測在 B 之前的左角括弧為一標籤的開始,在讀至 B 的時候,判斷其為元素名稱,然後讀到了逗點並傳回錯誤,因為逗點並不是正確有效的名稱字元。
如果您希望左角括弧在您的文件中被視為一個字元(例如,代表小於的意思),那麼您必須使用 < 實體參照:
<P>Paul used the caculation A<B, but I don't agree.</P>
另一個我們要探討的字元是 & ,請注意實體參照使用 & 為開頭的字元,但是如果我們要在XML文件中表達 & 這個字元的時候,必須使用 & 實體參照,如下所示:
<P>My AT&T mobile phone is working much better now that they put
the cell antenna on my neighbor's birdhouse</P>
剖析器可以在格式正確的文件中確認五種實體參照:
實體參照
意義
< <(小於符號)
> >(大於符號)
& &(And符號)
' '(單引號)
" "(雙引號)
屬性
有時候元素只有名稱是不夠的,您可以使用屬性來描述XML文件。屬性中包含關於元素的額外資訊,屬性的表現方式為-在元素的開始標籤中以名稱和值的方式成對出現。
<insuranceClaim dateFiled="2000-06-24">
在上例中,屬性名稱為 dateFiled 、屬性值為 2000-06-24 。請注意要使用等於符號(=)分開屬性名稱和屬性值,您也可以在等於符號的一或兩側使用空格。
還有一點要注意的是,屬性值必須包含在引號中。在HTML文件中,如果屬性值只有一個字(沒有空格)的話,並不需要包含在引號中。但是如果您使用XML文件,所有的屬性值都要以引號包含,縱使只有一個字也一樣。您可以使用單引號或雙引號,只要您是成對使用(不能一邊使用單引號、一邊使用雙引號)。
同時您也必須避免在屬性值中使用特定字元。如果您使用單引號包含您的屬性值,您可以在屬性值中使用雙引號為字元;同樣的,如果您使用雙引號包含您的屬性值,您也可以在其中使用單引號:
<driveway length="350'">
<gangster name='Wally "Fingers" Gambino'>
但是如果您必須在屬性值中同時使用單引號和雙引號呢?請使用 ' 或 " 實體參照:
<irish-gangster name='Shawn "Leaft" O'Doull'>
如果您必須在屬性值中使用左角括弧:
<math calculation="A<B">
您不能在結束標籤中使用屬性。
多年以來,許多XML程式設計師(和早期的SGML程式設計師)在指定特定的資訊為元素的內容,或是為屬性的值這個問題上爭論不休。以下是當您決定哪一種格式才適合您的考量因素。
•元素表示的物件如果是購物訂單、產品線等等時,您可以將屬性視為詳細的內容,例如最後一次修改的日期、作者或者貨幣類型等等。換句話說,將屬性想像成元素的修飾方法,就像形容詞修飾名詞一樣。
•在語法上屬性較有效率。最小的元素有七個字元的負載,然而最小的屬性卻只有五個字元的負載。當屬性或元素有長的名稱時,兩者之間的差異就變的非常有趣。
•在W3C Document Object Model(DOM)規範中屬性比元素易於存取;但是在XSL規範中兩者存取方式一樣簡單。
•屬性無法有元素結構。如果一個物件有子物件,該物件必須為元素,不能為屬性。
空元素
之前筆者曾經提到元素必須有開始標籤、結束標籤以及內容,可是在某些情況下您可能會使用沒有任何內容的元素,為什麼您會建立沒有任何內容的元素呢?您記得在HTML中的水平線標籤嗎?您可以使用該標籤在網頁上畫一條水平線,而水平線標籤是沒有任何內容的,同時也因為它沒有內容,您就不需要使用結束標籤,在HTML中的水平線標籤如下所示:
<HR>
在格式正確的XML文件中,HTML中的水平線標籤仍然適用,但是唯一的例外是您必須加入結束標籤,因為剖析器會搜尋 HR 元素的結束標籤,您可以使用下列的程式碼以建立格式正確的 <HR> 標籤:
<HR></HR>
但是這個標籤看起來十分笨拙,因為它並沒有表達出元素的用途,為了要解決這個問題,XML建議標準的程式開發師使用難以了解的SGML功能將開始標籤和結束標籤組合成一個標籤-空元素標籤,看起來就像結束標籤一樣,除了斜線符號在元素名稱的後面,如下所示:
<HR/>
當XML剖析器看到這種類型標籤的時候,它就不會搜尋相對應的結束標籤了。
空元素也可以有屬性,您記得在HTML中的 IMG 標籤嗎?該標籤用於在網頁中插入圖像。縱使 IMG 元素使用 SRC 屬性來指出圖像的路徑,它仍然為一個空元素。要成為格式正確的XML文件,該標籤應該如下列方式表示:
<IMG SRC="/images/hookah.gif"/>
請注意該結束標籤的右角括弧前面有一條斜線(/ >),斜線和右角括弧必須連在一起,它們中間不得有任何字元。
註解
在XML文件的任何地方都可以有註解,註解如下所示:
<!-- Better check these figures before sending the file -->
剖析器會忽略註解,而不會被傳送到應用程式。註解提供了隱藏來源文件資訊的最佳方式。
格式正確文件的範例
本節提供了一些格式正確文件的範例。下列的第一個範例中描述了電腦硬體中部分的設定項目,您可以從元素名稱了解它的涵義,這也是描述式標記的威力!
<configuration type="printer">
<parm name="port">/usr/lpr</parm>
<parm name="driver">/usr/drivers/HP5SIPS</parm>
<parm name="option">sheet feeder</parm>
<configured/>
<online/>
</configuration>
請注意該範例中並沒有XML宣告,如同您在本章前面學到的,XML宣告是選擇性的。
下列的範例顯示了有價值的資訊:
<?xml version="1.0"?>
<Joke author="Groucho Marx">
<Setup>Outside of a dog, a book is man's best
friend.</Setup>
<Punchline>Inside of a dog, it's too dark to
read.</Punchline>
</Joke>
請注意範例中的XML宣告,以及每一個開始標籤都有相對應的結束標籤。
有效合法的XML文件
假設您要提供格式正確的XML文件來形容您最喜歡的笑話-您提供了兩份文件,一份短的和一份長的文件。
<?xml version="1.0"?>
<favorite-joke author="Pate">
<one-liner>A duck walks into a bar and says to the
bartender, "Gimme a shot of whisky and put it on
my bill."</one-liner>
</favorite-joke>
長的笑話比第一個笑話更複雜。
<?xml version="1.0"?>
<duck_joke>
<scene number="1">
A duck walks into a bar, goes up to the bartender,
and says, "Don't you have any grapes?" The
bartender says, "No, this is a bar, of course
we don't have any grapes."
</sence>
<scene number="2">
The next day, the duck walks into a bar, goes
up to the bartender, and says, "Don't you have any
grapes?" The bartender says, "No, like I told
you yesterday, we don't have any grapes."
If you come in here one more time asking for
grapes, I'm going to nail your webbed feet to
that bar!"
</scene>
<scene number="3">
The next day, the duck walks into a bar, goes
up to the bartender, and says, "Don't you have any
nails?" The bartender says, "No, this is a bar,
of course we don't have any nails." Then the
duck says, "Don't you have any grapes?"
</sence>
</duck_joke>
這兩份文件都已經包含足夠的資訊指出每一個元素的意義,第一份文件清楚的描述了作者最喜歡的笑話;第二份文件是一份鴨子的笑話,總共有三種場景。兩份文件都是格式正確,而且XML剖析器在讀取文件時不會產生任何錯誤。
您可以想像,如果要將許多這一類型的文件集合在一起,然後撰寫一支程式將這些笑話載入資料庫的話,要怎麼做呢?然而事實是:現有的這兩份文件對您來說完全沒有用處。為什麼呢?因為沒有一套標準的結構,沒有方法可以預測資料將會如何排列,甚至預測標籤是如何定義的。因此,您也無法撰寫一支可以解譯所有不同笑話的程式。
您必須了解,我們可以了解文件中的涵義是因為我們是人類,而電腦卻不是,它無法如我們一般思考。在電腦處理資料之前,我們必須輔助它了解資料,如果沒有預先定義的正式結構,XML文件就只是一個純文字檔而已。
要輔助電腦解譯這些文件,您可以事先建立一套定義好的結構資訊。電腦就可以利用這些結構資訊為建立XML文件的準則。然後使用這個相容於載入資料庫程式的XML文件。因此我們可以將這個文件的定義資訊想像為建立結構的樣式準則。
樣式準則並不是新的發明,就像記者也有必須遵循報業規則的樣式準則一樣。樣式準則一般而言都有其必須遵循的原則,以記者來說,像是文法風格、避免毀謗和文章的論調等等。樣式準則也會指出文章預期的結構,舉例來說,指定文章的結構必須有標題、作者署名、日期、摘要和文章主體,還有其主體必須依次包含短評等等。
記者將原稿放在打字機中,並且開始輸入文章的主體,她輸入了標題、作者署名和摘要,然後輸入短評。完成後將紙從打字機中移除,並傳送給樓下的編輯。
編輯注意到記者忘記輸入日期,她將原稿傳回樓上。我們發現了什麼?在這個錯誤中涉及了兩個人-昂貴的錯誤。試想如果有一個守護天使在監控著記者的鍵盤,輔助她在文件中留下適當的空格,直到她遵守了所有規則才允許她將原稿從打字機中移除。對XML的建置來說,這個守護天使正是有效合法的XML,而這些規則的集合即為 架構 (Schema)。
文件類別宣告
就如同您在本章開始所學到的,XML規格中定義的有效合法的文件如下:
「如果XML文件由 文件類別宣告 (Document Type Declaration,DTD)加以定義,並且遵從DTD所定義的規則來表現和限制資料,則此XML文件則為有效合法的文件。」
那麼,何謂文件類別宣告?
文件類別宣告會指示XML剖析器到哪裡搜尋規則的集合以斷定文件中的哪些部分必須檢查。這些規則的集合又在哪裡呢?答案就是已經有某些人將文件的特定類別成員結構加以定義,並且描述這些結構以供剖析器使用。剖析器會讀取該結構描述,然後再剖析文件,決定該文件是否格式正確。在XML 1.0中,可以藉由文件類別宣告(DOCTYPE)指向規則的集合,文件類別宣告又稱為 文件類別定義 (Document Type Definition,DTD)。
請注意您現在應該了解格式正確的文件又有了額外的規則:該文件並不只需要遵守先前所列出格式正確文件的條件限制,同時它的結構還必須遵守使用者定義的結構描述。
該結構描述即為 架構 (Schema)。在XML 1.0中,唯一的架構類型即為DTD。DTD是直接取自於SGML的精簡版,並且去除了某些選擇性和難以建置的功能。
經過一番解釋之後,我們回頭看看第一個笑話的DTD:
<!ELEMENT Joke (Setup, Punchline) >
<!ATTLIST Joke author CDATA #REQUIRED
firstTold CDATA #IMPLIED >
<!ELEMENT Setup (#PCDATA) >
<!ELEMENT Punchline (#PCDATA) >
為了建立有效合法的XML文件,而將文件類別宣告放在該笑話文件的頂端以指示包含DTD的實體檔案-Joke.DTD。該檔案應該先讀取,並且Joke文件應該遵守Joke.DTD的結構定義而為一有效合法的文件。
<?xml version="1.0"?>
<!DOCTYPE Joke SYSTEM "Joke.dtd">
<Joke author="Groucho Marx">
<Setup>Outside of a dog, a book is man's
best friend</Setup>
<Punchline>Inside of a dog, it's too dark
to read.</Punchline>
</Joke>
本書主旨為敘述XML,DTD的詳細內容已經超過本書的範圍。許多相關XML的資源都會告訴您相關DTD各個部分的意義和語法。
DTD主要是為了描述舊型遺留系統的文件資訊,筆者在XML和SGML語法中協同DTD工作方面上具有15年的經驗,然而,DTD在電子商務交易的應用能力上卻有某些因素上的限制。
首先,DTD並非為XML語法使用而撰寫,如同您在前面的範例中所見,DTD使用簡潔的語法,語法中奇怪的單字例如 #PCDATA 和 ATTLIST ,這些語法和XML的設計目標並不一致。
另一個問題是DTD只有一種資料類型: TEXT 。我們可以定義包含其他元素或文字的元素。那麼我們如何確定文件的內容是來自正確的號碼或正確的日期呢?剖析器只確認元素中包含的字元,確認特定的字串形成正確的日期是應用程式的工作。
但是XML文件有一個優點,那就是XML在處理資料時是將「資料」和「處理動作」分開的,換句話說,同一份XML文件可以同時讓不同的應用程式進行處理。所有接觸文件的應用程式只要負責確認特定的元素內容或包含特定資料型別的屬性值即可。那麼,如果在應用程式取得文件之前讓剖析器確認資料型別的正確性不是更好嗎?
DTD最後一個主要問題是一份XML文件中只能有一個文件類型以描述整份文件,這樣相當沒有彈性。DTD是為了官方的文件保值管理系統而建立的,當您需要文件遵守嚴密的標準時,DTD是最佳的方式。舉例來說,所有的飛機維護手冊必須有相同的結構,因為安全性是主要的考量。安規工程師、維護人員、甚至法律部門都必須遵照這個設計,錯誤的文件設計結構會導致毀滅性的結果。
然而對於商業文件(例如發票或醫療紀錄等等),最嚴謹的設計卻無法符合其需求。以發票來說好了,如圖4-1所示,典型的發票會有標題資訊,例如發票號碼、日期和客戶編號等等,然後在描述訂購項目之後的範圍也會有買商住址。
我們對於世界上所有的客戶都使用同樣的發票,請您注意發票上的某些部分是無論我們送到哪裡都一樣的,客戶編號、發票號碼和項目等等,對所有的賣商來說都是共用的。然而,在美國、加拿大、日本等等國家都有不同的住址結構標準,如果我們的發票格式中包含所有國家的住址結構,然後再以DTD訂定一份文件類型,那麼發票的格式可能會十分的交錯複雜。
在這裡有一個解決方案-發票使用單一的架構,然後每一個國家的住址標準分別使用一個架構,再將每一個國家的架構插入發票的單一架構中。這樣不是更好嗎?我們可以藉由新的XML語法以及名稱空間達成這個目的。
圖4-1 一份商業文件可以包含其他的文件,圖中這份發票可以傳送至許多不同的國家,其中傳送的每一份發票可以使用不同的方式指定實體的住址資訊。
名稱空間
在說明架構之前,必須先說明W3C建議標準中的「Namespaces in XML」,您可以在 http://www.w3.org/TR/REC-xml-names/ 找到相關資訊。
名稱空間有兩個基本目的:架構結構和資料型別的共用,以及在多重架構環境中可以識別元素名稱為唯一的。名稱空間是設計用於解決資料來源具有相同的名稱,卻代表不同意義的問題。
您可以藉由宣告名稱空間來正確的指出在架構中您所使用文件資訊的精確位置,以提供剖析器正確的資源所在位置。
您可以看看清單4-1中所舉的發票範例,因為該發票是用於書,所以在 invoice 元素的 body 元素中有一個元素 tilte 。然而,在包含地址部分的架構中,也有一個元素名稱為 title ,該元素的意義是表示歡迎訂購該書的讀者(MS., Mr., Dr.等等),此時就出現了兩個 title 元素,卻有分別不同的意義。我們想要使用不同的方式處理它們,此時就是使用名稱空間的時機。
Invoice.xml
<?xml version="1.0"?>
<invoice>
<number>A-99-1443</number>
<customer>RA-81122</customer>
<billto>
<company/>
<contact>
<title>Mr.</title>
<name>Barnes</name>
</contact>
<street1/>
<street2/>
<city/>
<state/>
<zip/>
</billto>
<body>
<line>
<title>The Fountainhead</title>
<quantity>600</quantity>
<price>4.12</price>
</line>
<line>
<title>XML Programming for BizTalk Servers</title>
<quantity>1000</quantity>
<price>49.99</price>
</line>
<line>
<title>1001 Duck-Bar Jokes</title>
<quantity>1000</quantity>
<price>6.34</price>
</line>
</body>
</invoice>
清單4-1 名稱空間的衝突會造成不明確結果的狀況,因為兩個元素具有相同的名稱卻表示不同的意義。本例中分別為書的 title 和歡迎讀者的 title 。
我們需要某種方式來獨立地指出每一個元素,並且使用分別的方式正確處理該元素,使用名稱空間宣告正是這個可以避免名稱空間衝突而產生不明確狀況的方法。名稱空間宣告必須出現在該使用名稱空間的元素之前(或同時),名稱空間的宣告與開始標籤的屬性十分相似。所有的名稱空間宣告必須以 xmlns 為開頭,其後接著一個選擇性的區域空間名稱。
名稱空間宣告屬性的值是一個URL,並且指向定義該文件的架構。
--------------------------------------------------------------------------------
說明
W3C的名稱空間規格指出-「名稱空間的名稱必須符合其預期的目的,並具備唯一性和永久性的目的。直接取得可使用的架構資訊(如果有的話)並不是唯一的目標。為達成這些目標所設計的範例語法在 Uniform Resource Names [RFC2141] 中可以找到。然而,值得注意的是一般的URL可以使用這種方式管理以達成這些相同的目標」。
--------------------------------------------------------------------------------
名稱空間的範例 invoice 開始標籤如下:
<invoice xmlns="http://architag.com/schemas/invoice.xdr">
讀取該發票文件的應用程式會至其列出的資源處取得架構,並且藉由其中包含的規則驗證文件的架構。因為該名稱空間的宣告位於文件的根元素,因此其作用的範圍將會涵蓋整份文件-除非又有其他的名稱空間覆寫原來取得的資訊(稍後將會解釋這部分)。
名稱空間宣告會套用其宣告的元素以及該元素之下的所有子元素,我們可以在文件中任意使用名稱空間,但是只有最新定義的名稱空間會生效。
還有,請您必須注意一點,XML是階層式的語法。文件中所有的元素都在根元素之中,在根元素中的元素都藉由階層式結構與其他的元素相互關聯,因此在父層中的名稱空間會套用至子層的所有元素之中,除非有其他的名稱空間覆寫原來的資訊。覆寫別人的名稱空間宣告會一直保持其效力,直到它所宣告的元素關閉。
現在回到發票範例,我們定義了發票中可以插入住址資訊,這種結構稱為 開放內容模式 (Open Content Model),因為它的結構是開放式的,隨後可填入資訊,下列的文件是受名稱空間宣告影響範圍的範例:
Nsinvoice.xml
<?xml version="1.0"?>
<invoice xmlns="http://architag.com/schemas/invoice.xdr">
<number>21153</number>
<customer>SY221-00</customer>
<date>2000-01-24</date>
<address xmlns="http://xml.org/schemas/us-address.xdr">
<street>750 Davis Street</street>
<city>San Francisco</city>
<state>CA</state>
<zipcode>94107</zipcode>
</address>
<body>
<item num="YI-2289" qty="100" price="23.11"/>
<item num="WD-7198" qty="35000" price=".137"/>
<item num="ER-3211" qty="120" price="112.00"/>
</body>
</invoice>
清單4-2 在發票中的當位置使用名稱空間技術插入住址資訊。
請注意清單4-2的根元素 invoice 中包含了名稱空間屬性,並且其子元素 address 中也包含了自身的名稱空間資訊。如果您檢查 xmlns 中所指的文件,您會發現在 invoice 名稱空間中定義了如 number 、 customer 、 date 元素的資訊等等;如果您檢查 address 的名稱空間,您會發現如 street 、 city 、 state 和 zipcode 等資訊。
當您宣告名稱空間的時候,在父層範圍中的子元素會變成名稱空間的一部份。這稱為預設的名稱空間(default namespace)。但是如果您想要在一個元素範圍內混合名稱空間時要怎麼做呢?舉例來說,如果您想要讓 invoice 元素中的 date 元素有不同的資料型別宣告要怎麼辦?
您可以在 invoice 元素的開始標籤宣告其他的名稱空間,因為您一次只能定義一個預設的名稱空間,因此次要的名稱空間必須指定一個名稱空間前置字(prefix)。然後您可以在宣告次要名稱空間元素的開始標籤中附加此前置字於元素名稱之前,直到該元素結束標籤之前都屬於次要名稱空間的範圍。
清單4-3顯示相同的 invoice 元素中有多重名稱空間前置字,兩個名稱空間指出到何處搜尋元素的描述(元素的描述即為架構)。
Mnsinvoice.xml
<?xml version="1.0"?>
<invoice xmlns="http://architag.com/schemas/invoice.xdr"
xmlns:dt="http://schemas.com/schemas/datatypes.xdr">
<number>21153</number>
<customer>SY221-00</customer>
<date dt:type="date">2000-01-24</date>
<address xmlns="http://xml.org/schemas/us-address.xdr">
<street>750 Davis Street</street>
<city>San Francisco</city>
<state>CA</state>
<zipcode>94107</zipcode>
</address>
<body>
<item num="YI-2289" dt:qty="100" dt:price="23.11"/>
<item num="WD-7198" dt:qty="35000" dt:price=".137"/>
<item num="ER-3211" dt:qty="120" dt:price="112.00"/>
</body>
</invoice>
清單4-3 一張發票使用多重名稱空間。
請注意次要名稱空間的描述在第3行,該宣告指定您可以在 invoice 元素範圍中的任何地方使用該名稱空間,但是您必須在欲宣告元素的開始標籤和屬性中明確地指定該名稱空間。在第6行 date 元素的屬性使用 dt 名稱空間,本範例中,在 datatype 架構中的 type 屬性設定為 date 。請注意 dt 名稱空間也用於 body 元素屬性的14-16行中。
另一種名稱空間的指定方式為在所有的元素中使用名稱空間前置字,如清單4-4所示,這樣可以消除預設名稱空間都在一起的缺點。
Prefixns.xml
<?xml version="1.0"?>
<inv:invoice xmlns:inv="http://architag.com/schemas/invoice.xdr"
xmlns:dt="http://schemas.com/schemas/datatypes.xdr">
<inv:number>21153</inv:number>
<inv:customer>SY221-00</inv:customer>
<inv:date dt:type="date">2000-01-24</inv:date>
<addr:address xmlns:addr="http://xml.org/schemas/us-address.xdr">
<addr:street>750 Davis Street</addr:street>
<addr:city>San Francisco</addr:city>
<addr:state>CA</addr:state>
<addr:zipcode>94107</addr:zipcode>
</addr:address>
<inv:body>
<inv:item inv:num="YI-2289"
dt:qty="100" dt:price="23.11"/>
<inv:item inv:num="WD-7198"
dt:qty="35000" dt:price=".137"/>
<inv:item inv:num="ER-3211"
dt:qty="120" dt:price="112.00"/>
</inv:body>
</inv:invoice>
清單4-4 名稱空間前置字可用於任何元素之前,這樣會顯示哪個元素屬於哪個名稱空間,但是會增加複雜度。
架構
自從XML 1.0建議標準在1998年2月公佈後,W3C一直致力於取代DTD描述架構的其他規格。於是推出了 XML Schema 為最後階段的版本,該標準被視為2000年前半年的 候選標準 (Candidate Recommendation)。
W3C XML Schema Working Group將焦點放在3個主要的改善重點:
•以XML語法撰寫架構,此目標可讓使用者以相同的工具處理XML文件。
•讓新的架構標準支援一些共用的資料型別,例如 number 、 date 和 currency 等等,並且可以支援使用者自訂的資料型別。這個改良可以使應用程式驗證資料的負擔轉嫁給XML剖析器,所有讀取XML文件的應用程式可以存取資料。
•讓XML Schema具有開放內容模式,試想我們的發票需要有彈性的住址資訊。XML Schema將允許使用者定義發票資訊的架構,該架構中有一個稱為「hole」的區塊可放置住址資訊。然後使用者便可以使用描述住址資訊的任何架構插入發票的架構中。
--------------------------------------------------------------------------------
說明
W3C遵守稱為Datatypes for DTDs(DT4DTD)的規格,該規格將新增支援DTD的資料型別,為DTD語法的補強,可以供想要繼續利用DTD存取更多資料型別的使用者使用。當然,要以XML剖析器必須支援為前提。
--------------------------------------------------------------------------------
W3C架構也具有DTD不具備的其他功能。
XML Data Reduced
Microsoft為XML早期的提倡者,並且已經參與W3C的XML規格制定一段時間,在此期間也參與許多XML相關的社群,並且提出了許多技術展望規格。1998年1月,Microsoft、DataChannel、ArborText和Inso提出代替一項架構的語法,稱為XML Data。該語法達成了上述的3大目標,並包含數個新的項目。
1998年12月,Microsoft公佈了Internet Explorer 5,其中內建COM物件剖析器稱為MSXML。MSXML包含XML Data的精簡版,稱為 XML Data Reduced 或 XDR 。
縱使W3C XML Schema Working Group仍然致力於它們的官方架構,Microsoft建議XDR為BizTalk的架構語法。然而,Microsoft表明一旦W3C Schema的語法(Dubbed XSD)成熟就會配合該標準規格。
您應該使用數個月前的XML Data架構標準嗎?如果您使用目前的BizTalk和XML Data撰寫程式,您未來還需要重寫程式嗎?答案是「不用」。Microsoft和其他的賣商將會提供將XDR轉換為XSD語法的工具,因為兩種語法有相同的目標,因此在電腦中將一種語法轉換為另一種是微不足道的小事。因為所有的語法都是XML語法,XSL(Extensible Stylesheet Language)可以用於將一個架構語法轉換為另一個。
Extensibility, Inc.有一套稱為XML Authority的工具( http://ww.extensibility.com )也可以讓您建立和維護架構。使用該產品,您可以使用圖形化方式建立架構而不用擔心最終的語法形式。它會強調重要的地方,並且定義邏輯階層以呈現您的資料,也可以撰寫任何架構語法,它甚至可以讀取一種語法,並且儲存成另一種語法,圖4-2中顯示該工具。
您也可以建立格式正確的文件範例,然後XML Authority將會使用該文件建立架構,它也可以從COM物件、Java Classes和ODBC資料來源中建立架構。
圖4-2 Extensibility, Inc.的XML Authority工具
在Microsoft Developer Center( http://msdn.microsoft.com/xml )中有XML Data Reduced的語法。清單4-5顯示了XDR架構的範例。
Joke.xdr
1 <?xml version ="1.0"?>
2 <Schema name="Joke.xdr"
3 xmlns="urn:schemas-microsoft-com:xml-data"
4 xmlns:dt="urn:schemas-microsoft-com:datatypes">
5 <ElementType name="joke" content="eltOnly" order="one">
6 <AttributeType name="author" dt:type="string"
7 required="yes"/>
8 <AttributeType name="firstTold" dt:type="dateTime.tz"/>
9 <AttributeType name="rating" dt:type="enumeration"
10 dt:values="G PG R NC-17" required="yes"/>
11 <attribute type="author"/>
12 <attribute type="firstTold"/>
13 <attribute type="rating"/>
14 <element type="one-liner"/>
15 <element type="story"/>
16 <element type="setup-punchline"/>
17 </ElementType>
18
19 <ElementType name="one-liner" content="textOnly"/>
20 <ElementType name="story" content="eltOnly" order="seq">
21 <element type="scene" minOccurs="1" maxOccurs="*"/>
22 </ElementType>
23
24 <ElementType name="setup-punchline" content="eltOnly"
25 order="seq">
26 <element type="setup"/>
27 <element type="punchline"/>
28 </ElementType>
29
30 <ElementType name="scene" content="textOnly"/>
31 <ElementType name="setup" content="textOnly"/>
32 <ElementType name="punchline" content="textOnly"/>
33 </Schema>
清單4-5 XML Data Reduced(XDR)架構的範例
行
說明
1 該架構為XML文件
2 Schema 為根元素的開始標籤,該架構的名稱包含在 name 屬性中。
3-4 XDR架構規格包含兩個名稱空間,一個為結構名稱空間,另一個為定義用於架構中的資料型別。
5-17 ElementType 元素宣告一個元素並指出它的內容。在本例中,我們宣告了 joke 元素,屬性指出了 joke 元素只包含元素( content="eltOnly" ),且該元素只能包含一個列出的子元素( order="one" )。
6-7 屬性使用 AttributeType 元素加以宣告,此處的 author 屬性宣告為string資料型別( dt:type="string" )。當 joke 元素開始後, author 屬性為必須的( required="yes" )
8 firstTold 屬性被宣告為包含有效日期, datetime.tz 資料型別是由XDR規格定義,為ISO 8601標準的一個子集,該標準用於指定日期、時區。語法看起來像這樣:2000-04-25T09:00-08:00。 firstTold 屬性不是必須的。
9-10 rating 屬性的資料型別為 enumerated ,這表示它只能為在 dt:values 屬性的值清單中指定的其中之一。在本範例中,該值只能為"G", "PG", "R"或"NC-17"中的其中一個, rating 屬性是必須的。
11-13 每一個元素的屬性宣告後,它們必須被置於 attribute 元素中。
14-16 elemen t元素指定可以被置於 joke 元素中的元素,請記得 ElementType 的 content 屬性指定在父層元素內只能包含這三個元素的其中之一。這些元素中的每一個必須使用它自己的 ElementType 元素加以宣告。
24-28 宣告 setup-punchline 元素,屬性 order="seq" 指定在此列出的元素必須以它們宣告的順序出現。列出的元素為 setup 和 punchline 元素,因此在文件中, setup-punchline 元素必須以一個 setup 接著一個 punchline 元素組成。
30-32 這三個元素只能為文字。
表4-1 說明清單4-5中的架構
W3C XML Schema Working Group依然不斷致力於XML Schema的語法,2000年4月,公佈了Working Drafts of XML Schema Parts 1、2和3。XML Schema提供了XML 1.0 DTDs特性的超集合(superset),BizTalk率先使用XDR為描述XML文件的語法。
在XSD和XDR之間的主要差異在於架構文件的實際語法。然而,兩者之概念是相同的。Microsoft已經允諾當XSD成熟時會配合XSD各方面的建置工作,無論其為候選標準或最後的建議標準。 |