使用 XML Schema 定义元素的基本知识
XML Schema 比 DTD 更強大。為了說明 XML Schema 機制的強大功能,下面三個程序清單簡要比較了表示元素的不同方式。 清單 1給出了一個 XML 文檔片段, 清單 2用 DTD 語法聲明了這兩個元素, 清單 3則是相應(yīng)的 XML Schema 語法形式。要注意, 清單 3中所用的是相同的 XML 語法。通過模式,驗證解析器可以檢查元素 InvoiceNo 是否是正整數(shù),元素 ProductID 的首字符是否為 A 到 Z 之間的字母,后面為六個阿拉伯數(shù)字。相反,引用 DTD 的驗證解析器只能檢查這些元素是否用字符串表示。
清單 1:XML 文檔片段
| 以下是引用片段: <InvoiceNo>123456789</InvoiceNo> <ProductID>J123456</ProductID> |
?
清單 2:描述清單 1 中元素的 DTD 片段
| 以下是引用片段: <!ELEMENT?InvoiceNo?(#PCDATA)> <!ELEMENT?ProductID?(#PCDATA)> |
?
清單 3:描述清單 1 中元素的 XML Schema
| 以下是引用片段: <element?name='InvoiceNo'?type='positive-integer'/> <element?name='ProductID'?type='ProductCode'/> <simpleType?name='ProductCode'?base='string'> <pattern?value='[A-Z]{1}d{6}'/> </simpleType> |
?
在 XML Schema 中使用名稱空間
在這個協(xié)作的世界中,一個人可能處理來自多個其他團體的文檔,而不同的團體可能希望以不同的方式表示他們的數(shù)據(jù)元素。此外,他們還可能在一個文檔中引用不同團體創(chuàng)建的同名元素。如何區(qū)分相同名字的不同定義呢?XML Schema 使用名稱空間區(qū)分這些定義。
附:
DTD 的局限性
(盡管作為描述結(jié)構(gòu)化信息的一種機制,DTD 成功地為 SGML 和 HTML 開發(fā)人員服務(wù)了 20 年,但與 XML Schema 相比,它存在著嚴重的局限性。
DTD 要求元素由以下三種成分組成:
文本字符串
文本字符串與其他子元素的混合
一組子元素
DTD 不使用 XML 語法,對類型和名稱空間僅提供有限的支持。
一個給定的 XML Schema 定義了一組新名字,如元素名、類型名、屬性名、屬性組名,這些名字的定義和聲明都寫在模式中。 清單3定義的名字包括 InvoiceNo 、 ProductID 和 ProductCode 。
我們說模式中定義的名字屬于它的 目標名稱空間。名稱空間本身有一個固定但沒有限制的名字,必須符合 URL 語法。比如,對于清單3中模式片段,您可以把名稱空間的名字設(shè)為: http://www.SampleStore.com/Account 。
名稱空間的名字語法容易讓人混淆,盡管以 http:// 開始,那個 URL 并不指向一個包含模式定義的文件。事實上,這個 URL http://www.SampleStore.com/Account 根本沒有指向任何文件,只是一個分配的名字。
模式中的定義和聲明可能引用屬于其他名稱空間的名字。在本文中,我們稱這些名稱空間為 源名稱空間。每個模式都有一個目標名稱空間,但可能有多個源名稱空間。名稱空間的名字可能相當長,但在 XML 文檔中通過 xmlns 聲明可使用簡寫形式。為了說明這些概念,我們可以向前述 清單 4中的示例模式中添加更多的內(nèi)容。
清單 4:目標名稱空間和源名稱空間
| 以下是引用片段: <!--XML?Schema?fragment?in?file?schema1.xsd--> <xsd:schema?targetNamespace='http://www.SampleStore.com/Account' xmlns:xsd='http://www.w3.org/1999/XMLSchema' xmlns:ACC=?'http://www.SampleStore.com/Account'> <xsd:element?name='InvoiceNo'?type='xsd:positive-integer'/> <xsd:element?name='ProductID'?type='ACC:ProductCode'/> <xsd:simpleType?name='ProductCode'?base='xsd:string'> <xsd:pattern?value='[A-Z]{1}d{6}'/> </xsd:simpleType> |
在 清單 4的 XML Schema 中, targetNamespace 的名字是 http://www.SampleStore.com/Account ,其中包含的名字有 InvoiceNo 、 ProductID 和 ProductCode 。 schema 、 element 、 simpleType 、 pattern 、 string 和 positive-integer 這些名字屬于源名稱空間 http://www.w3.org/1999/XMLSchema ,通過 xmlns 聲明縮寫為 xsd 。別名 xsd 沒有任何特殊的地方,我們可以選擇任何其他的名字。在本文后面的部分為了方便和簡化起見,我們使用 xsd 代表名稱空間 http://www.w3.org/1999/XMLSchema ,在一些代碼片段中省略了限定符 xsd 。在這個例子中, targetNamespace 偶爾也作為一個源名稱空間,因為要使用名字 ProductCode 定義其他的名字。
清單 4中的模式片段不需要指定源模式文件的位置。對于整個“模式的模式”, http://www.w3.org/1999/XMLSchema ,不需要指定位置,因為它的位置是人所共知的。對于源名稱空間 http://www.SampleStore.com/Account ,也不需要指定位置,因為它恰好是該文件中定義的目標名稱空間。為了更好地理解如何指定模式的位置和使用默認名稱空間,看一看 清單 5中擴展的例子。
?
清單 5:多個源名稱空間,導(dǎo)入一個名稱空間
| 以下是引用片段: <!--XML?Schema?fragment?in?file?schema1.xsd--> <schema?targetNamespace='http://www.SampleStore.com/Account' xmlns='http://www.w3.org/1999/XMLSchema' xmlns:ACC=?'http://www.SampleStore.com/Account' xmlns:PART=?'http://www.PartnerStore.com/PartsCatalog'> <import?namespace='http://www.PartnerStore.com/PartsCatalog' schemaLocation='http://www.ProductStandards.org/repository/alpha.xsd'/> <element?name='InvoiceNo'?type='positive-integer'/> <element?name='ProductID'?type='ACC:ProductCode'/> <simpleType?name='ProductCode'?base='string'> <pattern?value='[A-Z]{1}d{6}'/> </simpleType> <element?name='stickyGlue'?type='PART:SuperGlueType'/> |
?
清單 5中多了一個名稱空間引用: http://www.PartnerStore.com/PartsCatalog 。這個名稱空間不同于 targetNamespace 和標準名稱空間。因此必須使用 import 聲明元素引入,該元素的 schemaLocation 屬性指明包含模式的文件位置。默認的名稱空間是 http://www.w3.org/1999/XMLSchema ,它的 xmlns 聲明沒有名字。每個非限定的名字如 schema 和 element ,都屬于默認名稱空間 http://www.w3.org/1999/XMLSchema 。如果模式從一個名稱空間中引用了多個名字,將其指定為默認名字空間更方便。
?
一個 XML 實例文檔可能引用多個名稱空間的元素名,這些名稱空間定義在不同模式中。為了引用和簡化名稱空間的名字,同樣要使用 xmlns 聲明。我們使用 XML Schema 實例名稱空間的 schemaLocation 屬性指定文件的位置。要注意,該屬性不同于上一個例子中 xsd 名稱空間的同名屬性 schemaLocation 。
清單 6:使用來自多個模式的多個名稱空間的名字
| 以下是引用片段: <?xml?version="1.0"?> <ACC:rootElement?xmlns:ACC='http://www.SampleStore.com/Account' xmlns:PART='http://www.PartnerStore.com/PartsCatalog' xmlns:xsi='http://www.w3.org/1999/XMLSchema-instance' xsi:schemaLocation='http://www.PartnerStore.com/PartsCatalog http://www.ProductStandards.org/repository/alpha.xsd http://www.SampleStore.com/Account http://www.SampleStore.com/repository/schema1.xsd'> <ACC:InvoiceNo>123456789</ACC:InvoiceNo> |
定義元素就是定義元素的名字和內(nèi)容模型。在 XML Schema 中,元素的內(nèi)容模型由其類型定義,因此 XML 文檔中實例元素的值必須符合模式中定義的類型。
類型包括簡單類型和復(fù)雜類型。簡單類型的值不能包含元素或?qū)傩浴?fù)雜類型可以產(chǎn)生在其他元素中嵌套元素的效果,或者為元素增加屬性。(到目前為止本文中的例子都是用戶定義的簡單類型,比如 ProductCode )。XML Schema 規(guī)范也包括預(yù)定義的簡單類型(請參閱側(cè)欄 簡單類型)。 派生的簡單類型約束了基類型的值。比如,派生簡單類型 ProductCode 的值是基類型 string 值的子集。
簡單的、非嵌套的元素是簡單類型
不含屬性或其他元素的元素可以定義為簡單類型,無論是預(yù)定義的簡單類型還是用戶定義的簡單類型,如 string 、 integer 、 decimal 、 time 、 ProductCode 等等。
清單 7:一些元素的簡單類型
| 以下是引用片段: <element?name='age'?type='integer'/> <element?name='price'?type='decimal'/> |
帶有屬性的元素必須是復(fù)雜類型
現(xiàn)在,試著向 清單 7中的簡單元素 price 增加屬性 currency 。您不能這樣做,因為簡單類型的元素不能有屬性。如果希望增加屬性,您必須把 price 元素定義成復(fù)雜類型。在 清單 8的例子中,我們定義了一個 匿名類型,沒有明確地命名這個復(fù)雜類型。換句話說,沒有定義復(fù)雜類型 complexType 的 name 屬性。
清單 8:一個復(fù)雜元素類型
| 以下是引用片段: <element?name='price'> <complexType?base='decimal'?derivedBy='extension'> <attribute?name='currency'?type='string'/> </complexType> </element> <!--?In?XML?instance?document,?we?can?write:?<price?currency='US'>45.50</price>?--> |
嵌入其他元素的元素必須是復(fù)雜類型
在 XML 文檔中,一個元素可能嵌入其他的元素。這種要求可以在 DTD 中直接表示。但 XML Schema 定義一個元素,這個元素有一個類型,而這個類型可以包含其他元素和屬性的聲明。 表 1給出了一個簡單的例子。
表 1:DTD 和 XML Schema 中復(fù)雜數(shù)據(jù)類型的比較
XML 文檔
| 以下是引用片段: <Book> <Title>Cool?XML<Title> <Author>Cool?Guy</Author> </Book> |
DTD
| 以下是引用片段: <Book> <Title>Cool?XML<Title> <Author>Cool?Guy</Author> </Book> |
XML Schema
| 以下是引用片段: <Book> <Title>Cool?XML<Title> <Author>Cool?Guy</Author> </Book> <!ELEMENT?Book?(Title,?Author)> <!ELEMENT?Title?(#PCDATA)> <!ELEMENT?Author?(#PCDATA)> <element?name='Book'?type='BookType'/> <complexType?name='BookType'> <element?name='Title'?type='string'/> <element?name='Author'?type='string'/> </complexType> |
盡管 表 1中的 XML 代碼同時滿足 DTD 與 XML Schema 片段,但兩者之間有一個很大的區(qū)別。在 DTD 中所有的元素都是全局性的,而表中的 XML Schema 允許把 Title 和 Author 定義成局部的——只出現(xiàn)在元素 Book 中。為了在 XML Schema 中實現(xiàn)與 DTD 聲明完全相同的效果,元素 Title 和 Author 必須是全局范圍的,如 清單 9中所示。元素 element 的 ref 屬性使您能夠引用前面聲明的元素。
清單 9:用全局簡單類型定義的復(fù)雜類型
| 以下是引用片段: <element?name='Title'?type='string'/> <element?name='Author'?type='string'/> <element?name='Book'?type='BookType'/> <complexType?name='BookType'> <element?ref='Title'/> <element?ref='Author'/> </complexType> |
在 表 1和 清單 9所示的例子中, BookType 是全局性的,可用于聲明其他元素。相反, 清單 10將該類型局部地定義到元素 Book 中,而且定義成匿名元素。要注意, 表 1中的 XML 文檔片段與表 1、 清單 9和 清單 10中三個模式片段都匹配。
清單 10:隱藏 BookType 作為本地類型
| 以下是引用片段: <element?name='Title'?type='string'/> <element?name='Author'?type='string'/> <element?name='Book'> <complexType> <element?ref='Title'/> <element?ref='Author'/> </complexType> </element> |
表示元素的復(fù)雜約束
對于表示元素內(nèi)容模型的約束,XML Schema 比 DTD 提供了更大的靈活性。在最簡單的層次上,像在 DTD 中那樣,您可以把屬性和元素聲明關(guān)聯(lián)起來,指明能夠出現(xiàn)的給定元素集合序列:只能出現(xiàn) 1 次(1)、出現(xiàn) 0 次或多次(*)或者出現(xiàn) 1 次或多次(+)。您還可以表示 XML Schema 中的其他約束,比方說使用 element 元素的 minOccurs 和 maxOccurs 屬性,以及 choice 、 group 和 all 元素。
清單 11:表示元素類型的約束
| 以下是引用片段: <element?name='Title'?type='string'/> <element?name='Author'?type='string'/> <element?name='Book'> <complexType> <element?ref='Title'?minOccurs='0'/> <element?ref='Author'?maxOccurs='2'/> </complexType> </element> |
在 清單 11中, Book 中 Title 的出現(xiàn)是可選的(類似 DTD 的 '?')。但是, 清單 11也說明 Book 元素中至少要有一個但不能超過兩個作者。 element 的 minOccurs 和 maxOccurs 屬性的默認值是 1。元素 choice 只允許它的一個子女出現(xiàn)在實例中。另外一個元素 all ,表示這樣的約束:組中的所有子元素可以同時出現(xiàn)一次,或者都不出現(xiàn),它們可以按任意的順序出現(xiàn)。 清單 12表示 Title 和 Author 兩者必須同時出現(xiàn)(順序任意)在 Book 中,或者都不出現(xiàn)。這種約束很難在 DTD 中表示。
清單 12:指出必須為元素定義所有的類型
| 以下是引用片段: <xsd:element?name='Title'?type='string'/> <xsd:element?name='Author'?type='string'/> <xsd:element?name='Book'> <xsd:complexType> <xsd:all> <xsd:element?ref='Tile'/> <xsd:element?ref='Author'/> </xsd:all> </xsd:complexType> </xsd:element> |
更上層樓
已經(jīng)討論了在 XML Schema 中定義元素所需的最基本的概念,通過一些簡單的例子使您領(lǐng)略到它的強大功能。還有一些更強大的機制:
XML Schema 對類型繼承提供了廣泛的支持,允許重用以前定義的結(jié)構(gòu)。使用所謂的 facets,您可以派生新的類型,表示其他某個類型值的更小子集,比如通過枚舉、范圍或模式匹配來定義子集。在本文的例子中, ProductCode 類型就是使用模式面( pattern facet)定義的。子類型也可以向基類型增加更多的元素和屬性聲明。
有幾種機制控制能否定義子類型,或者能否在具體的文檔中替換為子類型。比如,有可能表示 InvoiceType ( Invoice 編號的類型)不允許子類型化,任何人都不能定義新版本的 InvoiceType 。通過規(guī)定在特定的上下文中不能用 ProductCode 類型的子類型替換,也能表達這種約束。
除了子類型外,還可以定義等價的類型,這樣,一個類型的值可以用另一個類型代替。
通過聲明抽象的元素或者類型,XML Schema 提供了一種強制替換機制。
為了方便起見,可以定義并命名屬性組和元素組,從而能夠在后面引用這些組達到重用的目的。
XML Schema 提供了三個元素—— appInfo 、 documentation 和 annotation ——為模式作注解,以方便讀者( documentation )和應(yīng)用程序( appInfo )。
基于子元素的某些屬性可以表示惟一性約束。
可以通過 W3C 站點(請參閱 參考資料)的文檔進一步研究 XML Schema,或者訪問 dW XML 專區(qū)了解更多的內(nèi)容。目前,XML Schema 規(guī)范已經(jīng)被批準,并成為候選推薦標準(Candidate Recommendation),毫無疑問您將越來越多地用到它。
?
轉(zhuǎn)載于:https://www.cnblogs.com/binterminator/articles/1705972.html
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的使用 XML Schema 定义元素的基本知识的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: typescirpt 知识点
- 下一篇: asp.net ajax控件工具集 Au