XML定義語言:DTD,XDR和XSD
我們知道XML文檔有格式良好和有效性兩種約束。格式良好適合于所有的XML文檔,即滿足XML標(biāo)準(zhǔn)中對于格式的規(guī)定。而當(dāng)XML文檔滿足一定的語義約束則稱該XML文檔為有效的XML文檔。目前常用的XML定義語言有DTD,XDR和XSD。
文檔類型定義(DTD)
文檔類型定義用不同于XML的獨立語法來規(guī)定了XML文檔中各種元素集合的內(nèi)容模式。該語言直接沿襲了定義SGML語言的方法。
Schema
類似DTD,Schema可以規(guī)定一套特定文檔的結(jié)構(gòu)或模型。使用Schema語言來描述文檔結(jié)構(gòu)有下面以下好處:
XDR
XDR的全稱是XML-Data Reduced Language,是早先由XML-Data草案派生出來的一個定義XML語言的分支。由于微軟最先提出了XML-Data,并且經(jīng)過修訂后在其軟件中應(yīng)用,所以XDR也被廣泛使用。目前支持XDR Schema的產(chǎn)品有:
XDR也得到了Extensibility的 XML Authority編輯工具的支持。
XSD Schema
最為正式的XML Schema語言是由W3C指定的XML Schema規(guī)范,簡稱為XSD(XML Schema Definition)。XSD也提供了數(shù)據(jù)類型的支持和結(jié)構(gòu)定義的方法。
2001年5月2日,XML Schema 規(guī)范成為了W3C的正式推薦標(biāo)準(zhǔn)。這就意味著經(jīng)過三年多的發(fā)展,XML 的Schema標(biāo)準(zhǔn)終于修成了正果。這樣,XML、XML Schema和Namespace都成為了W3C的正式,這是一個值得慶賀的歷史性時刻,意味著XML語法的規(guī)范已經(jīng)奠定了扎實的基礎(chǔ)。XML的廣泛發(fā)展和應(yīng)用也即將成為現(xiàn)實。下面我們就將重點來介紹最新的XML Schema標(biāo)準(zhǔn)。
XML Schema的全貌
我們用實際的例子來介紹XML Schema的用法。比如,有這樣的XML實例文檔:
<?xml version="1.0" encoding="GB2312"?>
<!DOCTYPE studentlst SYSTEM "student.dtd">
<studentlst>
<student>
<name>至尊寶</name>
<genda>男</genda>
<sid>001</sid>
<birthday>1576-3-2</birthday>
</student>
<student>
<name>白晶晶</name>
<genda>女</genda>
<sid>002</sid>
<birthday>1578-4-25</birthday>
</student>
</studentlst>
該文檔用DTD定義如下:
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT studentlst (student)*>
<!ELEMENT student (name, genda, sid, birthday)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT genda (#PCDATA)>
<!ELEMENT sid (#PCDATA)>
<!ELEMENT birthday (#PCDATA)>
但是其中name和genda、sid等文本元素的數(shù)據(jù)類型都是統(tǒng)一的字符類型,而事實上我們一般要求對它們有更為嚴(yán)格的限制。比如,要求name仍然為字符類型,而genda為可選的枚舉類型,只能取男或女,sid要求是三位的整數(shù)類型,并且要求birthday為日期類型。name和birthday的定義比較簡單:
<element name="name" type="string" minOccurs="1" maxOccurs="1/">
<element name="birthday" type="date" minOccurs="1" maxOccurs="1/">
其中string和date類型都是Schema中自帶的基本數(shù)據(jù)類型(Primary Data Type)。minOccurs和maxOccurs是最少和最多出現(xiàn)次數(shù),這里是表示有而且只出現(xiàn)一次。這是最簡單的元素聲明。在XML Schema中提供兩種數(shù)據(jù)類型:一是我們剛剛接觸的基本數(shù)據(jù)類型或者稱為內(nèi)建數(shù)據(jù)類型;另外一種是擴展的數(shù)據(jù)類型,既在基本數(shù)據(jù)類型基礎(chǔ)上用戶自己擴展的數(shù)據(jù)類型。Schema中沒有規(guī)定性別的類型,也沒有直接規(guī)定三位整數(shù)的數(shù)據(jù)類型,但是性別是有男、女兩種選擇的枚舉類型;而sid的每位都是非負整數(shù),于是我們可以先定義兩類擴展數(shù)據(jù)類型,然后來限制genda和sid元素。
<simpleType name="GendaType">
<restriction base="string">
<enumeration value="男"/>
<enumeration value="女"/>
</restriction>
</simpleType>
<simpleType name="SIDType">
<restriction base="string">
<length value="3"/>
<pattern value="\d{3}"/>
</restriction>
</simpleType>
在定義擴展數(shù)據(jù)類型時是描述了一個simpleType元素,name屬性是該數(shù)據(jù)類型的名稱,數(shù)據(jù)類型由restriction子元素進行約束,該元素中的base屬性是基類型,即它要擴展的基本數(shù)據(jù)類型。在枚舉類型中在restriction的子元素中羅列初可選的數(shù)值;而在第二種情況時,通過對各方面(facet)進行規(guī)定來定義數(shù)據(jù)類型,比如length規(guī)定該數(shù)據(jù)類型總共有多少位數(shù),而pattern則通過正則表達式來規(guī)定出現(xiàn)的方式。這里的意思是連續(xù)出現(xiàn)三位的整數(shù)。
用上面定義的數(shù)據(jù)類型來約束genda和sid的方法和name和birthday元素的聲明相同:
<element name="genda" type="GendaType" minOccurs="1" maxOccurs="1"/>
<element name="sid" type="SIDType" minOccurs="1" maxOccurs="1"/>
有了最基本的四個文本內(nèi)容的元素,如何定義作為其父元素的student元素呢?由于student元素是由子元素組成的,在Schema中稱它位復(fù)雜類型的元素。而且其子元素是順序組成的序列,因此這樣聲明student元素:
<element name="student">
<complexType>
<sequence>
<element name="name" type="string" minOccurs="1" maxOccurs="1"/>
<element name="genda" type="GendaType" minOccurs="1" maxOccurs="1"/>
<element name="sid" type="SIDType" minOccurs="1" maxOccurs="1"/>
<element name="birthday" type="date" minOccurs="1" maxOccurs="1"/>
</sequence>
</complexType>
</element>
另外,studentlst元素包含了student元素,并且出現(xiàn)的方式是一個或者多個,或者可以不出現(xiàn),在Schema中出現(xiàn)的方式可以用miOccurs和maxOccurs來表達:
<element name="studentlst">
<complexType>
<sequence>
<element name="student" minOccurs="0" maxOccurs="unbounded">
<complexType>
<sequence>
<element name="name" type="string" minOccurs="1" maxOccurs="1"/>
<element name="genda" type="GendaType" minOccurs="1" maxOccurs="1"/>
<element name="sid" type="SIDType" minOccurs="1" maxOccurs="1"/>
<element name="birthday" type="date" minOccurs="1" maxOccurs="1"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
最后我們將這些元素和數(shù)據(jù)類型的聲明都包含在schema根元素中:
<?xml version="1.0"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:sl="http://www.xml.org.cn/namespaces/StudentList" targetNamespace="http://www.xml.org.cn/namespaces/StudentList">
<element name="studentlst">
<complexType>
<sequence>
<element name="student" minOccurs="0" maxOccurs="unbounded">
<complexType>
<sequence>
<element name="name" type="string" minOccurs="1" maxOccurs="1"/>
<element name="genda" type="sl:GendaType" minOccurs="1" maxOccurs="1"/>
<element name="sid" type="sl:SIDType" minOccurs="1" maxOccurs="1"/>
<element name="birthday" type="date" minOccurs="1" maxOccurs="1"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
<simpleType name="GendaType">
<restriction base="string">
<enumeration value="男"/>
<enumeration value="女"/>
</restriction>
</simpleType>
<simpleType name="SIDType">
<restriction base="string">
<length value="3"/>
<pattern value="{3}"/>
</restriction>
</simpleType>
</schema>
用XSD校驗XML
由了XML Schema,你可以用來校驗XML文檔的語義和結(jié)構(gòu)。在MSXML 4.0技術(shù)預(yù)覽版本已經(jīng)提供了用XSD Schema來校驗XML文檔的功能。在校驗文檔時,將schema添加到XMLSchemaCache對象中,設(shè)置其 object, set the schemas property of a DOMDocument對象的schemas屬性引用XMLSchemaCache對象中的schema。在將XML文檔載入到DOMDocument對象中時將自動執(zhí)行校驗操作。我們不妨用例子來說明如何在Visual Basic中通過編程實現(xiàn)XML文檔校驗。其中包括:
books.xsd
用來校驗books.xml文件的Schema
books.xml
該文件將被載入并且和books.xsd對照校驗
Visual Basic校驗代碼
創(chuàng)建一個XMLSchemaCache對象,將schema添加給它,然后設(shè)置schemas property of the DOMDocument對象的shemas屬性。在開始的時候你要進行如下操作:
打開Visual Basic 6.0,選擇Standard EXE新項目
在Project菜單中選擇References.
在Available References列表中選擇Microsoft XML,v4.0
給Form1添加一個Command button
存儲該項目
books.xml
在XML編輯器甚至一般的文本編輯器中輸入以下XML代碼,并且存為books.xml:
<?xml version="1.0"?>
<x:catalog xmlns:x="urn:books">
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer‘s Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications with XML.</description>
<title>2000-10-01</title>
</book>
</x:catalog>
books.xsd
下面是本例中使用的books.xsd schema。
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="catalog" type="CatalogData"/>
<xsd:complexType name="CatalogData">
<xsd:sequence>
<xsd:element name="book" type="bookdata" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="bookdata">
<xsd:sequence>
<xsd:element name="author" type="xsd:string"/>
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="genre" type="xsd:string"/>
<xsd:element name="price" type="xsd:float"/>
<xsd:element name="publish_date" type="xsd:date"/>
<xsd:element name="description" type="xsd:string"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string"/>
</xsd:complexType>
</xsd:schema>
Visual Basic校驗代碼
你可以運行下面的例子:
拷貝下面的代碼到Command1_Click過程中
Private Sub Command1_Click()
Dim xmlschema As MSXML2.XMLSchemaCache
Set xmlschema = New MSXML2.XMLSchemaCache
xmlschema.Add "urn:books", App.Path & "\books.xsd"
Dim xmldom As MSXML2.DOMDocument
Set xmldom = New MSXML2.DOMDocument
Set xmldom.schemas = xmlschema
xmldom.async = False
xmldom.Load App.Path & "\books.xml"
If xmldom.parseError.errorCode <> 0 Then
MsgBox xmldom.parseError.errorCode & " " & xmldom.parseError.reason
Else
MsgBox "No Error"
End If
End Sub
執(zhí)行該程序,然后點擊Command1按鈕,將返回"No Errors"消息框
XML Schema和名域
Schema是一些規(guī)則的集合(也稱為語法或者語匯),其中包括了類型定義(簡單和復(fù)雜類型)以及元素和屬性聲明。由于XML中可能存在不同的語匯來描述不同的元素和屬性,因此需要使用名域(namespace)和前綴來避免元素和屬性聲明之間的模糊性。當(dāng)你使用來自多個名域的schema時,分清元素和屬性名稱是最基礎(chǔ)性的工作。
一個名域通常有一串字符串來相互區(qū)別,如 "urn:www.microsoft.com", "http://www.xml.org.cn", "http://www.w3c.org/2001/XMLSchema"以及 "uuid:1234567890"等。
XML Schema的序言
XML schema的開頭時是一些導(dǎo)言,之后才是正式的聲明。在schema 元素的導(dǎo)言中可能包含三個可選的屬性。
例如,下面的語法使用的schema元素引用了三個最常使用的名域:
<schema
xmlns="http://www.w3c.org/2001/XMLSchema" xmlns:xsd="http://www.w3c.org/2001/XMLSchema-datatypes" xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instances"
version"1.0">
</schema>
前兩個屬性用XML名域來標(biāo)識W3C中的兩個XML schema規(guī)范。第一個 xmlns屬性包含了基本的XML schema元素,比如element, attribute, complexType, group, simpleType等。第二個xmlns屬性定義了標(biāo)準(zhǔn)的XML schema屬性類型例如string, float, integer, 等。
缺省名域
對于任何一個XML Schema定義文檔(XSD)都有一個最頂層的schema (XSD)元素。而且該schema (XSD)元素定義必須包含下面的名域:
http://www.w3.org/2001/XMLSchema
作為名域的標(biāo)識符(在聲明中作為元素或?qū)傩缘那熬Y),你也可以不使用xsd或xsi。
我們分別來觀察XSD和XML實例文檔中相關(guān)的名域。比如前面介紹student.xsd的序言是這樣的:
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:sl="http://www.xml.org.cn/namespaces/StudentList" targetNamespace="http://www.xml.org.cn/namespaces/StudentList">
這里的targetNamespace屬性表示了該shema所對應(yīng)的名域的URI。也就是說在引用該Schema的其它文檔中要聲明名域,其URI應(yīng)該是targetNamespace的屬性值。例如在這里因為要用到student.xsd自己定義的擴展數(shù)據(jù)類型,所以也聲明的名域xmlns:sl="http://www.xml.org.cn/namespaces/StudentList"。
我們再來看由該schema規(guī)定的XML文檔的開頭將是什么樣子:
<studentlst xmlns="http://www.xml.org.cn/namespaces/StudentList"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.xml.org.cn/namespaces/StudentList student.xsd">
其中缺省名域聲明xmlns="http://www.xml.org.cn/namespaces/StudentList"就是和剛剛聲明的XML Schema的名域相結(jié)合來規(guī)定該XML文檔。xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 是任何XML實例文檔固有的名域,當(dāng)然按照前面所說的名域名稱xsi是可以自己規(guī)定的。而xsi:schemaLocation="http://www.xml.org.cn/namespaces/StudentList student.xsd"則規(guī)定了該名域所對象的schema的位置,即在相同路徑的student.xsd文件。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=78882