我有以下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按预期工作?
http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#Complex_Type_Definition
一个扩展另一个定义的复杂类型通过在其他定义的内容模型的末尾具有额外的内容模型粒子,或者通过具有额外的属性声明,或者两者兼而有之。
- 注意:这个规范只允许追加,不允许其他类型的扩展。此决策简化了将实例从派生类型转换为基类型所需的应用程序处理。未来的版本可能允许更多类型的扩展,需要更复杂的转换才能实现强制转换
因此,在扩展类型时,字段只添加在底部。
破解:扩展类型的字段出现在顶部。即添加到扩展类型的字段被添加在顶部。因此,你可以有三个级别的类型:;伪";级别(用于顶部字段)、包含要继承的字段的中间级别和底部级别(用于底部字段)。导入它的模式将定义底层,redefine
定义顶层。这将使您能够在顶部和底部添加字段。big的问题是,它还将为所有其他扩展它的类型重新定义顶级……所以这些额外的字段将到处出现,这可能不是你想要的。
其他替代方案包括:避免扩展机制,而是使用substitution groups
(但这些需要不同的元素名称);或者在元素中创建自己的多态性(<choice>
)和继承性(顶部和底部的<group ref="..."/>
),但请注意,每个选择都必须以唯一的方式开始,否则就会违反UPA规则(因为它们不会像xsi:type
那样通过属性来区分)。
编辑我看到另一个答案已经涵盖了这一点,我已经键入了所有这些,还有一些额外的建议,所以我最好保留它。
更新
以下是XML模式规范中的相关声明:
2.2.1.3复杂类型定义(http://www.w3.org/TR/xmlschema-1/#Complex_Type_Definition)
一个扩展另一个的复杂类型通过具有额外的另一个定义内容末尾的内容模型粒子模型,或者通过具有额外的属性声明,或者两者兼而有之。
要对XML模式有效,扩展字段需要出现在继承字段之后。元素在解组时可以按任何顺序排列。如果从POJO开始,则可以标记父类@XmlTransient
,以便将父类属性视为子类的一部分,以便将它们包含在子类的propOrder
中。
有关更多信息
- http://blog.bdoughan.com/2012/08/jaxbs-xmltransient-and-property-order.html