2012-12-12 25 views
1

對於給定的類結構(跳過註釋等):JAXB編組與XSD生成模式 - 「去同步」它

class A { 
public B getObjectB {} 
} 

class B { 
public String getHello { return " world"; } 
} 

我有產生正確的XSD和XML輸出沒有問題:

<A> 
<B> 
    <hello>world</hello> 
</B> 
</A> 

事情是,我需要打破它一點:首先,XSD應該保持原樣 - 滿。但是,雖然編組A,我需要得到這樣的東西:

<A> 
someStringForA 
</A> 

(所以B呈現爲一些計算字符串)。同時,在編組B時(作爲根),我仍然需要獲得「正常」輸出。

我嘗試使用XmlAdapters,但使用@XmlJavaTypeAdapter也更改了XSD。通過Marshaller.setAdapter(...)顯然設置適配器(http://stackoverflow.com/questions/6110757/jaxb-xml-adapters-work-via-annotations-but-not-via-setadapter/6112149#6112149)將不行。

一些類型的解決方案是,如果有可能爲「關閉」的@XmlJavaTypeAdapter(由JUnit中,一些開關XSD生成「手動」,甚至黑客是允許的)

感謝您的幫助!

回答

1

注:我是E clipseLink JAXB (MOXy)的領導者和JAXB (JSR-222)專家組的成員。

備用映射 - oxm.xml

如果您正在使用莫西爲您的JAXB提供者,你可以使用外部映射文件,以提供您的域模型的替代映射(見:http://blog.bdoughan.com/2010/12/extending-jaxb-representing-annotations.html)。

<?xml version="1.0"?> 
<xml-bindings 
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" 
    package-name="forum13843624"> 
    <java-types> 
     <java-type name="A"> 
      <java-attributes> 
       <xml-value java-attribute="objectB"/> 
      </java-attributes> 
     </java-type> 
     <java-type name="B"> 
      <java-attributes> 
       <xml-value java-attribute="hello"/> 
      </java-attributes> 
     </java-type> 
    </java-types> 
</xml-bindings> 

Java模型

import javax.xml.bind.annotation.*; 

@XmlRootElement(name="A") 
class A { 

    private B b; 

    @XmlElement(name="B") 
    public B getObjectB() { 
     return b; 
    } 
    public void setObjectB(B b) { 
     this.b = b; 
    } 

} 

import javax.xml.bind.annotation.XmlElement; 

class B { 

    @XmlElement 
    public String getHello() { 
     return " world"; 
    } 

} 

jaxb.pr operties

要指定莫西爲您的JAXB提供者,你需要包括在同一個包命名jaxb.properties與以下條目您的域模型文件(見:http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html)。

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

演示代碼

import java.util.*; 
import javax.xml.bind.*; 
import org.eclipse.persistence.jaxb.JAXBContextProperties; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     B b = new B(); 
     A a = new A(); 
     a.setObjectB(b); 

     JAXBContext jc = JAXBContext.newInstance(A.class); 
     marshal(jc, a); 

     Map<String, Object> properties = new HashMap<String, Object>(); 
     properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "forum13843624/oxm.xml"); 
     JAXBContext jc2 = JAXBContext.newInstance(new Class[] {A.class}, properties); 
     marshal(jc2, a); 
    } 

    private static void marshal(JAXBContext jc, A a) throws Exception { 
     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(a, System.out); 
    } 

} 

輸出

下面是從運行演示代碼的輸出。注意同一個對象圖是如何編組的兩種不同的方式。

<?xml version="1.0" encoding="UTF-8"?> 
<A> 
    <B> 
     <hello> world</hello> 
    </B> 
</A> 
<?xml version="1.0" encoding="UTF-8"?> 
<A> world</A> 
+0

謝謝布萊斯爲你的出色答案 - 我希望有人支付你這個努力;)我看到你以前的答案和帖子,並正在考慮切換到MOXY,但希望它不是必要的.. 。我會檢查後果 – Tomasz

+0

@Tomasz - 我不確定我的使用情況是否完全正確。你真的想把A編組成多個XML表示形式嗎?就像我在回答中一樣? –

+0

是的。或者更確切地說 - 我需要將它的一些子元素(B)組織到一些字符串(實際上是URL)。同時,在將B編組爲根時,不應將其轉換爲該字符串(URL) - 它應該是「正常」的XML輸出(除非有一些嵌套的C,並且配置爲與B類似)。它的所有關於「邊緣包括」,如果你想知道原因;) – Tomasz