2012-09-14 57 views
4

我有一個子樹,我想附加在一個對象上,並讓JAXB將所有東西都當作一棵樹(以及適當的標籤)。但是目前,子樹的根標籤被替換爲另一個對象的標籤JAXB:如何追加子樹到一個對象並創建一棵完整的樹

不幸的是,我不允許在這裏發佈原始代碼,所以我在測試代碼中再現了我的問題(所以請耐心等待如果你發現這個愚蠢的)。

的想法是,我想輸出的結構如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<ns2:Root xmlns:ns2="urn:my:foo:bar:1.0" xmlns:ns3="urn:other:foo:bar:1.1"> 
    <Content> 
     <Header> 
      <ns3:Leaf/> 
     </Header> 
    </Content> 
</ns2:Root> 

,但目前,我得到的是這樣的:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<ns2:Root xmlns:ns2="urn:my:foo:bar:1.0" xmlns:ns3="urn:other:foo:bar:1.1"> 
    <Content> 
     <Header/> 
    </Content> 
</ns2:Root> 

我有兩個XSD的生成所有必要的類,所以我可以在那邊(但是因爲這些類是生成的,我不能修改它們)。

這裏是一個示例代碼,產生第二XML(錯誤的):

package foo.bar; 

import java.io.OutputStream; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 
import javax.xml.bind.Marshaller; 
import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.XmlType; 
import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.parsers.ParserConfigurationException; 

import org.w3c.dom.Document; 
import org.w3c.dom.Node; 

public class Test { 

    private JAXBContext context; 

    public Test() throws JAXBException { 
     context = JAXBContext.newInstance(RootElement.class, LeafElement.class); 
    } 

    @XmlRootElement(name = "Root", namespace = "urn:my:foo:bar:1.0") 
    @XmlAccessorType(XmlAccessType.FIELD) 
    @XmlType(name = "Root", propOrder = { "content" }) 
    public static class RootElement { 
     @XmlElement(name = "Content") 
     protected ContentElement content; 

     public ContentElement getContent() { 
      return content; 
     } 

     public void setContent(ContentElement content) { 
      this.content = content; 
     } 
    } 

    @XmlRootElement 
    @XmlAccessorType(XmlAccessType.FIELD) 
    @XmlType(name = "Content", propOrder = { "dummy" }) 
    public static class ContentElement { 
     @XmlElement(name = "Header") 
     protected Object dummy; 

     public Object getDummy() { 
      return dummy; 
     } 

     public void setDummy(Object dummy) { 
      this.dummy = dummy; 
     } 
    } 

    @XmlRootElement(name = "Leaf", namespace = "urn:other:foo:bar:1.1") 
    @XmlAccessorType(XmlAccessType.FIELD) 
    @XmlType(name = "Leaf") 
    public static class LeafElement { 

    } 

    public Node marshal(Object obj) throws JAXBException { 
     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
     dbf.setNamespaceAware(true); 
     Document doc = null; 
     try { 
      DocumentBuilder db = dbf.newDocumentBuilder(); 
      doc = db.newDocument(); 
     } catch (ParserConfigurationException ex) { 
      throw new JAXBException(ex); 
     } 

     Marshaller m = context.createMarshaller(); 
     m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); 
     m.marshal(obj, doc); 
     return doc.getDocumentElement(); 
    } 

    public void marshal(Object obj, OutputStream stream) throws JAXBException { 
     Marshaller m = context.createMarshaller(); 
     m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); 
     m.marshal(obj, stream); 
    } 

    public void test() throws JAXBException { 
     RootElement root = new RootElement(); 
     ContentElement content = new ContentElement(); 
     root.setContent(content); 
     LeafElement leaf = new LeafElement(); 
     content.setDummy(marshal(leaf)); 
     marshal(root, System.out); 
    } 

    public static void main(String[] args) throws JAXBException { 
     new Test().test(); 
    } 

} 

在該代碼中你會發現3 「marshallable」 類:

  1. RootElement
  2. ContentElement
  3. LeafElement

前兩個類來自一個XSD(具有給定名稱空間),最後一個來自另一個XSD(具有另一個名稱空間),如示例代碼中所示。

到目前爲止,我發現解決這個問題的唯一方法就是創建一個額外的類,它將在ContentElement上設置爲dummy,並且本身會保存LeafElement,以便JAXB創建適當的中間節點。但是我發現這個解決方案非常難看,不能真正維護,並且希望JAXB有辦法處理這種情況。

如果您需要更多信息,或者您需要我重新制定我的問題,請不要猶豫。我很難用簡單的話來解釋我的問題。

約束如下:

  • 我不能修改rootElement的,ContentElement的也不LeafElement
  • 我無法用別的東西比JAXB

回答

1

如果你不能改變任何元素類,則必須創建一個持有者對象的葉子。

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public static class LeafElementHolder { 
    @XmlAnyElement 
    private Object leaf; 

    public Object getLeaf() { 
     return leaf; 
    } 

    public void setLeaf(Object leaf) { 
     this.leaf = leaf; 
    } 
} 

這個類添加到關聯

public Test() throws JAXBException { 
    context = JAXBContext.newInstance(RootElement.class, LeafElement.class, LeafElementHolder.class); 
} 

,並在測試中使用()方法

LeafElement leaf = new LeafElement(); 
    LeafElementHolder holder = new LeafElementHolder(); 
    holder.setLeaf(leaf); 
    content.setDummy(marshal(holder)); 

您在XML 4個元素,所以你必須在Java中4類。

ns2:Root 
    ns2:Content 
    ns2:Header 
     ns3:Leaf