2011-12-19 102 views
3

我不得不馬歇爾我的根XML對象的片段JAXB片段:具有不同的命名空間

Header header = ebicsNoPubKeyDigestsRequest.getHeader(); 
JAXBElement<org.ebics.h003.EbicsNoPubKeyDigestsRequest.Header> jaxbElement = 
    new JAXBElement<EbicsNoPubKeyDigestsRequest.Header>(
    new QName("header"), EbicsNoPubKeyDigestsRequest.Header.class, header); 
byte[] headerXml = JAXBHelper.marshall(jaxbElement, true); 

但是當我馬歇爾ebicsNoPubKeyDigestsRequest的命名空間是不相同的(在報頭片段我有:xmlns:ns4="http://www.ebics.org/H003"但在ebicsNoPubKeyDigestsRequest我有xmlns="http://www.ebics.org/H003"

如果我馬歇爾直接標題對象,而無需使用的JAXBElement,我有一個No @XmlRootElement錯誤

怎樣纔可以有相同的N amespaces? 注:我已經使用了一個NamespacePrefixMapper類:

marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new NamespacePrefixMapper() { 

    @Override 
    public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) { 
    if (namespaceUri.equals("http://www.ebics.org/H003")) { 
     return ""; 
    } else if (namespaceUri.equals("http://www.w3.org/2000/09/xmldsig#")) { 
     return "ds"; 
    } else if (namespaceUri.equals("http://www.ebics.org/S001")) { 
     return "ns1"; 
    } else if (namespaceUri.equals("http://www.w3.org/2001/XMLSchema-instance")) { 
     return "ns2"; 
    } 
    return ""; 
    } 
}); 

編輯:這裏的不同package-info.java:

@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.ebics.org/H003", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) 
package org.ebics.h003; 

@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.ebics.org/S001", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) 
package org.ebics.s001; 

@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.w3.org/2000/09/xmldsig#", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) 
package org.w3._2000._09.xmldsig_; 
+0

我假定包org.ebics.h003和其中的所有類都是由XJC生成的。如果是,那麼如果包內有一個名爲'package-info.java'的文件,你可以將它和(* top part *,顯示'@ XmlRootElement','@ XmlType'等註釋)你的'EbicsNoPubKeyDigestsRequest'和'EbicsNoPubKeyDigestsRequest.Header'類? – 2011-12-19 11:54:39

+0

@ javax.xml.bind.annotation.XmlSchema(namespace =「http://www.ebics.org/H003」,elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) package org.ebics.h003; => H003 @ javax.xml.bind.annotation.XmlSchema(命名空間= 「http://www.ebics.org/S001」,將elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) 包有機ebics.s001; => s001 @ javax.xml.bind.annotation.XmlSchema(namespace =「http://www.w3.org/2000/09/xmldsig#」,elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED ) package org.w3._2000._09.xmldsig_; => w3 – Baptiste 2011-12-19 12:22:20

+0

您可以發佈此更新以提高可讀性。請在下次使用編輯功能。此外,您的課堂上的註釋也是有用的。 – 2011-12-19 12:32:41

回答

4

沒有看到實際的XML架構,文件和JAXB生成的類(和他們的註釋)我只能建議你嘗試修改下面的例子到你的場景中。

假設你有一個JAXB生成的類像下面這樣:

@XmlRootElement(namespace = "http://test.com") 
@XmlType(namespace = "http://test.com") 
public static final class Test { 

    public String data; 

    public Test() {} 
} 

這是在包test且有package-info.java文件中這樣說:

@XmlSchema(elementFormDefault = XmlNsForm.QUALIFIED, 
      xmlns = @XmlNs(prefix = "", namespaceURI = "http://test.com")) 
package test; 

import javax.xml.bind.annotation.XmlNs; 
import javax.xml.bind.annotation.XmlNsForm; 
import javax.xml.bind.annotation.XmlSchema; 

下面的代碼:

Test test = new Test(); 
test.data = "Hello, World!"; 

JAXBContext context = JAXBContext.newInstance(Test.class); 
Marshaller marshaller = context.createMarshaller(); 
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); 
marshaller.marshal(test, System.out); 

將打印此頁:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<test xmlns="http://test.com"> 
    <data>Hello, World!</data> 
</test> 

您完全可能完全忽略了NamespacePrefixMapper實現。

玩忽略任何註釋中特定的namespace元素,看看輸出如何變化。

Blaise Doughan(一個Java XML綁定專家,可能潛伏在某處附近)公佈關於在他的博客這個問題的一些信息,請參閱his post一些更深入的瞭解。


基於Baptiste在聊天中提供的輸入,我提出了以下解決方案(我認爲這是最無痛的)。

