具有相同名称但根据上下文具有不同子结构的元素的XML模式

时间:2008-10-09 17:48:30

标签: xsd

我尝试为收到的XML文档定义架构。

文件如下:

<root>
    <items>
        <group name="G-1">
            <item name="I-1"/>
            <item name="I-2"/>
            <item name="I-3"/>
            <item name="I-4"/>
        </group>
    </items>
    <data>
        <group name="G-1" place="here">
            <customer name="C-1">
                <item name="I-1" count="3"/>
                <item name="I-2" count="4"/>
            </customer>
            <customer name="C-2">
                <item name="I-3" count="7"/>
            </customer>
        </group>
    </data>
</root>

我在.NET 2.0中尝试过XmlSpy和xsd.exe。两者都创建了模式定义,允许<group> <item> <customer><group>元素下面<items>个元素。但我正在寻找的内容应该<item> <group>低于<data>元素,<customer>低于{{1}} {{1}}元素。

这是xml架构根本不具备的吗?

2 个答案:

答案 0 :(得分:6)

关键点(请参阅XML Schema Runtime Polymorphism via xsi:type and Abstract Types了解完整且正确的背景/位置/用法):

  1. 使用(abstract =“true”创建基类型以防止直接使用它)

    注意:ref属性替换了在别处定义的元素的name属性

    <xs:complexType name="CustomerType" abstract="true" > 
      <xs:sequence> 
        <xs:element ref="cust:FirstName" /> 
        <xs:element ref="cust:LastName" /> 
        <xs:element ref="cust:PhoneNumber" minOccurs="0"/> 
      </xs:sequence> 
      <xs:attribute name="customerID" type="xs:integer" /> 
    </xs:complexType>
    
  2. 通过扩展或限制基本类型

    来创建两个或更多派生类型
    <xs:complexType name="MandatoryPhoneCustomerType" > 
      <xs:complexContent> 
        <xs:restriction base="cust:CustomerType"> 
          <xs:sequence> 
            <xs:element ref="cust:FirstName" /> 
            <xs:element ref="cust:LastName" /> 
            <xs:element ref="cust:PhoneNumber" minOccurs="1" /> 
          </xs:sequence> 
        </xs:restriction> 
      </xs:complexContent> 
    </xs:complexType>
    

    <xs:complexType name="AddressableCustomerType" > 
      <xs:complexContent> 
        <xs:extension base="cust:CustomerType"> 
          <xs:sequence> 
            <xs:element ref="cust:Address" /> 
            <xs:element ref="cust:City" /> 
            <xs:element ref="cust:State" /> 
            <xs:element ref="cust:Zip" /> 
          </xs:sequence> 
        </xs:extension> 
      </xs:complexContent> 
    </xs:complexType>
    
  3. 在元素中引用基本类型

    <xs:element name="Customer" type="cust:CustomerType" />
    
  4. 在您的实例XML文档中,将特定的派生类型指定为xsi:type属性

    <cust:Customer customerID="12345" xsi:type="cust:MandatoryPhoneCustomerType" > 
      <cust:FirstName>Dare</cust:FirstName> 
      <cust:LastName>Obasanjo</cust:LastName> 
      <cust:PhoneNumber>425-555-1234</cust:PhoneNumber> 
    </cust:Customer>
    

    或:

    <cust:Customer customerID="67890" xsi:type="cust:AddressableCustomerType" > 
      <cust:FirstName>John</cust:FirstName> 
      <cust:LastName>Smith</cust:LastName> 
      <cust:Address>2001</cust:Address> 
      <cust:City>Redmond</cust:City> 
      <cust:State>WA</cust:State> 
      <cust:Zip>98052</cust:Zip> 
    </cust:Customer>
    

答案 1 :(得分:3)

是的,XSD可以解决这个问题。我从Visual Studio 2008生成了这个模式(比手工操作快得多)并且它会完成你正在寻找的东西:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="root">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="items">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="group">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element maxOccurs="unbounded" name="item">
                      <xs:complexType>
                        <xs:attribute name="name" type="xs:string" use="required" />
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                  <xs:attribute name="name" type="xs:string" use="required" />
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="data">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="group">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element maxOccurs="unbounded" name="customer">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element maxOccurs="unbounded" name="item">
                            <xs:complexType>
                              <xs:attribute name="name" type="xs:string" use="required" />
                              <xs:attribute name="count" type="xs:unsignedByte" use="required" />
                            </xs:complexType>
                          </xs:element>
                        </xs:sequence>
                        <xs:attribute name="name" type="xs:string" use="optional" />
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                  <xs:attribute name="name" type="xs:string" use="required" />
                  <xs:attribute name="place" type="xs:string" use="required" />
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>