rai*_*198 5 inheritance xsd code-generation jaxb xjc
有很多类似的问题集中在一个方面进行优化,但是每个解决方案都有一个丑陋的缺点。
假设我想开发一个XML模式(XSD),该模式允许以下文档,并希望使用XJC生成类:
<Catalogue>
<Book>...</Book>
<Journal>...</Journal>
<Book>...</Book>
...
</Catalogue>
Run Code Online (Sandbox Code Playgroud)
模式应为类型层次结构建模(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>
...
Run Code Online (Sandbox Code Playgroud)
这里的问题是,我必须提到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>
Run Code Online (Sandbox Code Playgroud)
仅当XML文档的格式为时,这才起作用<Publication xsi:type="Book"...>
。因此,别无选择!
3.)使用此处提到的替代组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>
...
Run Code Online (Sandbox Code Playgroud)
在这里,代码生成成为问题,因为的内部元素Catalogue
映射到List<JaxbElement<? extends Publication>>
而不是
List<Publication>
。因此,这也不是一个选择。
如何将我所有的目标结合在一起?:
如果没有符合所有这些目标的解决方案,您会选择哪一个?
我建议使用与您的第一个选项类似的方法,因为我从未见过更干净的解决方案来解决这个问题。
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>
Run Code Online (Sandbox Code Playgroud)
JAVA 这是我用来生成上述 XSD 的 Java 代码。
@XmlElements({
@XmlElement(name="Magazine", type=Magazine.class),
@XmlElement(name="Book", type=Book.class)
})
@XmlElementWrapper(name="Publications")
public List<Publication> publications;
Run Code Online (Sandbox Code Playgroud)