重用没有子复杂类型的XML模式元素/类型

时间:2014-08-27 08:46:25

标签: xml design-patterns xsd reusability

我已经定义了许多其他模式中常用的类型模式。

<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://www.exampleURI.com/MyTypes" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mytypes="http://www.exampleURI.com/MyTypes">
    <xs:complexType name="Order">
        <xs:sequence>
            <xs:element name="Customer" type="mytypes:Customer" minOccurs="1" maxOccurs="1"/>
            <xs:element name="Date" type="xs:date" minOccurs="1" maxOccurs="1"/>
            <xs:element name="Products" type="mytypes:Products" minOccurs="1" maxOccurs="1"/>
            <xs:element name="Total" type="xs:decimal" minOccurs="1" maxOccurs="1"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="Product">
        <xs:sequence>
            <xs:element name="Name" type="xs:string" minOccurs="1" maxOccurs="1"/>
            <xs:element name="Variation" type="mytypes:Variation" minOccurs="0" maxOccurs="1"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="Variation">
        <xs:sequence>
            <xs:element name="Color" type="xs:string" minOccurs="1" maxOccurs="1"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="Customer">
        <xs:sequence>
            <xs:element name="Discount" type="xs:int" minOccurs="1" maxOccurs="1"/>
            <xs:element name="Name" type="xs:string" minOccurs="1" maxOccurs="1"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="Products">
        <xs:sequence>
            <xs:element name="Product" type="mytypes:Product" minOccurs="1" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

通常我想重用这些类型,但不能重用所有ComplexType子元素。例如,以下 OrderList 响应必须包含订单客户数据,但不是产品数据。当我从先前的模式引用Order类型时,它将包含Order及其所有子元素。

<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://www.exampleURI.com/OrderList" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:s1="http://www.exampleURI.com/OrderList" xmlns:mytypes="http://www.exampleURI.com/MyTypes">
    <xs:import namespace="http://www.exampleURI.com/MyTypes" schemaLocation="types.xsd"/>
    <xs:element name="OrderListResponse" type="s1:OrderListResponse"/>
    <xs:complexType name="ResponseData">
        <xs:sequence>
            <xs:element name="id" type="xs:long" minOccurs="1" maxOccurs="1"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="Orders">
        <xs:sequence>
            <xs:element name="Order" type="mytypes:Order" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="OrderListResponse">
        <xs:sequence>
            <xs:element name="Orders" type="s1:Orders" minOccurs="1" maxOccurs="1"/>
            <xs:element name="Responsedata" type="s1:ResponseData" minOccurs="1" maxOccurs="1"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

我的目标:

  • 定义OrderListResponse,以便在Order下只返回SimpleType元素。
  • 仅将Order.Customer ComplexType添加到响应中。
  • 当我向MyTypes架构进行向后兼容更改时(例如新的可选元素),只有当它们是SimpleTypes(字符串,日期等)时,它们才应包含在OrderListResponse中。

是否有任何模式可以实现这些目标,还是应该将MyTypes模式类型复制粘贴到所有其他模式并删除不需要的子元素?

1 个答案:

答案 0 :(得分:2)

如果我正确理解您的问题,装饰器模式听起来就像满足您的需求,您可以使用扩展元素在XML中实现。首先定义一个OrderSimple类型,其中包含将要共享的简单元素。然后创建一个OrderComplex类型,它扩展OrderSimple以添加您定义的复杂元素。当然,您可以根据需要命名。例如:

<xs:complexType name="OrderSimple">
    <xs:sequence>
        <xs:element name="Date" type="xs:date" minOccurs="1" maxOccurs="1"/>
        <xs:element name="Total" type="xs:decimal" minOccurs="1" maxOccurs="1"/>
    </xs:sequence>
</xs:complexType>
<xs:complexType name="OrderComplex">
    <xs:complexContent>
        <xs:extension base="OrderSimple">
            <xs:sequence>
                <xs:element name="Customer" type="mytypes:Customer" minOccurs="1" maxOccurs="1"/>
                <xs:element name="Products" type="mytypes:Products" minOccurs="1" maxOccurs="1"/>
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

然后,您所要做的就是引用适合您正在构建的响应的类型。

另一种方法可能是简单地设置complexTypes的 minOccurs 属性,使它们在响应中可以为null,具体取决于您希望响应对象的“纯粹”程度。