通常用XJC編譯模式文件($ xjc .)。這將爲每個生成的包生成package-java.info文件。我假設這個模式並沒有每天更新,所以你可以安全地對package-info.java文件進行修改(即使這些文件中會有一些行註釋,告訴你不要這樣做 - 無論如何)。如果架構得到更新並且必須重新編譯,則運行帶有-npa開關的XJC,它告訴它不要自動生成這些package-info.java文件,因此(理想情況下)您無法覆蓋手動創建的文件(如果使用版本控制你可以/應該將這些(手工製作的)文件包含在存儲庫中)。

根據提供的模式文件生成四個軟件包,所以我將包含我的版本的修改後的package-info.java文件。

@XmlSchema(namespace = "http://www.ebics.org/H000", 
      xmlns = @XmlNs(prefix = "ns1", 
          namespaceURI = "http://www.ebics.org/H000")) 
package org.ebics.h000; 

@XmlSchema(namespace = "http://www.ebics.org/H003", 
      xmlns = @XmlNs(prefix = "", 
          namespaceURI = "http://www.ebics.org/H003")) 
package org.ebics.h003; 

@XmlSchema(namespace = "http://www.ebics.org/S001", 
      xmlns = @XmlNs(prefix = "ns3", 
          namespaceURI = "http://www.ebics.org/S001")) 
package org.ebics.s001; 

@XmlSchema(namespace = "http://www.w3.org/2000/09/xmldsig#", 
      xmlns = @XmlNs(prefix = "ns2", 
          namespaceURI = "http://www.w3.org/2000/09/xmldsig#")) 
package org.w3._2000._09.xmldsig; 

在這之後您創建JAXBContext這樣的:

JAXBContext context = 
    JAXBContext.newInstance("org.ebics.h003:org.ebics.s001:org.w3._2000._09.xmldsig"); 

(我注意到,你不實際使用使用h000封裝所以我從包名稱中省略它如果包含,則編組的XML根標籤可能會包含它的名稱空間和前綴映射,即使它很難被使用。)

在此之後,您將解析您的輸入XML和d o無論你想在記憶中的對象。現在

Unmarshaller unmarshaller = context.createUnmarshaller(); 

EbicsNoPubKeyDigestsRequest ebicsNoPubKeyDigestsRequest = 
    (EbicsNoPubKeyDigestsRequest) unmarshaller.unmarshal(stream); 

,如果你想馬歇爾只有header標籤被嵌套在該ebicsNoPubKeyDigestsRequest,你必須把它包裝一個JAXBElement<...>裏面,因爲header的類型EbicsNoPubKeyDigestsRequest.Header不與@XmlRootElement註解。你有兩個(在這個的情況下一個)的方式來創建這個元素。

爲相應的包創建一個ObjectFactory實例並使用它的JAXBElement<T> createT(T t)函數。其中包含輸入到JAXBElement<...>。不幸的是,對於header字段的類型(給定您的模式文件),XJC不會生成這樣的方法,因此您必須手動完成。

基本上你已經差不多完成了它,但是當創建JAXBElement<...>而不是傳遞new QName("header")時,必須創建一個完全限定名稱,這意味着該名稱空間也已指定。只傳遞XML標籤的名稱是不夠的,因爲JAXB不會以這種方式知道這個特定的header標籤是"http://www.ebics.org/H003"名稱空間的一部分。所以,像這樣做:

QName qualifiedName = new QName("http://www.ebics.org/H003", "header"); 
JAXBElement<EbicsNoPubKeyDigestsRequest.Header> header = 
    new JAXBElement<EbicsNoPubKeyDigestsRequest.Header>(
     qualifiedName, EbicsNoPubKeyDigestsRequest.Header.class, header); 

如果只改變QName實例解決您的問題,我沒有測試,但也許會的。不過,我認爲它不會和你必須手動管理你的前綴,以獲得不錯的一致的結果。

+0

謝謝,但我不能從這個xsd修改生成的類: http://www.ebics.org/fileadmin/unsecured/specification/schema_current/ebics_xml_schema-12-07-2011.zip,但也許我可以用xjb文件更改註釋? – Baptiste 2011-12-19 12:34:10

+0

@Baptiste我只要求你發佈你的類,看他們是否有任何註釋(是的,類文件生成coulbe通過綁定配置操縱)。我會爲自己生成類,看看我能做什麼。這對我可以告訴我們很有幫助,您是如何設法使用XJC編譯這些模式文件的。 – 2011-12-19 12:36:32

+0

非常感謝,我只是從jaxb開始,我什麼都不明白 – Baptiste 2011-12-19 12:39:31

相關問題