最佳的JAXB XJC代码生成和带有继承的最佳XML模式

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>。因此,这也不是一个选择。

如何将我所有的目标结合在一起?:

  • 规范的,非冗余的模式,用于建模继承(例如在2.中或在3.)中
  • 从此架构生成的简单干净的Java类,该类对继承进行建模(如2中所述),部分建模于1.)中
  • 干净的XML文档(不同于2)。
  • 使用标准JAXB,最好不要使用太多绑定元数据

如果没有符合所有这些目标的解决方案,您会选择哪一个?

Bra*_*sen 4

我建议使用与您的第一个选项类似的方法,因为我从未见过更干净的解决方案来解决这个问题。

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)