我有一个返回XML对象集的API,这些对象保证可以由抽象类表示,但是它们不能作为列表直接访问,因为它们采用以下形式:
<Response Timestamp="2019-02-06T13:16:32">
<TypeA [xml attributes]...>
...
</TypeA>
<TypeB ...>
...
</TypeB>
... (Different repeating elements)
</Response>
由于公司的做法,我将使用XSD编写此Feed的模型,由JaxB解析以生成源文件。但是,如果没有单独声明类型作为集合的可能元素(由于显而易见的原因我不想这样做),我不知道如何处理这个并将响应的子元素作为单个集合。
XSD的响应。
<xs:complexType name="Response">
<xs:sequence>
<xs:element name="Types" type="model:AbstractType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
示例元素类型
public class TypeA extends AbstractType
{
//Generated source
}
如何在XSD中指定任何扩展AbstractType的TypeX对象应该从响应中进入Types集合?
很高兴提供任何必要的进一步信息,只要不是我不允许分享的东西。
看到this相关问题然而它接受了任何元素,并且限制是基于名称,而为此我理想地想要验证收集的元素是有效的TypeX对象。
假设您已在XSD中将每个TypeX定义为AbstractType扩展:
<xsd:complexType name="TypeX">
<xsd:complexContent>
<xsd:extension base="AbstractType">
...
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
然后你可以这样做:
1)XSD选择,如果你真的想为每个TypeX使用不同的XML元素名称(不推荐,因为每当你添加一个新的AbstractType子类型时都需要修改Response类型):
<xs:complexType name="Response">
<xs:choice maxOccurs="unbounded">
<xs:element name="typeA" type="model:TypeA" />
<xs:element name="typeB" type="model:TypeB" />
</xs:sequence>
</xs:complexType>
2)XML多态(接近你的建议),更通用虽然改变了XML形式:
<xs:complexType name="Response">
<xs:sequence>
<xs:element name="something" type="model:AbstractType" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
(根据AbstractType实际表示的内容,将'something'替换为一些有意义的名称。)
xml看起来像这样:
<Response Timestamp="2019-02-06T13:16:32" xmlns="...">
<something xsi:type="TypeA" [xml attributes]...>
...
</something>
<something xsi:type="TypeB" ...>
...
</something>
... (Different repeating elements)
</Response>
在这两种情况下,我建议您使用JAXB RI extension for simpler/better binding mode(第3.1.6节)或等效扩展,它简化了生成的代码,并在必要时将生成的字段转换为复数形式。
然后在Response类中生成的代码(注意复数形式):List<AbstractType> somethings;
。