有很多类似的问题集中在一个方面进行优化,但每个解决方案都有一个丑陋的缺点。
假设我想开发一个XML模式(XSD),它允许以下文档并希望使用XJC生成类:
<Catalogue>
<Book>...</Book>
<Journal>...</Journal>
<Book>...</Book>
...
</Catalogue>
模式应该为类型层次结构建模(Book
和Journal
是Publication
的子类。当然,这也应该
是生成的Java类的情况。
我尝试了以下具有重大问题的方法:
1。)建模目录包含xsd:choice
所有可能的子类型。
<xsd:complexType name="Catalogue">
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="Book" />
<xsd:element ref="Magazine" />
</xsd:choice>
</xsd:complexType>
<xsd:element name="Publication" abstract="true" type="Publication" />
<xsd:element name="Book" type="Book"/>
<xsd:element name="Magazine" type="Magazine"/>
<xsd:complexType name="Publication">
<xsd:sequence></xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Book">
<xsd:complexContent>
<xsd:extension base="Publication">
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
...
这里的问题是我必须提到choice
元素中所有可能的子类型,这些子类型在实际应用程序中可能很多。
一个小问题是,虽然Catalogue
属性的类型List<Publication>
正确,但它的名称有bookAndMagazine
。
由于冗余架构定义,不是一个选项!
2。)建模目录包含父类的xsd:sequence
<xsd:complexType name="Catalogue">
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="Publication" maxOccurs="unbounded"/>
</xsd:choice>
</xsd:complexType>
仅当XML文档的表达方式与<Publication xsi:type="Book"...>
相同时,这才有效。因此,不是一个选择!
3。)使用这里提到的substitutionGroup http://www.xfront.com/ElementHierarchy.html
<xsd:complexType name="Catalogue">
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="Publication" maxOccurs="unbounded"/>
</xsd:choice>
</xsd:complexType>
<xsd:element name="Publication" abstract="true" type="Publication" />
<xsd:element name="Book" type="Book" substitutionGroup="Publication"/>
<xsd:element name="Magazine" type="Magazine" substitutionGroup="Publication"/>
<xsd:complexType name="Publication">
<xsd:sequence></xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Book">
<xsd:complexContent>
<xsd:extension base="Publication">
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
...
这里,代码生成是个问题,因为Catalogue
的内部元素映射到List<JaxbElement<? extends Publication>>
而不是List<Publication>
{{1}}。因此,这也不是一种选择。
如何将我的所有目标聚集在一起?:
如果没有符合所有这些目标的解决方案,您更喜欢哪一个?
答案 0 :(得分:3)
我建议使用与您的第一个选项类似的东西,因为我从未见过这个问题的清洁解决方案。
<强> XSD 强>
<xs:element name="Publications" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Magazine" type="magazine"/>
<xs:element name="Book" type="book"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="magazine">
<xs:complexContent>
<xs:extension base="publication">
<xs:sequence>
<xs:element name="issueName" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="publication">
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="book">
<xs:complexContent>
<xs:extension base="publication">
<xs:sequence>
<xs:element name="title" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<强> JAVA 强> 这是我用来生成上述XSD的Java代码。
@XmlElements({
@XmlElement(name="Magazine", type=Magazine.class),
@XmlElement(name="Book", type=Book.class)
})
@XmlElementWrapper(name="Publications")
public List<Publication> publications;
答案 1 :(得分:0)
如果您可以从代码(而不是XSD)开始并且使用MOXY就可以,请查看此blog post。它使用方法3而不使用JAXBElement包装器。我喜欢从XSD开始这样做的方法,但我还没有找到它。