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

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

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

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

模式应该为类型层次结构建模(Book和Journal是Publication的子类).当然,这也应该
是生成的Java类的情况.

我尝试了以下approches,这些都有一个重大问题:

1.)建模目录包含xsd:所有可能的子类型的选择.

<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>
...

这里的问题是我必须在选择元素中提到所有可能的子类型,这在实际应用中可能很多.
一个小问题是,尽管Catalog属性具有正确的类型List< Publication>它有一本丑陋的名字书和杂志.
由于冗余架构定义,不是一个选项!

2.)建模目录包含父类的xsd:序列

<xsd:complexType name="Catalogue">
    <xsd:choice maxOccurs="unbounded">
        <xsd:element ref="Publication" maxOccurs="unbounded"/>
    </xsd:choice>
</xsd:complexType>

这仅适用于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>
...

这里,代码生成是个问题,因为Catalog的内部元素被映射到List< JaxbElement<?扩展出版物>>而不是
列表与LT;公开> .因此,这也不是一种选择.

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

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

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

最佳答案 我建议使用类似于你的第一个选项,因为我从未见过这个问题的清洁解决方案.

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;
点赞