如何在complexType中将无界组与受限制的组混合?

时间:2009-02-05 17:28:05

标签: xml xsd

我正在尝试创建一个可以为通过在.NET中序列化类型生成的XAML生成XSD的工具,但这不是特定于.NET的。

假设我有一个类型。此类型具有属性并且是集合。

public class MyType : Collection<CollectedType>
{
  public PType1 PropertyOne {get;set;}
  public PType2 PropertyTwo {get;set;}
}

这序列化为以下(省略对象图构造):

<MyType xmlns="clr-namespace:blahblahblah">
  <CollectedType name="First instance in the collection"/>
  <CollectedType name="Second instance in the collection"/>
  <MyType.PropertyOne>
    <PType1 Value = "Serialized object in PropertyOne" />
  </MyType.PropertyOne>
  <MyType.PropertyTwo>
    <PType2 Value = "Serialized object in PropertyTwo" />
  </MyType. PropertyTwo >
</MyType>

在为此类型生成XSD时,我可以说以下内容:

  • MyType是complexType
  • MyType将包含对名为CollectedTypeGroup
  • 的组的引用
    • CollectedTypeGroup包含CollectedType的元素和扩展CollectedType
    • 的类型的元素
  • MyType将包含一个名为MyType.PropertyOne
  • 的元素
    • PType1是另一种complexType
  • MyType将包含一个名为MyType.PropertyTwo
  • 的元素
    • PType2是另一种complexType

这一切都相对容易。这是生成的xsd:

的一大块
  <xs:complexType name="MyType">
    <xs:sequence>
      <xs:element name="MyType.PropertyOne" type="PType1"/>
      <xs:element name="MyType.PropertyOne" type="PType1"/>
      <xs:group ref="CollectedTypeGroup"/>
    </xs:sequence>
  </xs:complexType>

现在来了困难的部分。因为XML将被映射回对象图,所以我有一个关于如何将元素添加到MyType的限制列表,其中必须强制执行模式。如果未强制执行这三个要求并且仅强制执行这三个要求,我将面临尝试使用我的架构的用户的问题:

1)添加到MyType 的元素不得限于特定订单
2)表示我的对象属性的元素只能出现一次或不出现
3)组元素必须是无界的;它们可以出现在父元素中的任何位置和0 ... *次

这是我有一个可怕的时间。我无法找到令人满意的选择,序列,所有等组合来满足这三个要求。我也尝试将元素放在一个单独的组中,complexTypes等。似乎没什么用。

如何将我的元素和我的组合成一个complexType并满足我的三个要求?

2 个答案:

答案 0 :(得分:1)

这是否符合您的需求?

  <xs:element name="MyType" type="MyType.Type"/>
    <xs:complexType name="MyType.Type">
      <xs:sequence>
        <xs:group ref="CollectedTypeGroup" minOccurs="0" maxOccurs="unbounded"/>
        <xs:choice minOccurs="0">
          <xs:sequence>
            <xs:element name="MyType.PropertyOne" type="PType1.Type"/>
            <xs:group ref="CollectedTypeGroup" minOccurs="0" maxOccurs="unbounded"/>
            <xs:sequence minOccurs="0">
              <xs:element name="MyType.PropertyTwo" type="PType2.Type"/>
              <xs:group ref="CollectedTypeGroup" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
          </xs:sequence>
          <xs:sequence>
            <xs:element name="MyType.PropertyTwo" type="PType2.Type"/>
            <xs:group ref="CollectedTypeGroup" minOccurs="0" maxOccurs="unbounded"/>
            <xs:sequence minOccurs="0">
              <xs:element name="MyType.PropertyOne" type="PType1.Type"/>
              <xs:group ref="CollectedTypeGroup" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
          </xs:sequence>
        </xs:choice>
      </xs:sequence>
    </xs:complexType>
    <xs:group name="CollectedTypeGroup">
      <xs:choice>
        <xs:element name="CollectedType" type="CollectedType.Type"/>
        <xs:element name="DerivedCollectedType" type="CollectedType.Type"/>
        <xs:element name="DerivedCollectedType2" type="CollectedType.Type"/>
      </xs:choice>
    </xs:group>
    <xs:complexType name="CollectedType.Type">
      <xs:attribute name="name" type="xs:string"/>
    </xs:complexType>
    <xs:complexType name="PType1.Type">
      <xs:sequence>
        <xs:element name="PType1">
          <xs:complexType>
            <xs:attribute name="Value" type="xs:string"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
    <xs:complexType name="PType2.Type">
      <xs:sequence>
        <xs:element name="PType2">
          <xs:complexType>
            <xs:attribute name="Value" type="xs:string"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>

答案 1 :(得分:1)

这让人困惑多年,但是无法在XML Schema中定义这个内容模型。

唯一的模式粒子可以保证元素一次或根本不出现,并且以任何顺序出现xsd:all。但是,正如您可能已经发现的那样,xsd:all中元素的最大界限是1,而不是无界限。

如果您的集合元素有一个容器元素,那么您可以放弃它:

<xs:complexType name="MyType">
    <xs:sequence>
      <xs:element name="MyType.PropertyOne" type="PType1" minOccurs="0"/>
      <xs:element name="MyType.PropertyTwo" type="PType2" minOccurs="0"/>
      <xs:element name="collection" type="CollectionType" minOccurs="0"/>
    </xs:sequence>
</xs:complexType>
<xs:complexType name="CollectionType">
    <xs:sequence>
       <xs:group ref="CollectedTypeGroup"/>
    </xs:sequence>
</xs:complexType>

将事物分组,复杂类型等等,无法帮助您解决此问题,因为架构处理器会将其展平以执行其验证。

仅供参考,Relax NG没有此限制。您可以使用其“interleave”结构来定义您要查找的内容(它与模式'all'相同,但允许无限制的子项。)

希望这有帮助。