2015-01-21 171 views
1

我想指定一個XSD類型的實現類。 這裏有一個小例子,模式:Jaxb implClass規範爲根元素忽略

<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="rd.test" 
     xmlns:tns="rd.test" elementFormDefault="qualified" 
     xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"> 
    <complexType name="DocumentType"> 
    <annotation> 
     <appinfo> 
     <jaxb:class implClass="rd.DocumentEx" /> 
     </appinfo> 
    </annotation> 
    <sequence> 
     <element name="element" type="tns:DocumentType" /> 
    </sequence> 
    <attribute name="title" type="string" /> 
    </complexType> 
<element name="document" type="tns:DocumentType"/> 
</schema> 

我使用從Java JDK(1.7)標準的XJC工具,現在的(但我也有行家-JAXB2-插件測試,相同的結果)。

對於短測試我用下面的XML文檔:

<?xml version='1.0' standalone='yes' ?> 
<document title="testDocument"> 
    <element title="testElement" /> 
</document> 

當我運行下面的測試程序,其結果爲頂級文檔元素(testDocument)和包含的子元件(不同testElement)。根的類型是「DocumentType」,即忽略指定的implClass-directive,而元素的類型是「DocumentEx」,這是預期的結果。 在生成的ObjectFactory適當的實例似乎是正確的,但它似乎沒有用於rootElement的:

public DocumentType createDocumentType() { 
    return new DocumentEx(); 
    } 

下面是測試程序:

InputStream inp=new FileInputStream(new File("test.xml")); 
JAXBContext jaxbContext = JAXBContext.newInstance("test.rd"); 
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); 

JAXBElement el = (JAXBElement)unmarshaller.unmarshal(inp); 
Object obj = el.getValue(); 
System.out.println("doc: " + obj); 
// result: "doc: [email protected]" 

DocumentType doc = (DocumentType)obj; 
Object obj2=doc.getElement(); 
System.out.println("obj2: " + obj2); 
// result: "obj2: [email protected]" 

我得到同樣的結果,如果我指定元素的implClass而不是complexType。

爲什麼根元素忽略implClass? 任何想法和提示都表示讚賞!


拓澄清我的意圖:

我不想引用現有的,JAXB註釋類,但有附加屬性使用自動生成的DocumentType級的基類extionsion和方法。對於後來的直接編組回到XML,我必須保持與XSD-Type的關係。因此,implClass指令實際上是適用於(據我所知)的方法來測試類型類的jaxb代。

它對於內部元素(標籤'testElement'內的文檔標籤'元素')完美工作!不幸的是,unmarshaller沒有使用implClass指定的類來正確地實例化根元素。在上面的程序摘錄中看到結果 - 評論(doc vs. obj2)。

+0

可能重複(http://stackoverflow.com/questions/26439184/why-is-the-objectfactory-not-used-during-unmarshalling) – lexicore 2015-01-21 10:48:16

+0

不幸它不是。它只是回答了這個問題,爲什麼ObjectFactory似乎不被使用,但它不回答(至少對我來說不),爲什麼implClass對另一個元素內的元素工作正常,但對於rootElement不是? – raindrop 2015-01-21 11:47:57

+0

感謝@lexicore的提示上面提到的解決方法是指定一個factoryClass和-method乍一看的確能繞過這個問題。不幸的是,這是不適用的,因爲適當的DocumentType-Class將被自動生成,因此如果需要手動修改則不好。不過,implClass對於文檔內部相同類型的元素沒有使用factoryClass的手動指定是完美的。這就是我不明白的地方?! – raindrop 2015-01-21 12:45:58

回答

0

對於你正在尋找我的行爲相信要指定ref,而不是impl

<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="rd.test" 
     xmlns:tns="rd.test" elementFormDefault="qualified" 
     xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"> 
    <complexType name="DocumentType"> 
     <annotation> 
      <appinfo> 
       <jaxb:class ref="rd.DocumentEx" /> 
      </appinfo> 
     </annotation> 
     <sequence> 
      <element name="element" type="tns:DocumentType" /> 
     </sequence> 
     <attribute name="title" type="string" /> 
    </complexType> 
    <element name="document" type="tns:DocumentType"/> 
</schema> 

這告訴JAXB使用rd.DocumentEx類的DocumentType複雜類型。現在DocumentType類沒有創建,並在ObjectFactorycreateDocument方法是這樣的:

@XmlElementDecl(namespace = "rd.test", name = "document") 
public JAXBElement<DocumentEx> createDocument(DocumentEx value) { 
    return new JAXBElement<DocumentEx>(_Document_QNAME, DocumentEx.class, null, value); 
} 

從JAXB 2.2規範的7.7.1:

•implClass如果指定,是 className的實現類的名稱,並且必須包含完整的軟件包名稱。請注意,這個 自定義僅影響className的工廠 方法的返回值。當使用new創建模式派生的Value類的 實例時,將忽略此自定義。

•ref(如果指定)是 在模式編譯器之外提供的值類的名稱。 此自定義會導致架構編譯器引用此外部類 類,而不是生成定義。它必須包含 完整的軟件包名稱。此屬性與 className屬性和implClass屬性互斥。

的[爲什麼解組過程中不使用的ObjectFactory?]
+0

謝謝你的回答!不幸的是你誤解了我的意圖(我看到,我沒有說清楚)。正如您指出的那樣,使用'ref'指令期望我的類DocumentEx被註釋爲JAXB,但這不是實例,因爲它只是自動生成的DocumentType-Class的特化。根據你的規範摘錄,在我看來,也許rootElement實例化的方式不同(使用'new'忽略值類)比內部元素,但如果這是正確的,爲什麼?! (編輯的問題更好地指出我的意圖) – raindrop 2015-01-21 17:06:10