XML 模式:瞭解結構

XML 模式:瞭解結構

瞭解如何使用 XML 模式結構聲明、擴展和限制 XML 的結構。

本系列中的其他文章:
XML 模式:瞭解命名空間
XML 模式:瞭解數據類型

 

語法定義語言的結構和語義、實施約束以及確保實例(實際數據)的有效性。正如英語(或任何其他語言)具有關聯的語法來定義有關特殊句子的撰寫規則,或者在給定英語句子的情況下,利用語法來檢查該句的有效性一樣,XML 實例文檔的語法也定義相應的規則以確保該文檔的結構和內容的有效性。

W3C XML 模式定義 (WXS) 採用 XML 語言表示 W3C XML 模式 (WXS) 的抽象數據模型。通過定義模式的抽象數據模型,W3C 模式並不知道用於表示該模型的語言。XML 表示形式是 WXS 指定的正式表示形式,但您可以根據所需的任何方式表示抽象數據模型並將它用於驗證。例如,您可以使用任何符合抽象數據模型的數據結構直接創建內存中的模式。這將促使開發 W3C 模式驗證程序的供應商提供一個可用於直接創建內存中模式的 API。

驗證 XML 實例文檔的語法有多種。某些語法很快便過時,而其他語法(如 DTD,它是 W3C XML 1.0 REC 的一部分)則已經通過了時間的考驗。在現有語法中,XML 模式在 XML 開發人員中應用最廣,這是因爲:

  1. 它使用 XML 語言來定義模式。
  2. 它具有 44 個以上的內置數據類型,可以對其中的每一個數據類型進行進一步地優化,以對 XML 中的字符數據進行細粒度驗證。
  3. 可以使用 minOccurs 和 maxOccurs 屬性以細粒度方式定義元素的基數。
  4. 它通過 extension、restriction、import、include 和 redefine 結構支持模塊化和可重用性。
  5. 它支持標識約束,以確保 XML 文檔中的值在指定集中的唯一性。
  6. 它具有抽象數據模型,因此它的表示形式並不限於 XML。

以下是一個有關如何根據外部指定的模式來驗證 XML 實例的示例:

import java.io.FileInputStream;
import oracle.xml.parser.v2.XMLError;
import oracle.xml.parser.schema.XML Schema;
import oracle.xml.parser.schema.XSDBuilder;
import oracle.xml.schemavalidator.XSDValidator;
...
//加載 XML 模式
XSDBuilder schemaBuilder = new XSDBuilder();
XML Schema schema = schemaBuilder.build(new FileInputStream("myschema.xsd"), null);

//將加載的 XML 模式設置爲 XSDValidator
XSDValidator validator = new XSDValidator();
validator.setSchema(schema);

//針對提供的 XML 模式驗證 XML 實例。
validator.validate(new FileInputStream("data.xml"));

//檢查錯誤
XMLError error = validator.getError();
if (error.getNumMessages() > 0) {
System.out.println("XML-instance is invalid.");
error.flushErrors();
}
else {
System.out.println("XML-instance is valid.");
}
當然,XML 模式也有限制:
  1. 它不支持基於規則的驗證。一個基於規則的驗證示例爲:如果屬性“score”的值大於 80,則 XML 實例中必須存在元素“distinction”,否則元素不存在。
  2. 唯一粒子屬性 (UPA) 約束過分嚴格地定義了用於所有類型的 XML 文檔的語法。(有關更多信息,請參閱“UPA 約束”。)

在我的前幾篇文章中,我介紹了命名空間的概念(在您深入研究 XML 模式之前必須瞭解它)、XML 模式中支持的數據類型以及用於進一步限制和使用這些數據類型的 simpleType 結構。

在本文中,我將介紹用於聲明、擴展和限制 XML 結構的模式。您還將學習由 XML 模式提供的模型組、粒子以及其他約束。

Oracle XML 開發人員工具包 (XDK) 包含一個符合 W3C 標準的 XML 模式處理器以及多個實用工具,如利用 API 通過編程來創建並限制模式數據類型、分析和驗證 XML 模式結構本身以及遍歷 XML 模式的抽象數據模型的實用工具。請檢查 oracle.xml.parser.schema 和 oracle.xml.schemavalidator 程序包。

內容和模型

元素內容

