4

我有一个包含多个地址的 XML 模式:

<xs:element name="personal_address" maxOccurs="1">
  <!-- address fields go here -->
</xs:element>
<xs:element name="business_address" maxOccurs="1">
  <!-- address fields go here -->
</xs:element>

在每个地址元素中,我包含一个“美国州”枚举:

<xs:simpleType name="state">
    <xs:restriction base="xs:string">
        <xs:enumeration value="AL" />
        <xs:enumeration value="AK" />
        <xs:enumeration value="AS" />
                ....
            <xs:enumeration value="WY" />
        </xs:restriction>
</xs:simpleType>

如何编写一次“美国州”枚举并在每个地址元素中重新使用它?如果这是一个 n00b 问题,我提前道歉——我以前从未写过 XSD。

我最初的尝试如下:

<xs:element name="business_address" maxOccurs="1">
  <!-- address fields go here -->
  <xs:element name="business_address_state" type="state" maxOccurs="1"></xs:element>
</xs:element>
4

2 回答 2

5

我认为你在正确的轨道上。我认为它更多地与 XML 命名空间有关。尝试以下操作:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.example.org/foo"
    xmlns:tns="http://www.example.org/foo"
    elementFormDefault="qualified">
    <xs:element name="business_address">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="business_address_state"
                    type="tns:state" maxOccurs="1" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:simpleType name="state">
        <xs:restriction base="xs:string">
            <xs:enumeration value="AL" />
            <xs:enumeration value="AK" />
            <xs:enumeration value="AS" />
            <xs:enumeration value="WY" />
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

请注意,类型是tns:state而不仅仅是state

然后这就是你将如何使用它:

<?xml version="1.0" encoding="UTF-8"?>
<business_address xmlns="http://www.example.org/foo"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.example.org/foo foo.xsd ">
    <business_address_state>AL</business_address_state>
</business_address>

请注意,此 XML 使用与 XSD 的 targetNamespace 相同的默认命名空间

于 2008-10-22T20:57:12.433 回答
2

虽然命名空间有助于保持模式的组织和防止冲突,但不是上面的命名空间允许重用,而是将类型放置为 <xs:schema> 根的直接子级,使其成为全局类型。(可在没有命名空间限定符的命名空间内使用,并且可以在任何使用 tns: 限定符的 tns 命名空间可见的地方使用。)

我更喜欢按照“伊甸园”方法构建我的模式,这可以最大限度地重用元素和类型(并且还可以促进对精心制作的唯一类型/元素的外部逻辑引用,例如存储在数据库中的数据字典.

请注意,虽然“伊甸园”模式模式提供了最大的重用性,但它也涉及最多的工作。在这篇文章的底部,我提供了指向博客系列中涵盖的其他模式的链接。

伊甸园方法 http://blogs.msdn.com/skaufman/archive/2005/05/10/416269.aspx

通过全局定义所有元素来使用模块化方法,并且像 Venetian Blind 方法一样,所有类型定义都是全局声明的。每个元素都被全局定义为节点的直接子节点,并且其类型属性可以设置为指定的复杂类型之一。

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="TargetNamespace" xmlns:TN="TargetNamespace" xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:element name="BookInformation" type="BookInformationType"/>
    <xs:complexType name="BookInformationType">
        <xs:sequence>
            <xs:element ref="Title"/>
            <xs:element ref="ISBN"/>
            <xs:element ref="Publisher"/>
            <xs:element ref="PeopleInvolved" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="PeopleInvolvedType">
        <xs:sequence>
            <xs:element name="Author"/>
        </xs:sequence>
    </xs:complexType>
    <xs:element name="Title"/>
    <xs:element name="ISBN"/>
    <xs:element name="Publisher"/>
    <xs:element name="PeopleInvolved" type="PeopleInvolvedType"/>
</xs:schema>
这种方法的优点是模式是可重用的。由于元素和类型都是全局定义的,因此两者都可以重用。这种方法提供了最大数量的可重用内容。缺点是架构冗长。当您创建通用库时,这将是一个合适的设计,在这些库中,您可以对模式元素和类型的范围以及它们在其他模式中的使用做出任何假设,特别是在可扩展性和模块化方面。


由于每个不同的类型和元素都有一个单一的全局定义,这些规范的粒子/组件可以与数据库中的标识符一对一地关联。乍一看,维护文本 XSD 粒子/组件与数据库之间的关联似乎是一项令人厌烦的持续手动任务,但 SQL Server 2005 实际上可以通过语句生成规范架构组件标识符

CREATE XML SCHEMA COLLECTION

http://technet.microsoft.com/en-us/library/ms179457.aspx

相反,为了从规范粒子构造模式,SQL Server 2005 提供了

SELECT xml_schema_namespace function

http://technet.microsoft.com/en-us/library/ms191170.aspx

ca·non·i·cal 与数学有关。(方程、坐标等)“最简单或标准形式” http://dictionary.reference.com/browse/canonical

其他更容易构建但不太可重复/更“非规范化/冗余”的模式模式包括

俄罗斯娃娃方法http://blogs.msdn.com/skaufman/archive/2005/04/21/410486.aspx

该模式有一个单一的全局元素 - 根元素。所有其他元素和类型都嵌套得越来越深,因为每种类型都适合它上面的类型,所以给它起了名字。由于此设计中的元素是在本地声明的,因此它们不能通过 import 或 include 语句重用。

萨拉米切片方法 http://blogs.msdn.com/skaufman/archive/2005/04/25/411809.aspx

所有元素都是全局定义的,但类型定义是本地定义的。这样其他模式可以重用这些元素。使用这种方法,具有本地定义类型的全局元素提供了元素内容的完整描述。此信息“切片”是单独声明的,然后重新聚合在一起,也可以拼凑在一起以构建其他模式。

威尼斯盲人方法 http://blogs.msdn.com/skaufman/archive/2005/04/29/413491.aspx

与俄罗斯娃娃方法类似,它们都使用单个全局元素。Venetian Blind 方法通过全局命名和定义所有类型定义来描述模块化方法(与全局声明元素和本地类型的 Salami Slice 方法相反)。每个全局定义的类型都描述了一个单独的“slat”,并且可以被其他组件重用。此外,根据架构顶部的 elementFormDefault 属性设置,所有本地声明的元素都可以是命名空间限定的或命名空间不限定的(slat 可以是“打开的”或“关闭的”)。

于 2008-10-24T05:54:25.843 回答