如何分组类型和XSD中的子类型

时间:2011-07-11 16:09:12

标签: xml xsd

我有这样的XML:

<type>
    <mainType>...</mainType>
    <subtype>...<subtype>
</type>

mainTypes是受限制的xs:strings(它们的列表)。每个mainType都有一个可能的子类型列表。 IE:
mainTypeA有可能的子类型:subtype1,subtype2,subtype3
mainTypeB有可能的子类型:subtype4,subtype5

如何在XSD中表示这一点,以便每个子类型枚举都专门与其主要类型相关联? 有没有更好的方法来表示这两个字段,使XSD更简单?我并不反对更改XML文档结构。

4 个答案:

答案 0 :(得分:6)

(这可能是@hughadick的答案中的另一个评论,但对于这样的话太长了。)

初始设计中存在两个问题,这会使结构复杂化:

  1. 您可以将某些内容视为共现约束,因为<subType>只有在<mainType>出现时才能显示
  2. 元素声明是不一致的,因为你有
    • ...在相同的背景下(<type>的孩子们)
    • ...具有相同名称的元素(<mainType>
    • ...但具有不同的类型(不同的值和相关的<subType>元素)。
  3. 在XML Schema 1.0中,没有一般方法可以使这些功能成为可能,尽管在某些情况下和/或某些方法可以实现这些功能。模糊类型问题的一种可能的解决方法是在实例文档中使用xsi:type属性来确定使用的模式类型(示例1)。

    我建议你不要使用一些可能的解决方法来解决这些问题,而是要关注@hughadick的answer,并为所有主要类型创建不同名称的元素,这些元素对于不同的子类型将再次具有不同的元素。如果您不喜欢将类型名称作为元素名称(或者它不是对XML元素名称有效),您可以将其放在属性中,可能使用默认值或固定值(<myType1 typeName="Type 1 name">)(例2)。如果子类型是互斥的,您可以将它们放在属性(<myType1 subType="subType2">)中。如果你真的想在元素内容(<mainType1>Type 1 name</mainType1>)中有类型名称,那么最好将<subType>元素作为以下兄弟而不是<mainType1>的子元素,因为那样会导致混合内容容易导致空白和文本节点位置相关的问题(例3)。

    是的,替换组也可以与@hughadick的答案一起使用。您将拥有一个抽象的<mainType>元素,并且所有主要类型元素定义都具有substitutionGroup="mainType"属性。您仍然需要为不同的主要类型元素使用不同的名称,因为它们允许不同的允许元素/值集合。这些元素的类型必须从它们替换的抽象<mainType>元素的类型派生(例4)。

    代码示例

    示例1

    <xs:element name="type">
        <xs:complexType>
            <xs:choice>
                <xs:element name="mainType" type="mainType1"/>
                <xs:element name="mainType" type="mainType2"/>
                <xs:element name="mainType" type="mainType3"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    
    <type>
        <mainType xsi:type="mainType1"/>
    </type>
    

    示例2

    <xs:element name="mainType1">
        <xs:complexType>
            <xs:choice>
                <xs:element ref="subType1"/>
                <xs:element ref="subType2"/>
                <xs:element ref="subType3"/>
            </xs:choice>
            <xs:attribute name="typeName" type="xs:string"/>
        </xs:complexType>
    </xs:element>
    

    示例3

    <xs:element name="type">
        <xs:complexType>
            <xs:choice>
                <xs:sequence>
                    <xs:element name="mainType" type="mainType1"/>
                    <xs:choice>
                        <xs:element ref="subType1"/>
                        <xs:element ref="subType2"/>
                        <xs:element ref="subType3"/>
                    </xs:choice>
                </xs:sequence>
                <!-- repeat similarily for other main types -->
                <xs:sequence>
                    <!-- ... -->
                </xs:sequence>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    

    示例4

    <xs:element name="type">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="mainType"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    
    <xs:element name="mainType" type="mainType" abstract="true"/>
    <xs:element name="mainType1" type="typeForMainType1" substitutionGroup="mainType"/>
    <xs:element name="mainType2" type="typeForMainType2" substitutionGroup="mainType"/>
    
    <xs:complexType name="mainType">
    <!-- definition for mainType -->
    </xs:complexType>
    
    <xs:complexType name="typeForMainType1">
        <xs:complexContent>
            <xs:restriction base="mainType">
                <!-- definition for mainType1 -->
            </xs:restriction>
        </xs:complexContent>
    </xs:complexType>
    
    <xs:complexType name="typeForMainType2">
        <xs:complexContent>
            <xs:restriction base="mainType">
                <!-- definition for mainType1 -->
            </xs:restriction>
        </xs:complexContent>
    </xs:complexType>
    

答案 1 :(得分:3)

您需要明确将类型定义为包含主类型和子类型。在每个关键时刻,您明确定义该点的可能性:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="root">
    <xs:complexType>
      <xs:choice>
        <xs:element name="MyType1" type="MyType1Type" />
        <xs:element name="MyType2" type="MyType2Type" />
      </xs:choice>
    </xs:complexType>
  </xs:element>
  <!-- MainType definitiions -->
  <xs:complexType name="MyType1Type>
    <xs:all minOccurs="1">
      <xs:element name="MyType1SubType1" type="MyType1SubType1Type" />
      <xs:element name="MyType1SubType2" type="MyType1SubType2Type" />
      <xs:element name="MyType1SubType3" type="MyType1SubType3Type" />
    </xs:all>
  </xs:complexType>
  <xs:complexType name="MyType2Type>
    <xs:all minOccurs="1">
      <xs:element name="MyType2SubType4" type="MyType2SubType4Type" />
      <xs:element name="MyType2SubType5" type="MyType2SubType5Type" />
    </xs:all>
  </xs:complexType>
  <!-- SubType definitions -->
  <xs:complexType name="MyType1SubType1Type>
    <xs:sequence>
      <xs:element name="MyType1SubType1TypeValue" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="MyType1SubType2Type>
    <xs:sequence>
      <xs:element name="MyType1SubType2TypeValue" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="MyType1SubType3Type>
    <xs:sequence>
      <xs:element name="MyType1SubType3TypeValue" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="MyType2SubType4Type>
    <xs:sequence>
      <xs:element name="MyType2SubType4TypeValue" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="MyType2SubType5Type>
    <xs:sequence>
      <xs:element name="MyType2SubType5TypeValue" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
</xs:schema>

所以它有点长,但在XSD中几乎没有捷径。您需要确定所有类型的定义。希望这会有所帮助。

答案 2 :(得分:0)

XML有很多不同的选择。你只需要根据自己的需要来构建它。对我来说,我喜欢在可能的情况下使用属性,这只是个人偏好。这只是一个建议。

<types>
   <type name="mainTypeA">
       <subType name="subType1"></subType>
       <subType name="subType2"></subType>
       <subType name="subType3"></subType>
   </type>
   <type name="mainTypeB">
       <subType name="subType4"></subType>
       <subType name="subType5"></subType>
       <subType name="subType6"></subType>
   </type>
</types>

另一个建议:

<type name="MainTypeA">
    <type name="subType1"></type>
    <type name="subtype2"></type>
</type>
<type name="MainTypeB">
    <type name="subType3">
        <type name="subSubType1"></type>
    </type>
    <type name="subtype4"></type>
</type>

答案 3 :(得分:0)

<type>
    <name>MainTypeA</name>
    <type>
        <name>subtype1</name>
    </type>
    <type>
        <name>subtype1</name>
    </type>
</type>

<type name="MainTypeA">
    ...
    <type name="subtype1">
        ...
    </type>
    <type name="subtype2">
        ...
    </type>
</type>

这无限地允许子类型等。子类型本质上与类型不同吗?如果没有,则无需为它们创建单独的subType标记。任何深度的所有类型的统一标签名称都可以使分析更容易。