在 XML 文檔中,元素內容是指包含在它的 <頭> 和 </尾> 標記之間的內容。元素只能有四種類型的內容:TextOnly(純文本)、ElementOnly(純元素)、Mixed(混合)和 Empty(空)。在元素上聲明的屬性並視爲是元素內容的一部分。它們只是其聲明所在的元素的一部分,他們組成了 XML 的結構。

TextOnly

如果元素在其 <頭> 和 </尾> 標記之間只有字符數據(或簡單稱爲文本數據),即如果元素沒有子元素,則該元素的內容被視爲是 TextOnly(純文本)。例如:

<TextOnly>some character data</TextOnly>
ElementOnly

 

如果元素在其 <opening> 和 </closing> 標記之間只有子元素(可以選擇性地由空格、製表符、換行符、回車符分隔),則該元素的內容被視爲是 TextOnly(純元素)。這些空格被稱作是可忽略的空格,並通常用於對 XML 進行縮進。因此,以下內容:

沒有空格的 ElementOnly 內容

<ElementOnly><child1 .../><child2 .../></ElementOnly>
等價於:

 

空格的 ElementOnly 內容

<ElementOnly>
<child1 .../>
<child2 .../>
</ElementOnly>
混合

 

如果元素的字符數據與子元素分散在 <頭> 和 </尾巴> 標記之間,則該元素的內容被視爲是 Mixed(混合)。(換言之,它的內容同時包含字符數據和子元素。)混合內容後,前面所說的可忽略空格將不再是可忽略的。因此,以下內容:

<Mixed><child1.../>some character data<child1.../></Mixed>
不同於:
<Mixed>
<child1 .../>
some character data
<child1 .../>
</Mixed>

 

如果元素在 <頭> 和 </尾> 標記之間絕對沒有任何內容(甚至是空格),則該元素的內容被視爲是 Empty(空)。例如:

<Empty></Empty>
另一種便於使用,並且格式清晰的元素(具有空內容)表示方法是使用單個 Empty 標記,如下所示:
<Empty />
內容模型

 

在 XML 語法中,您可以聲明元素的內容模型,以指定相應 XML 實例文檔中的元素內容類型。因此,內容模型是元素內容的定義。

下圖演示瞭如何在 XML 模式中聲明內容模型。沿着圖中從 <schema> 開始的路徑深入探討,以瞭解如何聲明四種元素內容(包含和不包含屬性聲明)的內容模型。讓我們簡單介紹一下每個元素內容。

圖 1
圖 1:在 XML 模式中聲明內容模型

 

TextOnly

在以上圖示中,沿路徑找到 simpleType-1 以使用 TextOnly 內容模型聲明元素:

<xsd:element name="TextOnly">
<xsd:simpleType>
<xsd:restriction base="xsd:string" />
</xsd:simpleType>  
</xsd:element>

或等價於

<xsd:element name="TextOnly" type="xsd:string" />
以上模式使用 TextOnly 內容模型聲明瞭一個名爲“TextOnly”(可以爲任何名稱)的元素,其內容必須是相應 XML 實例中的整數。如果元素的內容模型爲 TextOnly,則它始終有一個關聯的 simpleType,用於指示該元素的數據類型。例如,在本示例中,元素 TextOnly 的數據類型爲 string請參閱上一部分中此模式的相應 XML 實例。

 

正如前面指出的,屬性並不是元素內容;因此,另一個具有 TextOnly 內容並具有屬性的 XML 實例的示例爲:

<TextOnly att="val">some character data</TextOnly>
現在,沿着圖 1 中的路徑找到 simpleContent-3,以使用 TextOnly 內容模型和屬性聲明一個元素:
<xsd:element name="TextOnly">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="att" type="xsd:string" use="required" />
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
以上模式使用 TextOnly 內容模型聲明一個名爲“TextOnly”的元素,其內容必須爲字符串並且在相應的 XML 實例中必須有一個名爲“attr”的屬性。

 

ElementOnly

沿着圖 1 中的路徑直到找到 sequence-5、choice-6 之一或 all-7,以使用 ElementOnly 內容模型聲明一個元素:

