目录

XSD 示例


本章将演示如何编写 XML 模式。您还将了解到可以用不同的方式编写模式。


XML 文档

让我们看一下这个名为 "shiporder.xml" 的 XML 文档:

<?xml version="1.0" encoding="UTF-8"?>

<shiporder orderid="889923"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="shiporder.xsd">
  <orderperson>John Smith</orderperson>
  <shipto>
    <name>Ola Nordmann</name>
    <address>Langgt 23</address>
    <city>4000 Stavanger</city>
    <country>Norway</country>
  </shipto>
  <item>
    <title>Empire Burlesque</title>
    <note>Special Edition</note>
    <quantity>1</quantity>
    <price>10.90</price>
  </item>
  <item>
    <title>Hide your heart</title>
    <quantity>1</quantity>
    <price>9.90</price>
  </item>
</shiporder>

上面的 XML 文档由根元素 "shiporder" 组成,其中包含名为 "orderid" 的必需属性。 "shiporder" 元素包含三个不同的子元素:"orderperson"、"shipto" 和"item"。 "item" 元素出现两次,它包含一个 "title"、一个可选的 "note" 元素、一个 "quantity" 和一个 "price" 元素。

上面的行: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 告诉 XML 解析器应该根据模式验证该文档。 xsi:noNamespaceSchemaLocation="shiporder.xsd" 行指定架构所在的位置(此处与 "shiporder.xml" 位于同一文件夹中)。



创建 XML 架构

现在我们要为上面的 XML 文档创建一个架构。

我们首先打开一个新文件,我们将其命名为"shiporder.xsd"。为了创建模式,我们可以简单地遵循 XML 文档中的结构并定义我们找到的每个元素。我们将从标准 XML 声明开始,后跟定义架构的 xs:schema 元素:

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
...
</xs:schema>

在上面的 schema 中,我们使用标准命名空间 (xs),与此命名空间关联的 URI 是 Schema 语言定义,其标准值为 http://www.w3.org/2001/XMLSchema。

接下来,我们必须定义"shiporder" 元素。该元素有一个属性,并且包含其他元素,因此我们将其视为复杂类型。 "shiporder" 元素的子元素被 xs:sequence 元素包围,该元素定义了子元素的有序序列:

<xs:element name="shiporder">
  <xs:complexType>
    <xs:sequence>
      ...
    </xs:sequence>
  </xs:complexType>
</xs:element>

然后我们必须将 "orderperson" 元素定义为简单类型(因为它不包含任何属性或其他元素)。类型 (xs:string) 以与 XML 模式关联的命名空间前缀为前缀,指示预定义的模式数据类型:

<xs:element name="orderperson" type="xs:string"/>

接下来,我们必须定义两个复杂类型的元素:"shipto" 和 "item"。我们首先定义 "shipto" 元素:

<xs:element name="shipto">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="address" type="xs:string"/>
      <xs:element name="city" type="xs:string"/>
      <xs:element name="country" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

通过模式,我们可以使用 maxOccurs 和 minOccurs 属性定义元素可能出现的次数。 maxOccurs 指定元素的最大出现次数,minOccurs 指定元素的最小出现次数。 maxOccurs 和 minOccurs 的默认值为 1!

现在我们可以定义 "item" 元素。该元素可以在 "shiporder" 元素内多次出现。这是通过将 "item" 元素的 maxOccurs 属性设置为 "unbounded" 来指定的,这意味着 "item" 元素可以根据作者的意愿出现任意多次。请注意,"note" 元素是可选的。我们通过将 minOccurs 属性设置为零来指定这一点:

<xs:element name="item" maxOccurs="unbounded">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="title" type="xs:string"/>
      <xs:element name="note" type="xs:string" minOccurs="0"/>
      <xs:element name="quantity" type="xs:positiveInteger"/>
      <xs:element name="price" type="xs:decimal"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

我们现在可以声明 "shiporder" 元素的属性。由于这是必需的属性,我们指定 use="required"。

笔记:属性声明必须始终放在最后:

<xs:attribute name="orderid" type="xs:string" use="required"/>

