XSD扩展了一个类型,并在顶部和底部添加字段

时间:2012-12-03 11:06:47

标签: xsd jaxb

我有以下XSD(为了提出这个问题):

  <xsd:complexType name="BaseType" abstract="true">
    <xsd:sequence>
      <xsd:element name="field1" type="xsd:string"/>
      <xsd:element name="field2" type="xsd:string"/>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="ExtendedType">
    <xsd:complexContent>
      <xsd:extension base="tns:BaseType">
        <xsd:sequence>
          <xsd:element name="fieldA" type="xsd:string"/>
          <xsd:element name="fieldB" type="xsd:string"/>
        </xsd:sequence>
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>

  <xsd:element name="extendedType" type="tns:ExtendedType"/>

这允许XML文件如下:

<extendedType>
  <field1>hello</field1>
  <field2>world</field2>
  <fieldA>aaa</fieldA>
  <fieldB>bbb</fieldB>
</extendedType>

也就是说,两个新闻字段fieldA和fieldB被添加到BaseType的底部。

有没有办法扩展BaseType, 但是在顶部插入fieldA,在底部插入fieldB? 这样有效吗?

<extendedType>
  <fieldA>aaa</fieldA>
  <field1>hello</field1>
  <field2>world</field2>
  <fieldB>bbb</fieldB>
</extendedType>

以及如何使JAXB按预期工作?

2 个答案:

答案 0 :(得分:4)

http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#Complex_Type_Definition

  

通过在另一个定义的内容模型的末尾添加额外的内容模型粒子,或者通过具有其他属性声明,或两者兼而有之,扩展另一个的复杂类型是这样做的。

     
      
  • 注意:此规范仅允许附加,而不允许其他类型的扩展。此决定简化了将实例从派生类型转换为基类型所需的应用程序处理。未来版本可能允许更多类型的扩展,需要更复杂的转换才能实现转换。
  •   

因此,在扩展类型时,只在底部添加字段。

黑客攻击:扩展类型的字段出现在顶部。即添加到扩展类型的字段添加在顶部。因此,您可以有三种类型的类型:顶部“虚拟”级别(用于顶部字段),中间级别包含要继承的字段,底部级别(用于底部字段)。导入此模式的模式将定义底层 - redefine顶层。这样您就可以在顶部和底部添加字段。 这个 问题是它还将重新定义扩展它的所有其他类型的顶级...所以这些额外的字段将遍布整个地方,这可能不是你想要的。

其他替代方案包括:避免使用扩展机制,而是使用substitution groups(但这些需要不同的元素名称);或者在元素中创建自己的多态(<choice>)和继承(<group ref="..."/>在顶部和底部) - 但请注意,每个选项必须独立开始或违反UPA规则(因为他们赢了'可以通过属性区分,例如xsi:type)。

编辑我看到另一个答案已经涵盖了这一点我已经输入了所有这些,还有一些额外的建议,所以我不妨保留它。

答案 1 :(得分:2)

<强>更新

以下是XML Schema规范中的相关声明:

2.2.1.3复杂类型定义http://www.w3.org/TR/xmlschema-1/#Complex_Type_Definition

  

通过增加另一个来扩展另一个的复杂类型   内容模型粒子在另一个定义的内容的末尾   模型,或通过附加属性声明,或两者兼而有之。


要对XML模式有效,扩展字段需要在继承字段之后发生。在解组时,元素可以是任何顺序。如果您从POJO开始,则可以标记父类@XmlTransient,以便将父属性视为子项的一部分,以便它们可以包含在子项propOrder中。

了解更多信息