<xsd:element name="ElementOnly">
<xsd:complexType>
<xsd:sequence> <!-- could have used choice or all instead —>
<xsd:element name="child1" type="xsd:string" />
<xsd:element name="child2" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
以上模式使用 ElementOnly 內容模型聲明一個名爲“ElementOnly”的元素。元素“ElementOnly”在相應的 XML 實例文檔中必須具有子元素“child1”和“child2”。請參閱上一部分中此模式的相應 XML 實例。

 

另一個包含 ElementOnly 元素內容和屬性的 XML 實例如下所示:

<ElementOnly att="val">
<child1 .../>
<child2 .../>
</ElementOnly>
要使用 ElementOnly 內容模型和屬性聲明一個元素,圖 1 中的路徑與聲明 ElementOnly 內容模型的路徑相同。然後,按如下所示在 complexType 中聲明屬性:
<xsd:element name="ElementOnly">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="child1" type="xsd:string" />
<xsd:element name="child2" type="xsd:string" />
</xsd:sequence>
<xsd:attribute name="att" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
以上模式的相應 XML 實例如下
<Mixed att="val">
<child1 .../>
some character data
<child1 .../>
</Mixed>
混合型

 

沒着圖 1 中的路徑找到 sequence-5、choice-6 之一或 all-7,以使用 Mixed 內容模型(它與聲明 ElementOnly 內容模型相同)聲明元素,但這次將 complexType 的 mixed 屬性設置爲 true,如下所示:

<xsd:element name="Mixed">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element name="child1" type="xsd:string" />
<xsd:element name="child2" type="xsd:string" />
</xsd:sequence>
<xsd:attribute name="att" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
Empty

 

沿着此路徑直到找到 complexType-2 以使用 Empty 聲明一個具有或沒有屬性的元素:

<xsd:element name="EmptyContentModels">
<xsd:complexType>
<xsd:sequence>

<xsd:element name="Empty1">
<xsd:complexType />
</xsd:element>

<xsd:element name="Empty2">
<xsd:complexType>
<xsd:attribute name="att" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>

</xsd:sequence>
</xsd:complexType>
</xsd:element>
以上模式的相應 XML 實例如下
<EmptyContentModels>
<Empty1 />
<Empty2 att="val" />
</EmptyContentModels>
模型組

 

如果將元素的內容模型聲明爲 ElementOnly或混合型(意味着該元素具有子元素),則可以使用模型組更詳細地指定子元素的順序出現位置。模型組由粒子組成;粒子可以是元素聲明或其他模型組。模型組本身有一個基數,可以使用 minOccurs 和 maxOccurs 屬性對其進行優化。這些特徵使模型組非常強大。

XML 模式支持的三個模型組分別爲:

  • Sequence - (a , b)* - 在 sequence 模型組中聲明的子元素必須以模式中定義的同樣順序出現在相應的 XML 實例中。Sequence 模型組的基數範圍從 0 到無限大。通過遞歸方式,sequence 模型組還可以進一步包含 Sequencechoice 模型組。
  • Choice - (a | b)* - 表示在 choice 模型組中聲明的子元素集中,必須有一個元素出現在相應的 XML 實例中。Choice 模型組的基數範圍從 0 到無限大。通過遞歸方式, choice 模型組可以進一步包含 SequenceChoice 模型組。
  • all - {a , b}?- 表示在 all 模型組中聲明的整個子元素集必須出現在相應的 XML 實例中,但與 sequence 模型組不同的是,順序並不重要。因此,子元素可以任何順序出現。all 模型組的基數只能爲 0 或 1。all 模型組只能包含元素聲明而不能包含任何其他模型組。

這些模型組既可以內聯方式聲明,也可以全局聲明(一個包含名稱並可重用的 <schema> 結構的直接子項)方式聲明。必須在 <group> 結構中聲明全局模型組,您可以以後按其名稱引用它。但與內聯模型組不同的是,不能在全局聲明的模型組上聲明 minOccurs/maxOccurs 屬性。如果需要,可以在引用全局聲明的模型組時使用 minOccurs/maxOccurs 屬性。例如:

<xsd:group name="globalDecl">
<xsd:sequence>
<xsd:element name="child1" type="xsd:string" />
<xsd:element name="child2" type="xsd:string" />
</xsd:sequence>
</xsd:group>
隨後,可以在需要時使用 group 結構以及 minOccurs/maxOccurs 屬性引用全局聲明的模型組:
<xsd:group ref="globalDecl" maxOccurs="unbounded">
爲更好地瞭解模型組,以下提供了一個複雜示例:
((a | b)* , c+)?

