5

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

假设我想开发一个 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.)使用这里提到的替代组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>. 因此,这也不是一个选择。

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

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

如果没有与所有这些目标相匹配的解决方案,您更喜欢哪一个?

4

2 回答 2

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;
于 2012-04-12T18:01:03.850 回答
0

如果您可以从代码(而不是 XSD)开始,并且可以使用 MOXY,请查看此博客文章。它使用没有 JAXBElement 包装器的方法 3。我希望有一种从 XSD 开始的方法,但我还没有找到它。

于 2013-09-24T17:23:48.037 回答