2012-04-12 72 views
4

有很多類似的問題集中在一個方面進行優化,但每個解決方案都有一個醜陋的缺點。最佳JAXB XJC代碼生成和最佳XML模式的繼承

假設我想開發一個XML模式(XSD),它允許下列文件,想用生成的類XJC:

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

架構應該模擬類型層次結構(BookJournalPublication子)。當然,對於生成的Java類,這也應該是 。

我嘗試以下approches其中都有一個主要問題:

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:complexType name="Catalogue"> 
    <xsd:choice maxOccurs="unbounded"> 
     <xsd:element ref="Publication" maxOccurs="unbounded"/> 
    </xsd:choice> 
</xsd:complexType> 

這不只是工作的xsd:sequence如果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>。因此,這也不是一種選擇。

如何把我所有的目標一起?:

  • 規範的,非冗餘的架構該款車型繼承(如2)3)
  • 簡單幹淨從這個模式生成的Java類以及哪些模型繼承(如在2)部分在1)
  • 清潔XML文檔(不像在2))標準JAXB和最好不要太大約束力元數據的
  • 使用

如果沒有解決,所有這些目標,一會你喜歡它匹配?

+0

你能詳細說明爲什麼選項3)不好,爲什麼'List >'不適合你?它實際上是優雅的:不僅你有一個JAXB對象,而且JAXBElement <>包裝器爲你提供完全限定的元素名稱。 xml info – 2012-04-13 05:23:30

+0

1.)我想在其他應用程序部分使用生成的類層次結構作爲域模型的一種,我不想讓它們依賴於JaxB類型。 2)我正在應用XJC插件jaxb-visitor,它爲訪問者模式豐富了生成的類。 JaxbElement屬性打破了遍歷文檔樹的自然方式。 – rainer198 2012-04-13 07:40:35

+0

我也覺得選項3非常難看。我更喜歡保持與pojo的接近,並且從來不需要JAXBElement在這種情況下提供的東西,因爲它全部是一個模式。 – 2012-05-12 13:28:06

回答

2

我會建議使用類似於你的第一個選項的東西,因爲我從來沒有見過這個問題的更清潔的解決方案。

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; 
+0

謝謝。我其實也決定1)。但是,在您的示例中,您正在實現包括一些註釋的Java類型並從中生成XSD。我正試圖扭轉局面。開發XSD並生成代碼。有趣的是,看到Generic XSD等於解決方案1) – rainer198 2012-04-13 07:49:25

+0

我建議你考慮的一件事是,與選項1,你堅持這兩個子類型,將不得不加速XSD以支持一種新的類型未來。有一些方法可以緩解(爲了向前兼容),例如允許未知類型: 2012-04-14 01:08:58

0

如果從代碼中(而不是XSD)開始,並使用MOXY看看這個blog post確定。它使用沒有JAXBElement包裝的方法3。我很想用XSD開始做這件事,但我還沒有找到它。