<xsd:element name="complexModelGroup">
<xsd:complexType>

<xsd:sequence minOccurs="0" maxOccurs="1">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="a" type="xsd:string" />
<xsd:element name="b" type="xsd:string" />
</xsd:choice>
<xsd:element name="c" type="xsd:string" minOccurs="1" maxOccurs="unbounded">
</xsd:sequence>

</xsd:complexType>
</xsd:element>
complexType 敘述

 

您現在擁有足夠的信息來編寫一個簡單的 XML 文檔模式。但 XML 模式中的許多高級概念仍有待介紹。

complexType 是 XML 模式中其他強大的結構之一。您除了可以聲明所有四個包含或不包含屬性的內容模型以外,還可以通過繼承已經聲明的 complexType 以派生出新的 complexType。因此,派生的 complexType 既可以將更多聲明添加到由基礎 complexType 繼承而來的聲明(使用 extension),也可以限制基礎 complexType 中的聲明(使用 restriction

可以使用 simpleContentcomplexContent 擴展或限制 complexType。具有 simpleContent 的 complexType 聲明一個包含或不包含屬性的 TextOnly 內容模型。具有 complexContent 的 complexType 可用於聲明其它三個包含或不包含屬性的內容模型(ElementOnly、Mixed 或 Empty)。

擴展 complexType

simpleContent

圖 2
圖 2:只能通過擴展具有 simpleContent 的 complexType 才能添加屬性。

 

具有 simpleContent 的 complexType 可以擴展 simpleType 具有 simpleContent 的 complexType。如圖 2 中所示,在派生的 complexType 中,允許您執行的唯一操作是添加屬性。例如:

<?xml version="1.0"?>
<xsd:schema targetNamespace="http://inheritance-ext-res"
xmlns:tns="http://inheritance-ext-res"
xmlns:xsd="http://www.w3.org/2001/XML Schema"
elementFormDefault="qualified">
attributeFormDefault="unqualified">
    
<xsd:complexType name="DerivedType1">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="att1" type="xsd:string" use="required" />
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>

<xsd:complexType name="DerivedType2">
<xsd:simpleContent>
<xsd:extension base="tns:DerivedType1">
<xsd:attribute name="att2" type="xsd:string" use="required" />
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>

<xsd:element name="SCExtension">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Derived1" type="tns:DerivedType1" />
<xsd:element name="Derived2" type="tns:DerivedType2" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>

</xsd:schema>
在以上模式中:

 

 

  1. DerivedType1 基於內置的 simpleType string 擴展,並添加了一個屬性 attr1
  2. DerivedType2 繼承基礎 DerivedType1(它是一個具有 simpleContent 的 complexType)中的屬性 attr1,並添加一個屬性 attr2

 

對應於以上模式的 XML 實例如下:

<SCExtension xmlns="http://inheritance-ext-res"
xmlns:xsi="http://www.w3.org/2001/XML Schema-instance"
xsi:schemaLocation="http://inheritance-ext-res CTSCExt.xsd">

<Derived1 att1="val">abc</Derived1>
<Derived2 att1="val" att2="val">def</Derived2>
  
</SCExtension>
complexContent

 

圖 3
圖 3:具有 complexContent 的 complexType 可用於擴展模型組以及添加屬性。

 

具有 complexContent 的 complexType 可以擴展 complexType 具有 complexContent 的 complexType。如圖 3 所示,在派生的 complexType 中,允許您添加屬性以及擴展模型組。例如:

<?xml version="1.0"?>
<xsd:schema targetNamespace="http://inheritance-ext-res"
xmlns:tns="http://inheritance-ext-res"
xmlns:xsd="http://www.w3.org/2001/XML Schema"
elementFormDefault="qualified">
attributeFormDefault="unqualified">

<!— (child1)+ —>
<xsd:complexType name="BaseType">
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="child1" type="xsd:string" />
</xsd:sequence>
<xsd:attribute name="att1" type="xsd:string" use="required" />
</xsd:complexType>

<!— ((child1)+ , (child2 | child3)) —>
<xsd:complexType name="DerivedType">
<xsd:complexContent>
<xsd:extension base="tns:BaseType">
<xsd:choice>
<xsd:element name="child2" type="xsd:string" />
<xsd:element name="child3" type="xsd:string" />
</xsd:choice>
<xsd:attribute name="att2" type="xsd:string" use="required" />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>

<xsd:element name="CCExtension">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Base" type="tns:BaseType" />
<xsd:element name="Derived" type="tns:DerivedType" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>

</xsd:schema>
在以上模式中:

 

 

  1. DerivedType 繼承基礎 complexType 中的 sequence 模型組,並添加一個 choice 模型組,從而生成派生的 complexType 的最終內容模型- ((child1)+ , (child2 | child3))。
  2. DerivedType 繼承 BaseType 中的屬性 attr1,並添加屬性 attr2

對應於以上模式的 XML 實例如下:

<CCExtension xmlns="http://inheritance-ext-res"
xmlns:xsi="http://www.w3.org/2001/XML Schema-instance"
xsi:schemaLocation="http://inheritance-ext-res CTCCExt.xsd">

<Base att1="val">
<child1>This is base</child1>
<child1>This is base</child1>
</Base>
  
<Derived att1="val" att2="val">
<child1>This is inherited from base</child1>
<child1>This is inherited from base</child1>
<child1>This is inherited from base</child1>
<child3>This is added in the derived</child3>
</Derived>

</CCExtension>
限制 complexType

 

simpleContent

圖 4
圖 4:具有 simpleContent 的 complexType 可用於限制數據類型和屬性。

 

具有 simpleContent 的 complexType 只能限制具有 simpleContent 的 complexType。如圖 4 中所示,在派生的 complexType 中,可以限制基類的 simpleType,以及限制基類中的屬性的類型和使用(可選、強制等)。例如:

<?xml version="1.0"?>
<xsd:schema targetNamespace="http://inheritance-ext-res"
xmlns:tns="http://inheritance-ext-res"
xmlns:xsd="http://www.w3.org/2001/XML Schema"
elementFormDefault="qualified">
attributeFormDefault="unqualified">
    
<xsd:complexType name="BaseType">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="att1" type="xsd:string" use="optional" />
<xsd:attribute name="att2" type="xsd:integer" use="optional" />
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>

<xsd:complexType name="DerivedType">
<xsd:simpleContent>
<xsd:restriction base="tns:BaseType">
<xsd:maxLength value="35" />
<xsd:attribute name="att1" use="prohibited" />

<xsd:attribute name="att2" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:integer">
<xsd:totalDigits value="2" />
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>

</xsd:restriction>
</xsd:simpleContent>
</xsd:complexType>

<xsd:element name="SCRestriction">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Base" type="tns:BaseType" />
<xsd:element name="Derived" type="tns:DerivedType" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>

</xsd:schema>
在以上模式中:

 

 

  1. 您將基類的 simpleType 內容(字符串類型)限制爲派生的 simpleType 中一個長度爲 35 的字符串。
  2. 您禁止從基類中繼承屬性 att1。
  3. 您將屬性 att2 的類型限制爲一個 2 位整數,並使其從可選變爲強制。

 

對應於以上模式的 XML 實例如下:

<SCRestriction xmlns="http://inheritance-ext-res"
xmlns:xsi="http://www.w3.org/2001/XML Schema-instance"
xsi:schemaLocation="http://inheritance-ext-res CTSCRes.xsd">

<Base att1="val">This is base type</Base>
<Derived att2="12">This is restricted in the derived</Derived>
  
</SCRestriction>
complexContent

 

圖 5
圖 5:具有 complexContent 的 complexType 可用於限制模型組和屬性。

 

具有 complexContent 的 complexType 可以限制 complexType 具有 complexContent 的 complexType。如圖 5 中所示,在派生的 complexType 中,您必須重複基類中的整個內容模型並在需要時按照要求對其進行限制。可以按照限制 simpleContent 的同一方法來限制屬性。例如:

<?xml version="1.0"?>
<xsd:schema targetNamespace="http://inheritance-ext-res"
xmlns:tns="http://inheritance-ext-res"
xmlns:xsd="http://www.w3.org/2001/XML Schema"
elementFormDefault="qualified">
attributeFormDefault="unqualified">

<xsd:complexType name="BaseType">
<xsd:sequence>
<xsd:element name="child1" type="xsd:string" maxOccurs="unbounded" />
<xsd:element name="child2" type="xsd:string"/>
</xsd:sequence>
<xsd:attribute name="att1" type="xsd:string" use="optional" />
</xsd:complexType>

<xsd:complexType name="DerivedType">
<xsd:complexContent>
<xsd:restriction base="tns:BaseType">
<xsd:sequence>
<xsd:element name="child1" type="xsd:string" maxOccurs="4" />

<xsd:element name="child2">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="35" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>

</xsd:sequence>
<xsd:attribute name="att1" type="xsd:string" use="prohibited" />
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>

<xsd:element name="CCRestriction">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Base" type="tns:BaseType" />
<xsd:element name="Derived" type="tns:DerivedType" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>

</xsd:schema>
在以上模式中:

 

 

  1. 您將 DerivedType(從 BaseType 繼承)中的 child1 的基數從無限大限制爲 4。
  2. 您將 DerivedType(從 BaseType 繼承)中的 child2 的類型限制爲一個長度爲 35 的字符串。
  3. 您禁止從 BaseType 繼承屬性 att1。

 

對應於以上模式的 XML 實例如下:

<CCRestriction xmlns="http://inheritance-ext-res"
xmlns:xsi="http://www.w3.org/2001/XML Schema-instance"
xsi:schemaLocation="http://inheritance-ext-res CTCCRes.xsd">

<Base att1="val">
<child1>This is base type</child1>
<child2>This is base type</child2>
</Base>
  
<Derived>
<child1>This is restricted in the derived</child1>
<child2>This is restricted in the derived</child2>
</Derived>
  
</CCRestriction>
組裝模式

 

導入、包含和 可變式效果

許多 Java 項目都涉及多個不同的類和程序包,而不只是一個大的 Java 文件,這是因爲模塊化可以方便代碼的重用、讀取和維護。隨後,必須將必需的導入語句加入到類中,然後才能使用它們。同樣,在 XML 模式中,您必須在各種不同命名空間中管理不同的模式,並需要將必需的導入語句加入到模式中,然後才能使用它們。

可以使用 <import/> 和 <include/> 模式結構組裝 XML 模式,當然,以下應是該模式中位於其他任何聲明之前的第一個語句:

<schema>
<import namespace="foo" schemaLocation="bar.xsd" />
<include schemaLocation="baz.xsd" />
  ...
</schema>
當導入的模式具有 targetNamespace 時,將使用 <import />,而當包含的模式未聲明 targetNamespace 時,將使用 <include />。

 

下面,我們將介紹一個示例,該示例涉及兩個模式 A 和 B,且 A 引用 B 中聲明的項目。

情況 I
如果兩個模式都有 targetNamespace,且模式 A 的 targetNamespace (tnsA) 不同於模式 B 的 targetNamespace (tnsB),則 A 必須導入 B。

<import namespace="tnsB" schemaLocation="B.xsd">
但 A 導入 B 時和 A 包含 B 時不指定命名空間是一個錯誤。

 

情況 II
如果兩個模式都包含 targetNamespace,且模式 A 的 targetNamespace (tnsAB) 與模式 B 的 targetNamespace (tnsAB) 相同,則 A 必須包含 B。

<include schemaLocation="B.xsd">
A 導入 B 是錯誤的。

 

情況 III
如果模式 A 和 B 都沒有 targetNamespace。這種情況下,A 必須包含 B。

<include schemaLocation="B.xsd" />
情況 IV
如果模式 A 沒有 targetNamespace,而模式 B 包含 targetNamespace (tnsB),則 A 必須導入 B。
<import namespace="tnsB" schemaLocation="B.xsd" />
A 包含 B 是錯誤的,這是因爲 B 包含一個 targetNamespace。

 

情況 V
如果模式 A 包含 targetNamespace (tnsA),而模式 B 不包含 targetNamespace,情況又將如何?A 應包含 B。但如果我認爲在本例中,A 應導入 B,情況將如何?實際上,在這種情況下,A 可以導入或包含 B,且這兩個操作都是合法的,但效果並不相同。

如果 A 包含 B,則所包含的來自 B 的所有項目將獲取 A 的命名空間。這樣的包含被稱作 可變式 包含。

如果您不希望發生這樣的可變式效果,則必須在不指定命名空間情況下完成導入。沒有 namespace 屬性的導入允許對不包含目標命名空間的組件進行非限定性引用。

<import schemaLocation="B.xsd">
多次導入或包含一個模式不會產生錯誤,這是因爲模式處理器可以檢測這種情況並不再加載已加載的模式。因此,A.xsd 導入 B.xsd 和 C.xsd 並不產生錯誤;B.xsd 和 C.xsd 各自單獨導入 A.xsd。循環引用不會產生錯誤,但強烈建議您不要使用它。

 

順便說明的是,一個類似 <import /> 的簡單導入也是合法的。該方法只允許對不包含目標命名空間的外部組件進行非限定性引用,而不提供任何有關其所在位置的信息提示。模式處理器將利用某種機制提示出錯或查找未知項目,因模式處理器而異。但使用 <include /> 是非法的。

經驗法則:

 

  1. <include/> - 它的作用與在包含模式中以內聯方式定義被包含的模式相當。
  2. <import/> -如果被導入的模式與導入模式的 targetNamespace 不同則始終使用 <import/>。

 

重新定義模式

您可能並不總想用其原始格式組裝模式。例如,您可能需要修改從模式中導入的組件。在此類情況下,當我們需要重定義聲明而不更改其名稱時,我們使用重定義組件完成這一過程,要重定義的模式必須滿足以下限制條件:(a) 與 重定義模式文檔具有相同的 targetNamespace,(b) 根本沒有 targetNamespace,這種情況下,被重定義模式文檔將轉變爲重定義模式文檔的 targetNamespace。

例如:

 

actual.xsd
<?xml version="1.0"?>
<xsd:schema targetNamespace="http://inheritance-ext-res"
xmlns:tns="http://inheritance-ext-res"
xmlns:xsd="http://www.w3.org/2001/XML Schema"
elementFormDefault="qualified">
attributeFormDefault="unqualified">

<xsd:complexType name="BaseType">
<xsd:sequence>
<xsd:element name="child1" type="xsd:string" />
</xsd:sequence>
<xsd:attribute name="att1" type="xsd:string" use="required" />
</xsd:complexType>

<xsd:complexType name="DerivedType">
<xsd:complexContent>
<xsd:extension base="tns:BaseType">
<xsd:choice>
<xsd:element name="child2" type="xsd:string" />
<xsd:element name="child3" type="xsd:string" />
</xsd:choice>
<xsd:attribute name="att2" type="xsd:string" use="required" />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>

</xsd:schema>
redefine.xsd
<?xml version="1.0"?>
<xsd:schema targetNamespace="http://inheritance-ext-res"
xmlns:tns="http://inheritance-ext-res"
xmlns:xsd="http://www.w3.org/2001/XML Schema"
elementFormDefault="qualified">
attributeFormDefault="unqualified">
            
<xsd:redefine schemaLocation="actual.xsd">
<xsd:complexType name="DerivedType">
<xsd:complexContent>
<xsd:extension base="tns:DerivedType">
<xsd:sequence>
<xsd:element name="child4" type="xsd:string" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:redefine>

<xsd:element name="Redefine">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Base" type="tns:BaseType" />
<xsd:element name="Derived" type="tns:DerivedType" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>

</xsd:schema>
在以上模式中:

 

 

  1. 您在未更改其名稱的情況下,通過向內容模型中添加一個或多個元素重新定義了名稱爲 DerivedType 的 complexType。
  2. 不在重定義模式中重新定義基類,它將按原樣繼承。

 

注意,重定義類型時,類型名稱並不更改。所以,重定義的類型將其自身用作基類。

在以上示例中,我們重新定義了一個名爲 DerivedType 的 complexType 而未更改其名稱。重定義 DerivedType 時,對“DerivedType”的任何引用(例如,base="tns:DerivedType")都被認爲是引用實際的 DerivedType。重定義類型後,對 DerivedType 的任何引用都被認爲是引用重定義後的類型。

對應於以上重新定義的模式的 XML 實例如下:

<Redefine xmlns="http://inheritance-ext-res"
xmlns:xsi="http://www.w3.org/2001/XML Schema-instance"
xsi:schemaLocation="http://inheritance-ext-res redefine.xsd">

<Base att1="val">
<child1>This is base type</child1>
</Base>
  
<Derived att1="val" att2="val">
<child1>This is inherited from the base as is</child1>
<child2>This is added in the derived</child2>
<child4>This is added when redefining</child4>
</Derived>

</Redefine>
約束

 

身份約束

使用 XML 模式,您可以對元素和屬性的內容實施唯一性約束,這可以保證指定元素或屬性的值在實例文檔中是唯一的。實施唯一性時,必須要有一個其值需要進行唯一性檢查的項目,例如,ISBN 號。確定項目後,必須確定一個集合(例如,圖書集),以在其中對這些選定的項目的值進行唯一性檢查。

XML 模式爲實施唯一性約束提供了兩個結構: uniquekeyUnique 確保當指定值不爲空時,它們必須在定義的集合中是唯一的;key 確保指定值始終不爲空,並在定義的集合中是唯一的。

還有一個結構 — keyref,它指向某個已定義的鍵。Keyref 確保 keyref 指向的鍵集中存在 keyref 中指定項目的值。

這三個結構的全都具有相同的語法(它們全都使用選擇器和域),但含義不同。選擇器用於定義集合,以在其中實施在其中實施唯一性,(多個域用於定義一個組合項目)用於定義項目,以對其值進行唯一性檢查。選擇器的值均爲 XPath 表達式。XPath 表達式不支持缺省命名空間,因此必須通過顯式使用綁定到相應命名空間(如果命名空間中存在元素/屬性)的前綴以使 XPath 表達式支持命名空間。例如:

<?xml version="1.0"?>
<xsd:schema targetNamespace="http://identity-constraint"
xmlns:tns="http://identity-constraint"
xmlns:xsd="http://www.w3.org/2001/XML Schema"
elementFormDefault="qualified">
attributeFormDefault="unqualified">


<xsd:complexType name="BookType">
<xsd:sequence>
<xsd:element name="title" type="xsd:string" />
<xsd:element name="half-isbn" type="xsd:string" />
<xsd:element name="other-half-isbn" type="xsd:float" />
</xsd:sequence>
</xsd:complexType>

<xsd:element name="Books">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Book" type="tns:BookType" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>

<xsd:key name="isbn">
<xsd:selector xpath=".//tns:Book" />
<xsd:field xpath="tns:half-isbn" />
<xsd:field xpath="tns:other-half-isbn" />
</xsd:key>

</xsd:element>

</xsd:schema>
在以上模式中,我們聲明瞭一個名爲“isbn”的鍵,它表示由“field 指定的組合值不得爲空,並在由 selector 指定的圖書集中是唯一的”。

 

唯一粒子屬性 (UPA) 約束

UPA 約束確保按以下方式指定每個元素的內容模型:在驗證 XML 實例時,不存在模糊性,且可以明確確定正確的元素聲明以進行驗證。例如,以下模式違反了 UPA 約束:

<xsd:element name="upa">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="a" minOccurs="0"/>
<xsd:element name="b" minOccurs="0"/>
<xsd:element name="a" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
這是因爲在以上模式的相應 XML 實例中:
<upa>
<a/>
</upa>
不能確定 XML 實例中的元素“a”對應於模式中的哪個元素聲明 - 是位於“b”的元素聲明之前“a”的元素聲明,還是位於“b”的元素聲明之後的“a”的元素聲明。該限制使您只能編寫上面的 XML 實例類型的 XMLSchema。在本示例中,如果您只將元素“b”的 minOccurs 設置爲任何大於 0 的值,則不會違反 UPA。

 

因此,以下是一個有效模式:

<xsd:element name="upa">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="a" minOccurs="0"/>
<xsd:element name="b" minOccurs="1"/>
<xsd:element name="a" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
這是因爲在以上模式的相應 XML 實例中:
<upa>
<a/>
<b/>
</upa>
顯而易見的是,XML 實例中的元素“a”實際上是“a”的元素聲明(它位於該模式中“b”的元素聲明之前)實例。

 

結論

現在,您已經完成了本系列,您應瞭解以下內容:

 

  1. XML 和 XML 模式中的命名空間概念
  2. XML 模式中支持的標量數據類型以及如何使用 simpleType 進一步限制它們
  3. 元素內容、內容模型、模型組、粒子、擴展和限制 complexType、組裝模式、標識約束和 UPA(用於定義和約束 XML 的結構)。

 

至此,您應已經較好地掌握了 XML 模式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章