一个 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>
在上面的模式中,我们使用标准命名空间 (xs),与该命名空间关联的 URI 是模式语言定义,它具有标准值 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">
<!-- 简单元素定义 -->
<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"/>
<!-- 属性定义 -->
<xs:attribute name="orderid" type="xs:string"/>
<!-- 复杂元素定义 -->
<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>
restriction 元素表明数据类型是从 W3C XML 模式命名空间数据类型派生的。 因此,以下片段意味着元素或属性的值必须是字符串值
<xs:restriction base="xs:string">
restriction 元素更常用于对元素应用限制。 请查看上面模式中的以下几行
<xs:simpleType name="orderidtype">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]{6}"/>
</xs:restriction>
</xs:simpleType>
这表明元素或属性的值必须是字符串,它必须正好是六个连续的字符,这些字符必须是 0 到 9 之间的数字。