你現在應該知道XML只說明數據的結構而并不關心數據是如何具體描述的、數據是否正確。XML文檔的強制性結構化需求是通過DTD(文檔類型說明)來實現的。那就是本系列文章中先前講述的主題。在本文里,我們概要介紹DTD所存在的缺點,討論新型的更為強大的標準XML Schema。
DTD的麻煩
使用DTD雖然在指定許可的元素、需要的元素以及給定XML文檔中如何組織元素等方面給我們以較大的方便,但是,一旦你想針對特定元素施加數據類型就會遇到麻煩了。DTD規范嚴格地定義了結構,但只支持相對功能較弱的內容類型規范,而對強制性結構化卻無計可施,比如名為Date 的數據如何規定它必須包含有效值呢?
這就要指望XML Schema了,XML Schema目前作為建議已經于2001年提交給了W3C ,這意味著它最終將成為一般用途的建議標準。假如你對此感興趣,你不妨到W3C網站找些官方文檔和內容簡介之類的材料來看看。注意,其他schema定義也是有的,包括日本的標準RELAX 和微軟公司的XDR。可是,XML Schema是唯一受到W3C成為的建議標準,所以我在這篇文章中只對它進行闡述。
XML Schema不僅可以讓你定義XML文檔的結構而且還允許你約束文檔的內容,這就不同于DTD了。另外,一個 XML Schema自身就是一個XML文檔,其基于標簽的語法比DTD中的特殊字符要清楚多了。
Schema概述
XML Schema是用一套預先規定的XML元素和屬性創建的,這些元素和屬性定義了文檔的結構和內容模式。相應的一套精巧的規則(這些規則卻很有意思的用DTD來表示)指定了每個Schema元素或者屬性的合法用途。如果違反這些規則解析器就會拒絕解析你的Schema以及任何同它相聯系的文檔。
現在讓就讓我們來看看清單A中顯示的XML Schema示例,該例對我們以前在清單B中用到的圖書目錄進行了說明。清單B有了點小改動:作為根元素的catalog現在有了兩個新屬性,它們通過清單A中的catalog schema與之關聯。
你再看catalog schema,很快你就會注意到它包含了標準的XML頭<?xml version = "1.0"?>,這表示schema自己就是一個XML文檔。而任何schema的根元素都必須是schema,它有一個或者多個說明自己的屬性。在這種情況下,schema的namespace定義屬性(xmlns)會定義名稱空間為xs,它將用作文檔中所有元素的根名稱空間。
--------------------------------------------------------------------------------
什么是名稱空間
XML把名稱空間定義為包裝XML元素在一起供以后重用的方式。為了使用XML文檔的名稱空間中定義的元素,你必須通過xmlns屬性聲明你希望采用名稱空間。你還必須為該名稱空間定義快捷方式的前綴(例如xs:)作為你文檔中的根元素,從而使得名稱空間在文檔中都可用。前綴是用于文檔的任何導入名稱空間的元素的標識符。這一過程就如同在Visual Basic中給庫加索引或者導入模塊;C++、Java或者.NET下的名稱空間也具有同樣的含義。
--------------------------------------------------------------------------------
我們的schema示例中接下來的元素是annotation,它的作用是代表同其父元素有關的文檔。annotation可以包含兩個子元素之一,或者是documentation或者是appinfo,或者兩者都包含進去。前者用于可讀的文檔,而后者則用來保存供應用程序處理的指令。
接下來我們定義了兩個主要的元素(根元素catalog及其子元素book),它們用在書目文檔內,后者采用了兩個element元素。這些元素都包含了定義名字的屬性和各個元素準許的內容。在這種情況下,catalog元素被定義為catalogtype類型,而book元素則被定義為elementtype類型;這兩種類型以后還要在schema文檔中被定義。
什么是類型?
我已經說過了,XML Schema可以讓你把XML文檔中的元素聲明為特定的類型,準許解析器檢查文檔的內容及其結構。XML Schem定義了兩種主要的數據類型:預定義簡單類型和復雜類型。這兩種數據類型之間的主要區別是復雜類型可以象數據一樣包含其他元素而簡單類型則只能包含數據。簡單類型給予了XML Schema低級類型檢查能力,允許你把元素定義為圖A中的任何類型之一。
圖A
簡單類型 定義
string 字符串數據。
boolean 二元類型的True或者False。
date 歷法日期,格式是CCYY-MM-DD。
dateTime 歷法日期和時間。
time 24小時格式的時間可根據時區調節。
decimal 任意精度和位數的十進制數。
integer 整數
float 標準的32位浮點數。
XML Schema預定義簡單類型
你也可以定義自己的簡單類型。為了更深入地了解各種XML Schema數據類型,請參看W3C網站上的“XML Schema Part 2: DataTypes”。
復雜類型由complexType元素定義,它通常至少擁有一個name屬性,用在聲明其他元素時索引類型,除非它位于某一元素之內(參見下一節)。所有的復雜類型都會包含一個內容定義類型,其主要功能是定義類型能包含的內容模式。某些可用的內容模式請見圖B。
圖B
復雜類型 定義
sequence 在其定義范圍之內的所有元素都必須按順序出現,范圍由minOccurs和 maxOccurs指定。
choice 其范圍內有且只有一個元素必須出現。
any 定義的任何元素都必須出現。
simpleContent 這種復雜類型只包含了非嵌套元素。可以通過包含擴展元素的方式擴展先前定義的簡單類型。
complexContent 這種復雜類型只能包含其他元素。可以通過包含擴展元素的方式擴展先前定義的復雜類型。
attribute 這種復雜類型只能包含命名屬性。
一些準許的XML Schema復雜類型
我們示例schema中的第一個complexType元素定義了booktype類型,你能從文檔注釋元素中看出,該類型給目錄中單一的書建模型。Booktype包含一個sequence元素,通過它告訴解析器這種復雜類型的元素必須按照同樣準確的順序包含出現在sequence標簽內出現的所有元素。就booktype而言,元素author、title、genre、price和publish_date都必須出現在 booktype元素之內。
Description又是怎么一回事呢?它出現在sequence元素內,有沒有這個必要呢?當然沒有。description元素有一個minOccurs屬性,它定義了復雜類型中元素可以出現的最小次數。在這種情況下,minOccurs的值是零,因此description是一個可選的元素。
author元素也是這樣。它有一個maxOccurs屬性,但卻沒有設值,意思是說author元素可以在sequence中出現無限次,顯然,一本圖書的作者至少有一個但卻不一定只有一個。既沒有minOccurs也沒有maxOccurs屬性的元素必須而且僅僅只能在sequence中出現一次,因此,booktype sequence中的所有其他元素都是必要的而且只能出現一次。
在我們的示例catalog schema中定義的第二個同時也是最后一個復雜類型是catalogtype復雜類型。它也是包含一個以上的sequence,你可以從無界的maxOccurs屬性看出這一點。
深入解釋
看你的背景知識有多少了,本文用到的示例schema的結構對你來說要不本該如何要不只會叫你發昏,對book和catalog元素不采用正規復雜類型聲明來定義catalog schema也是可能的,清單C就是這樣。注意,清單C中的complexType元素嵌套在了element元素之內,catalog的sequence元素的子元素具有一個ref屬性通過它告訴解析器它有一個引用指向先前定義的book元素。
我曾經聽到很多人這樣問:“很好,如果是這樣的話,那么你為什么要采用以上那些費工夫的辦法呢?”很簡單,我們繞來饒去只是為了說明XML Schema的重要一點:它是可擴展的。通過定義類型的方式你就可以在多個文檔中重用它們,甚至還可以用不同的schema對其進行擴展,這就像你在開發應用程序的時候重用或者擴展抽象數據類型或對象是一個道理。
工具
到目前為止,你應該意識到XML Schema的語法并不簡單。雖然可以用簡單的文本編輯器手工創建schema,不過,這樣做也許會叫你累得吐血。為了更好地利用它,你可以采用若干種XML工具,最近出現的一些工具甚至提供了創建XML Schema的圖形界面。XML Spy和Cape Clear Studio都是具有XML Schema創建功能的全方位XML綜合開發環境。dtd2xs是一種DTD-to-XML的Schema轉換工具,它有兩種形式:單獨運行的應用程序和Java類。同DTD一樣,標準的XML Schema定義非常多,你可以根據自己的需要在應用程序的開發中采用。
結論
XML Schema具有強制文檔內容和結構的能力,它是XML世界中的一種不但重要而且強大的新標準。在這篇文章里,我僅僅浮光掠影地大致解釋了其基本原理,但我希望這些闡述能給你打下一個繼續前進的基礎。