XSD:如何创建一个多态的“列表”?

3

我正在尝试构建一个元素类型,它保留了一个change元素类型的列表,该元素类型是几个其他子类型的基本类型。我得到了这段代码:

<xs:complexType name="change_list" >
    <xs:annotation>
      <xs:documentation>List of changes.</xs:documentation>
    </xs:annotation>

    <xs:sequence>
      <xs:choice minOccurs="1" maxOccurs="unbounded" >

        <xs:element name="change" type="aos:change" >
          <xs:annotation>
            <xs:documentation>Generic or specific type of change.</xs:documentation>
          </xs:annotation>
        </xs:element>

        <xs:element name="activate" type="aos:activate" >
          <xs:annotation>
            <xs:documentation>Change that will activate an element or do nothing if already activated.</xs:documentation>
          </xs:annotation>
        </xs:element>

        <xs:element name="deactivate" type="aos:deactivate" >
          <xs:annotation>
            <xs:documentation>Change that will deactivate an element or do nothing if already deactivated.</xs:documentation>
          </xs:annotation>
        </xs:element>

        <xs:element name="switch" type="aos:switch" >
          <xs:annotation>
            <xs:documentation>Change that will activate the element if deactivated or deactivate it if activated.</xs:documentation>
          </xs:annotation>
        </xs:element>

        <xs:element name="transform" type="aos:transform" >
          <xs:annotation>
            <xs:documentation>
              Change that will modify the geometric state of the element
              by applying one or several geometric transformations.
            </xs:documentation>
          </xs:annotation>
        </xs:element>


      </xs:choice>
    </xs:sequence>

我正在使用CodeSynthesis生成C++代码。

现在,这似乎过于复杂了,因为我们已经清楚地定义了对不同类型的访问。我认为我想要的是更简单的东西,比如:

更改列表。

    <xs:sequence>
      <xs:choice minOccurs="1" maxOccurs="unbounded" >

        <xs:element name="change" type="aos:change" >
          <xs:annotation>
            <xs:documentation>Generic or specific type of change.</xs:documentation>
          </xs:annotation>
        </xs:element>

      </xs:choice>
    </xs:sequence>

现在我不能为不同的更改子类型使用不同的标签。 所以我想也许一个好的解决方案是使用替换组。 但那样我就失去了使用特定子类型属性和元素的能力。 原始解决方案是否适合这样做(拥有一个可以获取子类型的基础类型对象列表)?

1
替换组的问题究竟是什么?在XML Schema中建模多态性是一种常见做法。 - lexicore
也许我错了,但据我所知,使用替换组是一种别名,对吗?那么我可以将其用作“change”标记的别名,我对吗?那么我不能使用更改标记子元素类型特定的元素和属性。我对吗? - Klaim
3个回答

3
不知道你是否还需要答案...但是以下模式可以满足你的需求。
首先是基础类型和两个具体的子类型(确保你的基类设置了abstract="true"):
<xs:complexType abstract="true" name="BaseTask">
  <xs:sequence>
    <xs:element name="Name" type="xs:string" />
  </xs:sequence>
</xs:complexType>

<xs:complexType name="ConcreteTask1">
  <xs:complexContent>
    <xs:extension base="BaseTask">

    </xs:extension>
  </xs:complexContent>
</xs:complexType>

<xs:complexType name="ConcreteTask2">
  <xs:complexContent>
    <xs:extension base="BaseTask">
      <xs:sequence>
        <xs:element name="Description" type="xs:string" />
      </xs:sequence>
    </xs:extension>
  </xs:complexContent>
</xs:complexType>

接着添加一个列表,其中包含继承自BaseTask的元素:

<xs:element name="TaskList">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="Tasks" minOccurs="0" maxOccurs="unbounded" type="BaseTask" />
    </xs:sequence>
  </xs:complexType>
</xs:element>

XML看起来像这样:
<TaskList>
  <Tasks xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ConcreteTask1">
    <Name>Foo1</Name>
  </Tasks>
  <Tasks xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ConcreteTask2">
    <Name>Foo2</Name>
    <Description>Test</Description>
  </Tasks>
</TaskList>

0
你想要的在xml-schema中不可能实现。你可以扩展(或限制)已定义的类型,但这将创建一个新类型。子类型多态性(包含多态性)在xml-schema中不存在。

那么,就没有办法说一个序列例如可以有一个类型的元素或这个类型的子类型吗?或者在xsd中是否有相应的等效物可以帮助我解决我的问题? - Klaim

0
听起来你想要的是一个变更列表,但你还希望在列表中记录变更类型(启用、切换等)。
我会创建一个简单元素叫做 ChangeType 元素,并添加一个 "type" 属性,其数据类型为另一个元素 ChangeTypeType,它将是您有效变更类型的枚举。例如:
<element name="ChangeList" type="ChangeListType"/>    
<complexType name="ChangeListType">
    <annotation>
        <documentation>
            A list of changes
        </documentation>
    </annotation>
    <sequence>
        <element name="change" type="ChangeType" minOccurs="1" maxOccurs="unbounded">
            <annotation>
                <documentation>
                    A change event
                </documentation>
            </annotation>
        </element>
    </sequence>
</complexType>

<complexType name="ChangeType">
    <annotation>
        <documentation>
            A change unit
        </documentation>
    </annotation>
    <attribute ref="typeOfChange" use="required"/>
</complexType>

<attribute name="typeOfChange" type="ChangeTypeType">
    <annotation>
        <documentation>
            The kind of change
        </documentation>
    </annotation>
</attribute>

<simpleType name="ChangeTypeType">
    <annotation>
        <documentation>
            Describes the types of allowed changes
        </documentation>
    </annotation>
    <restriction base="token">
        <enumeration value="activate"/>
        <enumeration value="activate"/>
                    <enumeration value="switch"/>
                    <enumeration value="transform"/>
    </restriction>
</simpleType>

这将为您提供一个类似于XML文档的内容:
<ChangeList>
    <change typeOfChange="activate/>
    <change typeOfChange="switch/>
    <change typeOfChange="transform/>
</ChangeList>

我已经有了,但这并不能解决问题:如果你这样做,就无法访问子元素类型特定的内容。例如,如果只有开关具有“目标”元素(甚至属性),则无法在列表中设置它。 - Klaim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接