以下是名为 "shiporder.xsd" 的架构文件的完整列表:

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="shiporder">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="orderperson" type="xs:string"/>
      <xs:element name="shipto">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="address" type="xs:string"/>
            <xs:element name="city" type="xs:string"/>
            <xs:element name="country" type="xs:string"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="item" maxOccurs="unbounded">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="title" type="xs:string"/>
            <xs:element name="note" type="xs:string" minOccurs="0"/>
            <xs:element name="quantity" type="xs:positiveInteger"/>
            <xs:element name="price" type="xs:decimal"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
    <xs:attribute name="orderid" type="xs:string" use="required"/>
  </xs:complexType>
</xs:element>

</xs:schema>

划分架构

以前的设计方法很简单,但是当文档复杂时,会很难阅读和维护。

下一个设计方法是首先定义所有元素和属性,然后使用 ref 属性引用它们。

以下是架构文件的新设计 ("shiporder.xsd"):

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<!-- definition of simple elements -->
<xs:element name="orderperson" type="xs:string"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="address" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
<xs:element name="title" type="xs:string"/>
<xs:element name="note" type="xs:string"/>
<xs:element name="quantity" type="xs:positiveInteger"/>
<xs:element name="price" type="xs:decimal"/>

<!-- definition of attributes -->
<xs:attribute name="orderid" type="xs:string"/>

<!-- definition of complex elements -->
<xs:element name="shipto">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="name"/>
      <xs:element ref="address"/>
      <xs:element ref="city"/>
      <xs:element ref="country"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

<xs:element name="item">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="title"/>
      <xs:element ref="note" minOccurs="0"/>
      <xs:element ref="quantity"/>
      <xs:element ref="price"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

<xs:element name="shiporder">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="orderperson"/>
      <xs:element ref="shipto"/>
      <xs:element ref="item" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute ref="orderid" use="required"/>
  </xs:complexType>
</xs:element>

</xs:schema>

使用命名类型

第三种设计方法定义类或类型,使我们能够重用元素定义。这是通过命名 simpleTypes 和 complexTypes 元素,然后通过元素的 type 属性指向它们来完成的。

这是架构文件的第三种设计 ("shiporder.xsd"):

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:simpleType name="stringtype">
  <xs:restriction base="xs:string"/>
</xs:simpleType>

<xs:simpleType name="inttype">
  <xs:restriction base="xs:positiveInteger"/>
</xs:simpleType>

<xs:simpleType name="dectype">
  <xs:restriction base="xs:decimal"/>
</xs:simpleType>

<xs:simpleType name="orderidtype">
  <xs:restriction base="xs:string">
    <xs:pattern value="[0-9]{6}"/>
  </xs:restriction>
</xs:simpleType>

<xs:complexType name="shiptotype">
  <xs:sequence>
    <xs:element name="name" type="stringtype"/>
    <xs:element name="address" type="stringtype"/>
    <xs:element name="city" type="stringtype"/>
    <xs:element name="country" type="stringtype"/>
  </xs:sequence>
</xs:complexType>

<xs:complexType name="itemtype">
  <xs:sequence>
    <xs:element name="title" type="stringtype"/>
    <xs:element name="note" type="stringtype" minOccurs="0"/>
    <xs:element name="quantity" type="inttype"/>
    <xs:element name="price" type="dectype"/>
  </xs:sequence>
</xs:complexType>

<xs:complexType name="shipordertype">
  <xs:sequence>
    <xs:element name="orderperson" type="stringtype"/>
    <xs:element name="shipto" type="shiptotype"/>
    <xs:element name="item" maxOccurs="unbounded" type="itemtype"/>
  </xs:sequence>
  <xs:attribute name="orderid" type="orderidtype" use="required"/>
</xs:complexType>

<xs:element name="shiporder" type="shipordertype"/>

</xs:schema>

限制元素指示数据类型派生自 W3C XML 模式命名空间数据类型。因此,以下片段意味着元素或属性的值必须是字符串值:

<xs:restriction base="xs:string">

限制元素更常用于对元素施加限制。查看上面架构中的以下几行:

<xs:simpleType name="orderidtype">
  <xs:restriction base="xs:string">
    <xs:pattern value="[0-9]{6}"/>
  </xs:restriction>
</xs:simpleType>

这表明元素或属性的值必须是字符串,必须是连续的六个字符,并且这些字符必须是 0 到 9 之间的数字。