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

时间:2012-04-12 14:43:44

标签: inheritance xsd jaxb code-generation xjc

有很多类似的问题集中在一个方面进行优化,但每个解决方案都有一个丑陋的缺点。

假设我想开发一个XML模式(XSD),它允许以下文档并希望使用XJC生成类:

<Catalogue>
    <Book>...</Book>
    <Journal>...</Journal>
    <Book>...</Book>
    ...
</Catalogue>

模式应该为类型层次结构建模(BookJournalPublication的子类。当然,这也应该 是生成的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}}。因此,这也不是一种选择。

如何将我的所有目标聚集在一起?:

  • 规范继承的规范,非冗余模式(例如 2。) 3。)
  • 从这个模式生成的简单而干净的Java类以及哪些模型继承模型(如 2。),部分在 1中。)
  • 清理XML文档(不像 2。)
  • 标准JAXB的使用,并且最好没有多少绑定元数据

如果没有符合所有这些目标的解决方案,您更喜欢哪一个?

2 个答案:

答案 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开始这样做的方法,但我还没有找到它。