Xml架构扩展顺序

时间:2013-09-17 10:47:56

标签: xml inheritance xsd

如果我有扩展名,我怎样才能确保派生元素位于基类元素的前面?默认是相反的方式。我本来喜欢使用all,但我知道这是不可能的。

<xs:complexType name="BaseClass">
  <xs:sequence>
    <xs:element name="foo" type="xs:string/>
    <xs:element name="bar" type="xs:string/>
  </xs:sequence>
</xs:complexType>
<xs:complexType name="DerivedClass">
  <xs:complexContent>
    <xs:extension base="BaseClass">
      <xs:sequence>
        <!-- This makes the order foo, bar, cheese, tomato -->
        <!-- But I need cheese, tomato, foo, bar -->
        <xs:element name="cheese" type="xs:string/>
        <xs:element name="tomato" type="xs:string/>
      </xs:sequence>
    </xs:extension>
  </xs:complexContent>
</xs:complexType>
<xs:element name="BaseClass" type="BaseClass"/>
<xs:element name="DerivedClass" type="DerivedClass" substitutionGroup="BaseClass"/>

我想接受的xml看起来像这样:

<mylist>
    <BaseClass>
     <foo>lala</foo>
     <bar>lala</bar>
    </BaseClass>
    <DerivedClass>
     <cheese>cheddar</cheese>
     <tomato>red</tomato>
     <foo>lala</foo>
     <bar>lala</bar>
    </DerivedClass>
</mylist>

目前我正在考虑将BaseClass的所有元素复制到DerivedClass中,但我不知道替换组会发生什么,不会发生什么。

3 个答案:

答案 0 :(得分:7)

  

如果我有扩展名,我怎样才能确保派生元素位于基类元素的前面?

不幸的是,这是不可能的。 当扩展complexType时,新元素将作为序列添加到基本元素。 基本上,新的内容模型将如下所示:

(base element model), (extension element model)

这就是XSD中的类型扩展的工作原理。 你可能想知道为什么? 因为扩展类型必须符合基本类型。 你不能把任何东西作为基础的扩展。

假设您有一个知道如何处理A类元素的软件。 软件可以假设实际上可以扩展类型A, 但无论如何,它必须能够在一个假定为A类的元素中找到它 它知道/期望的所有类型A ...以及类型A固有的元素内容 (这是最重要的事情之一)必须是第一个!

答案 1 :(得分:0)

在验证由PHP生成的XML时遇到了同样的问题。

This就是我解决它的方式。基本上,

  1. 迭代所有php类属性,
  2. 将当前类中的内容推送到一个数组中,
  3. 将父类中的内容推送到另一个数组中。
  4. 将当前类属性合并到父类属性的末尾
  5. 从重新排序的属性数组生成XML

答案 2 :(得分:0)

解决此问题的唯一方法是使用组,可以将其插入序列中的任何位置。但是,使用这种方法无法使用substitutionGroup

<xs:group name="BaseGroup">
  <xs:sequence>
    <xs:element name="foo" type="xs:string"/>
    <xs:element name="bar" type="xs:string"/>
  </xs:sequence>
</xs:group>
<xs:complexType name="BaseClass">
  <xs:group ref="BaseGroup"/>
</xs:complexType>
<xs:complexType name="DerivedClass">
  <xs:sequence>
    <xs:element name="cheese" type="xs:string"/>
    <xs:element name="tomato" type="xs:string"/>
    <xs:group ref="BaseGroup"/>
  </xs:sequence>
</xs:complexType>
<xs:element name="BaseClass" type="BaseClass"/>
<xs:element name="DerivedClass" type="DerivedClass"/>