首頁 >後端開發 >XML/RSS教程 >詳解使用XML Schema定義元素的基本知識(圖文)

詳解使用XML Schema定義元素的基本知識(圖文)

黄舟
黄舟原創
2017-03-28 16:36:402399瀏覽

新的 XML Schema 系統即將成為 W3C 推薦標準,目的是為了克服 DTD 的限制(請參閱側邊欄, DTD 的限制 ),為 XML 文件提供豐富的語法結構。本文展示了模式的彈性,說明如何使用 XML Schema 系統來定義最基本的 XML 文檔建構區塊-元素。

XML Schema 比 DTD 更強大。為了說明 XML Schema 機制的強大功能,以下三個程式清單簡要地比較了表示元素的不同方式。 清單 1給出了一個 XML 文檔段, 清單 2用 DTD 語法聲明了這兩個元素, 清單 3則是對應的 XML Schema 語法形式。要注意, 清單 3中所用的是相同的 XML 語法。透過模式,驗證解析器可以檢查元素 InvoiceNo 是否為正整數,元素 ProductID 的首字是否為 A 到 Z 之間的字母,後面為六個阿拉伯數字。相反,引用 DTD 的驗證解析器只能檢查這些元素是否以字串表示。

清單1:XML 文件段

<InvoiceNo>123456789</InvoiceNo>
<ProductID>J123456</ProductID>

清單2:描述清單1 中元素的DTD 段

<!ELEMENT InvoiceNo (#PCDATA)>
<!ELEMENT ProductID (#PCDATA)>

清單3:描述清單1 中元素的XML Schema

<element name=&#39;InvoiceNo&#39; type=&#39;positive-integer&#39;/>
<element name=&#39;ProductID&#39; type=&#39;ProductCode&#39;/>
<simpleType name=&#39;ProductCode&#39; base=&#39;string&#39;>
<pattern value=&#39;[A-Z]{1}d{6}&#39;/>
</simpleType>

在XML Schema 中使用名稱空間

在這個協作的世界中,一個人可能處理來自多個其他團體的文檔,而不同的團體可能希望以不同的方式表示他們的數據元素。此外,他們也可能在一個文件中引用不同團體所創建的同名元素。如何區分相同名字的不同定義呢? XML Schema 使用名稱空間來區分這些定義。

附:

DTD 的限制

(儘管作為描述結構化資訊的機制,DTD 成功地為SGML 和HTML 開發人員服務了20 年,但與XML Schema 相比,它存在著嚴重的限制。其他子元素的混合

一組子元素

DTD 不使用XML 語法,對類型和名稱空間僅提供有限的支援。 Schema 定義了一組新名字,如元素名、型別名、屬性名、屬性組名,這些名字的定義和宣告都寫在模式中。 清單 3定義的名字包括 InvoiceNo 、 ProductID 和 ProductCode 。

我們說模式中定義的名字屬於它的 目標名稱空間。名稱空間本身有一個固定但沒有限制的名字,必須符合 URL 語法。例如,對於 清單 3中模式段,您可以將名稱空間的名字設為: http://www.SampleStore.com/Account 。

名稱空間的名字語法容易讓人混淆,儘管以 http:// 開始,那個 URL 並不指向一個包含模式定義的檔案。事實上,這個 URL http://www.SampleStore.com/Account 根本沒有指向任何文件,只是一個被指派的名字。

模式中的定義和宣告可能會引用屬於其他名稱空間的名字。在本文中,我們稱這些名稱空間為 來源名稱空間。每個模式都有一個目標名稱空間,但可能有多個來源名稱空間。名稱空間的名字可能相當長,但在 XML 文件中透過 xmlns 宣告可使用簡寫形式。為了說明這些概念,我們可以向前述 清單 4中的範例模式中加入更多的內容。

清單4:目標名稱空間與來源名稱空間

<!--XML Schema fragment in file schema1.xsd-->

<xsd:schema targetNamespace=&#39;http://www.SampleStore.com/Account&#39;
xmlns:xsd=&#39;http://www.w3.org/1999/XMLSchema&#39;
xmlns:ACC= &#39;http://www.SampleStore.com/Account&#39;>
<xsd:element name=&#39;InvoiceNo&#39; type=&#39;xsd:positive-integer&#39;/>
<xsd:element name=&#39;ProductID&#39; type=&#39;ACC:ProductCode&#39;/>
<xsd:simpleType name=&#39;ProductCode&#39; base=&#39;xsd:string&#39;>
<xsd:pattern value=&#39;[A-Z]{1}d{6}&#39;/>
</xsd:simpleType>

在清單4的XML Schema 中, targetNamespace 的名字是www.SampleStore.com/Account ,其中包含的名字有InvoiceNo 、 ProductID 和ProductCode 。 schema 、 element 、 simpleType 、 pattern 、 string 和 positive-integer 這些名字屬於來源名稱空間 www.w3.org/1999/XMLSchema ,透過 xmlns 宣告縮寫為 xsd 。別名 xsd 沒有任何特殊的地方,我們可以選擇任何其他的名字。在本文後面的部分為了方便和簡化起見,我們使用 xsd 代表名稱空間 www.w3.org/1999/XMLSchema ,在一些程式碼片段中省略了限定符 xsd 。在這個例子中, targetNamespace 偶爾也會作為一個來源名稱空間,因為要使用名字 ProductCode 定義其他的名字。

#清單 4中的模式段不需要指定來源模式檔案的位置。對於整個“模式的模式”, http://www.w3.org/1999/XMLSchema ,不需要指定位置,因為它的位置是人所共知的。對於來源名稱空間 www.SampleStore.com/Account ,也不需要指定位置,因為它恰好是該檔案中定義的目標名稱空間。為了更好地理解如何指定模式的位置和使用預設名稱空間,請看一看 清單 5中擴充的範例。

清單 5:多個來源名稱空間,匯入一個名稱空間

<!--XML Schema fragment in file schema1.xsd-->
<schema targetNamespace=&#39;http://www.SampleStore.com/Account&#39;
xmlns=&#39;http://www.w3.org/1999/XMLSchema&#39;
xmlns:ACC= &#39;http://www.SampleStore.com/Account&#39;
xmlns:PART= &#39;http://www.PartnerStore.com/PartsCatalog&#39;>
<import namespace=&#39;http://www.PartnerStore.com/PartsCatalog&#39;
schemaLocation=&#39;http://www.ProductStandards.org/repository/alpha.xsd&#39;/>
<element name=&#39;InvoiceNo&#39; type=&#39;positive-integer&#39;/>
<element name=&#39;ProductID&#39; type=&#39;ACC:ProductCode&#39;/>
<simpleType name=&#39;ProductCode&#39; base=&#39;string&#39;>
<pattern value=&#39;[A-Z]{1}d{6}&#39;/>
</simpleType>
<element name=&#39;stickyGlue&#39; type=&#39;PART:SuperGlueType&#39;/>

清单 5中多了一个名称空间引用: www.PartnerStore.com/PartsCatalog 。这个名称空间不同于 targetNamespace 和标准名称空间。因此必须使用 import 声明元素引入,该元素的 schemaLocation 属性指明包含模式的文件位置。默认的名称空间是www.w3.org/1999/XMLSchema ,它的 xmlns 声明没有名字。每个非限定的名字如 schema 和 element ,都属于默认名称空间www.w3.org/1999/XMLSchema 。如果模式从一个名称空间中引用了多个名字,将其指定为默认名字空间更方便。

一个 XML 实例文档可能引用多个名称空间的元素名,这些名称空间定义在不同模式中。为了引用和简化名称空间的名字,同样要使用 xmlns 声明。我们使用 XML Schema 实例名称空间的 schemaLocation 属性指定文件的位置。要注意,该属性不同于上一个例子中 xsd 名称空间的同名属性 schemaLocation 。

清单 6:使用来自多个模式的多个名称空间的名字

<?xml version="1.0"?>
<ACC:rootElement xmlns:ACC=&#39;http://www.SampleStore.com/Account&#39;
xmlns:PART=&#39;http://www.PartnerStore.com/PartsCatalog&#39;
xmlns:xsi=&#39;http://www.w3.org/1999/XMLSchema-instance&#39;
xsi:schemaLocation=&#39;http://www.PartnerStore.com/PartsCatalog
http://www.ProductStandards.org/repository/alpha.xsd
http://www.SampleStore.com/Account
http://www.SampleStore.com/repository/schema1.xsd&#39;>
<ACC:InvoiceNo>123456789</ACC:InvoiceNo>

图 2:清单 5 和清单 6 的名称空间

詳解使用XML Schema定義元素的基本知識(圖文)

定义元素

定义元素就是定义元素的名字和内容模型。在 XML Schema 中,元素的内容模型由其类型定义,因此 XML 文档中实例元素的值必须符合模式中定义的类型。

类型包括简单类型和复杂类型。简单类型的值不能包含元素或属性。复杂类型可以产生在其他元素中嵌套元素的效果,或者为元素增加属性。(到目前为止本文中的例子都是用户定义的简单类型,比如 ProductCode )。XML Schema 规范也包括预定义的简单类型(请参阅侧栏 简单类型)。 派生的简单类型约束了基类型的值。比如,派生简单类型 ProductCode 的值是基类型 string 值的子集。

简单的、非嵌套的元素是简单类型

不含属性或其他元素的元素可以定义为简单类型,无论是预定义的简单类型还是用户定义的简单类型,如 string 、 integer 、 decimal 、 time 、 ProductCode 等等。

清单 7:一些元素的简单类型

<element name=&#39;age&#39; type=&#39;integer&#39;/>
<element name=&#39;price&#39; type=&#39;decimal&#39;/>

带有属性的元素必须是复杂类型

现在,试着向 清单 7中的简单元素 price 增加属性 currency 。您不能这样做,因为简单类型的元素不能有属性。如果希望增加属性,您必须把 price 元素定义成复杂类型。在 清单 8的例子中,我们定义了一个 匿名类型,没有明确地命名这个复杂类型。换句话说,没有定义复杂类型 complexType 的 name 属性。

清单 8:一个复杂元素类型

<element name=&#39;price&#39;>
<complexType base=&#39;decimal&#39; derivedBy=&#39;extension&#39;>
<attribute name=&#39;currency&#39; type=&#39;string&#39;/>
</complexType>
</element>
<!-- In XML instance document, we can write: <price currency=&#39;US&#39;>45.50</price> -->

嵌入其他元素的元素必须是复杂类型

在 XML 文档中,一个元素可能嵌入其他的元素。这种要求可以在 DTD 中直接表示。但 XML Schema 定义一个元素,这个元素有一个类型,而这个类型可以包含其他元素和属性的声明。 表 1给出了一个简单的例子。

表 1:DTD 和 XML Schema 中复杂数据类型的比较

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>










尽管 表 1中的 XML 代码同时满足 DTD 与 XML Schema 段,但两者之间有一个很大的区别。在 DTD 中所有的元素都是全局性的,而表中的 XML Schema 允许把 Title 和 Author 定义成局部的——只出现在元素 Book 中。为了在 XML Schema 中实现与 DTD 声明完全相同的效果,元素 Title 和 Author 必须是全局范围的,如 清单 9中所示。元素 element 的 ref 属性使您能够引用前面声明的元素。

清单 9:用全局简单类型定义的复杂类型

<element name=&#39;Title&#39; type=&#39;string&#39;/>
<element name=&#39;Author&#39; type=&#39;string&#39;/>
<element name=&#39;Book&#39; type=&#39;BookType&#39;/>
<complexType name=&#39;BookType&#39;>
<element ref=&#39;Title&#39;/>
<element ref=&#39;Author&#39;/>
</complexType>

在 表 1和 清单 9所示的例子中, BookType 是全局性的,可用于声明其他元素。相反, 清单 10将该类型局部地定义到元素 Book 中,而且定义成匿名元素。要注意, 表 1中的 XML 文档段与表 1、 清单 9和 清单 10中三个模式段都匹配。

清单 10:隐藏 BookType 作为本地类型

<element name=&#39;Title&#39; type=&#39;string&#39;/>
<element name=&#39;Author&#39; type=&#39;string&#39;/>
<element name=&#39;Book&#39;>
<complexType>
<element ref=&#39;Title&#39;/>
<element ref=&#39;Author&#39;/>
</complexType>
</element>

表示元素的复杂约束

对于表示元素内容模型的约束,XML Schema 比 DTD 提供了更大的灵活性。在最简单的层次上,像在 DTD 中那样,您可以把属性和元素声明关联起来,指明能够出现的给定元素集合序列:只能出现 1 次(1)、出现 0 次或多次(*)或者出现 1 次或多次(+)。您还可以表示 XML Schema 中的其他约束,比方说使用 element 元素的 minOccurs 和 maxOccurs 属性,以及 choice 、 group 和 all 元素。

清单 11:表示元素类型的约束

<element name=&#39;Title&#39; type=&#39;string&#39;/>
<element name=&#39;Author&#39; type=&#39;string&#39;/>
<element name=&#39;Book&#39;>
<complexType>
<element ref=&#39;Title&#39; minOccurs=&#39;0&#39;/>
<element ref=&#39;Author&#39; maxOccurs=&#39;2&#39;/>
</complexType>
</element>

在 清单 11中, Book 中 Title 的出现是可选的(类似 DTD 的 '?')。但是, 清单 11也说明 Book 元素中至少要有一个但不能超过两个作者。 element 的 minOccurs 和 maxOccurs 属性的默认值是 1。元素 choice 只允许它的一个子女出现在实例中。另外一个元素 all ,表示这样的约束:组中的所有子元素可以同时出现一次,或者都不出现,它们可以按任意的顺序出现。 清单 12表示 Title 和 Author 两者必须同时出现(顺序任意)在 Book 中,或者都不出现。这种约束很难在 DTD 中表示。

清单 12:指出必须为元素定义所有的类型

<xsd:element name=&#39;Title&#39; type=&#39;string&#39;/>
<xsd:element name=&#39;Author&#39; type=&#39;string&#39;/>
<xsd:element name=&#39;Book&#39;>
<xsd:complexType>
<xsd:all>
<xsd:element ref=&#39;Tile&#39;/>
<xsd:element ref=&#39;Author&#39;/>
</xsd:all>
</xsd:complexType>
</xsd:element>

更上层楼

我们已经讨论了在 XML Schema 中定义元素所需的最基本的概念,通过一些简单的例子使您领略到它的强大功能。还有一些更强大的机制:

XML Schema 对类型继承提供了广泛的支持,允许重用以前定义的结构。使用所谓的 facets,您可以派生新的类型,表示其他某个类型值的更小子集,比如通过枚举、范围或模式匹配来定义子集。在本文的例子中, ProductCode 类型就是使用模式面( pattern facet)定义的。子类型也可以向基类型增加更多的元素和属性声明。

有几种机制控制能否定义子类型,或者能否在具体的文档中替换为子类型。比如,有可能表示 InvoiceType ( Invoice 编号的类型)不允许子类型化,任何人都不能定义新版本的 InvoiceType 。通过规定在特定的上下文中不能用 ProductCode 类型的子类型替换,也能表达这种约束。

除了子类型外,还可以定义等价的类型,这样,一个类型的值可以用另一个类型代替。

通过声明抽象的元素或者类型,XML Schema 提供了一种强制替换机制。

为了方便起见,可以定义并命名属性组和元素组,从而能够在后面引用这些组达到重用的目的。

XML Schema 提供了三个元素—— appInfo 、 documentation 和 annotation ——为模式作注解,以方便读者( documentation )和应用程序( appInfo )。

基于子元素的某些属性可以表示惟一性约束。

可以通过 W3C 站点(请参阅 参考资料)的文档进一步研究 XML Schema,或者访问 dW XML 专区了解更多的内容。目前,XML Schema 规范已经被批准,并成为候选推荐标准(Candidate Recommendation),毫无疑问您将越来越多地用到它。

以上是詳解使用XML Schema定義元素的基本知識(圖文)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn