2013-02-05 77 views
4

我想將下列xml解組爲另一個如下定義的父對象。但它總是返回NULL。JAXB爲包含集合的嵌套xml返回null

傳入XML:對應於<contentFiles>

@XmlRootElement(name = "contentFiles") 
    public class RtSuperQuickMetadata 
    { 
     private List<RtSuperQuickMetadataItem> rtSuperQuickMetadataItems; 

     public RtSuperQuickMetadata() 
     { 
      rtSuperQuickMetadataItems = new ArrayList<RtSuperQuickMetadataItem>(); 
     } 

     public List<RtSuperQuickMetadataItem> getRtSuperQuickMetadataItems() 
     { 
      return rtSuperQuickMetadataItems; 
     } 

     public void setRtSuperQuickMetadataItems(
      List<RtSuperQuickMetadataItem> rtSuperQuickMetadataItems) 
     { 
      this.rtSuperQuickMetadataItems = rtSuperQuickMetadataItems; 
     } 

    } 

父類

<contentFiles> 
<contentFile> 
<contentFileName>cwb_reg_content_IB20C0F504A9A11E281E4C8BF76F4977C.pdf</contentFileName> 
<title><![CDATA[SEC No-Action Guidance Expanding the Definition of 「Ready Market」 for Certain Foreign Equity Securities]]></title> 
<sourcePublicationDate>20121219</sourcePublicationDate> 
<alternateDocNumbers> 
    <alternateDocNumber>12345-b</alternateDocNumber> 
</alternateDocNumbers> 
<citesAffected> 
    <cite>SEA Rule 15c3-1</cite> 
</citesAffected> 
</contentFile> 
</contentFiles>  

父類對應於<contentFile>

@XmlRootElement(name = "contentFile") 
public class RtSuperQuickMetadataItem 
{ 
    private String contentFileName; 
    private String title; 
    private String sourcePublicationDate; 
    private List<AlternateDocNumber> alternateDocNumbers; 
    private List<Cite> citesAffected; 

    public RtSuperQuickMetadataItem() 
    { 
     alternateDocNumbers = new ArrayList<AlternateDocNumber>(); 
     citesAffected = new ArrayList<Cite>(); 
    } 


    public List<AlternateDocNumber> getAlternateDocNumbers() 
    { 
     return alternateDocNumbers; 
    } 


    public List<Cite> getCitesAffected() 
    { 
     return citesAffected; 
    } 


    public String getContentFileName() 
    { 
     return contentFileName; 
    } 


    public String getSourcePublicationDate() 
    { 
     return sourcePublicationDate; 
    } 

    public String getTitle() 
    { 
     return title; 
    } 


    public void setAlternateDocNumbers(List<AlternateDocNumber> alternateDocNumbers) 
    { 
     this.alternateDocNumbers = alternateDocNumbers; 
    } 


    public void setCitesAffected(List<Cite> citesAffected) 
    { 
     this.citesAffected = citesAffected; 
    } 


    public void setContentFileName(String contentFileName) 
    { 
     this.contentFileName = contentFileName; 
    } 


    public void setSourcePublicationDate(String sourcePublicationDate) 
    { 
     this.sourcePublicationDate = sourcePublicationDate; 
    } 

    public void setTitle(String title) 
    { 
     this.title = title; 
    } 

} 


@XmlRootElement(name = "alternateDocNumber") 
class AlternateDocNumber 
{ 
    private String alternateDocNumber; 

    public String getAlternateDocNumber() 
    { 
     return alternateDocNumber; 
    } 

    public void setAlternateDocNumber(String alternateDocNumber) 
    { 
     this.alternateDocNumber = alternateDocNumber; 
    } 

    @Override 
    public String toString() 
    { 
     return "AlternateDocNumber [alternateDocNumber=" + alternateDocNumber + "]"; 
    } 
} 


@XmlRootElement(name = "cite") 
class Cite 
{ 
    private String cite; 

    public String getCite() 
    { 
     return cite; 
    } 

    public void setCite(String cite) 
    { 
     this.cite = cite; 
    } 

    @Override 
    public String toString() 
    { 
     return "Cite [cite=" + cite + "]"; 
    } 
} 

Unmarshaller的代碼使用JAXB:

public RtSuperQuickMetadata unmarshallXml(final File metadataFile) 
     throws JAXBException, FileNotFoundException 
    { 
     RtSuperQuickMetadata rtSuperQuickMetadata = null; 
     try 
     { 
      JAXBContext jc = JAXBContext.newInstance(RtSuperQuickMetadata.class); 

      Unmarshaller um = jc.createUnmarshaller(); 
      rtSuperQuickMetadata = 
       (RtSuperQuickMetadata) um.unmarshal(metadataFile); 
     } 
     catch (JAXBException e) 
     { 
      String msg = "Malformed XML supplied as Metadata" + " Msg " + e.getMessage(); 
      LOG.error(msg, e); 
      throw new RuntimeException(msg, e); 
     } 

     return rtSuperQuickMetadata; 
    } 
+1

不是一個真正的答案,但一般建議。我想借此原理圖和在其上運行XJC生成JAXB類,而不是通過手工來註解它們的。即使你沒有決定使用他們,你至少可以得到什麼編組期待的一個好主意。在實踐中,我發現它更容易有在由XJC編譯的時候產生的模型對象。 – ach

+0

你可以舉一個例子,我可以看一下這個技術並實現它? – Phoenix

+0

@Phoenix通常讓我的XML將看起來怎麼樣,我想在代碼中創建我的對象的結構和使用封送打印​​到System.out的想法。我想更新我的答案來證明這一點。 – cklab

回答

3

您有太多XmlRootElements,您通常只想將它與頂部元素一起使用。你想要做的是將孩子標記爲XmlElement

從所有拆下XmlRootElement註解,但是您的根元素(即RtSuperQuickMetadata),並用XmlElement在從它們將被加載類標記它們。

因此,作爲一個例子,這裏是你的RtSuperQuickMetadata類應該是什麼樣子:

@XmlRootElement(name = "contentFiles") 
class RtSuperQuickMetadata 
{ 
    private List<RtSuperQuickMetadataItem> rtSuperQuickMetadataItems; 

    public RtSuperQuickMetadata() 
    { 
     rtSuperQuickMetadataItems = new ArrayList<RtSuperQuickMetadataItem>(); 
    } 

    @XmlElement(name = "contentFile") 
    public List<RtSuperQuickMetadataItem> getRtSuperQuickMetadataItems() 
    { 
     return rtSuperQuickMetadataItems; 
    } 

    public void setRtSuperQuickMetadataItems(
      List<RtSuperQuickMetadataItem> rtSuperQuickMetadataItems) 
    { 
     this.rtSuperQuickMetadataItems = rtSuperQuickMetadataItems; 
    } 

} 

轉移這一原則alternateDocNumberscitesAffected爲好。


如果你想看到的Unmarshaller如何認爲你的XML是基於把你的註釋格式的一個例子,你可以在代碼中創建您的結構和使用Marshaller。這裏是一個快速和醜陋例如:

RtSuperQuickMetadata rtSuperQuickMetadata = new RtSuperQuickMetadata(); 

List<RtSuperQuickMetadataItem> rtSuperQuickMetadataItems = new ArrayList<RtSuperQuickMetadataItem>(); 
rtSuperQuickMetadata.setRtSuperQuickMetadataItems(rtSuperQuickMetadataItems); 

RtSuperQuickMetadataItem item = new RtSuperQuickMetadataItem(); 
rtSuperQuickMetadataItems.add(item); 

ArrayList<Cite> cites = new ArrayList<Cite>(); 
Cite cite = new Cite(); 
cite.setCiteStr("MyCite"); 
cites.add(cite); 
item.setCitesAffected(cites); 

Marshaller m = jaxbContext.createMarshaller(); 
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
m.marshal(rtSuperQuickMetadata, System.out); 

這將結果輸出到System.out。你可以把它放在一個文件中,而不是滿足你的需要。

+0

這工作。謝謝!我有另一個問題。爲什麼不JAXB自動包含在對象列表分配內存。我們爲什麼要爲它構造函數分配的內存? – Phoenix

+0

坦率地說,我不知道回答你的問題。我最好的猜測是因爲我們使用接口時,聲明我們的變量THEREFORE JAXB沒有實際執行的'list'使用的知識。這就是我們進來說:使用'ArrayList'。 – cklab

+0

@Phoenix - 你並不需要爲'list'性質預先初始化值。 –

1

我已經添加了此答案,以解決您發佈爲answer given by cklab評論的後續問題。

我還有一個問題。 jaxb爲什麼不自動爲對象中包含的列表分配內存 。爲什麼我們需要在它的構造函數中分配內存 ?

你不需要,見下文。

在解編這些項目時,以下內容未保存到 元數據對象中。 12 I 需要添加另一個元素來生成這個?

請參見下面的映射。

RtSuperQuickMetadata

import java.util.*; 
import javax.xml.bind.annotation.*; 

@XmlRootElement(name = "contentFiles") 
public class RtSuperQuickMetadata { 

    private List<RtSuperQuickMetadataItem> rtSuperQuickMetadataItems; 

    @XmlElement(name="contentFile") 
    public List<RtSuperQuickMetadataItem> getRtSuperQuickMetadataItems() { 
     return rtSuperQuickMetadataItems; 
    } 

    public void setRtSuperQuickMetadataItems(
      List<RtSuperQuickMetadataItem> rtSuperQuickMetadataItems) { 
     this.rtSuperQuickMetadataItems = rtSuperQuickMetadataItems; 
    } 

} 

RtSuperQuickMetadataItem

import java.util.List; 
import javax.xml.bind.annotation.XmlType; 

@XmlType(propOrder={"contentFileName", "title", "sourcePublicationDate", "alternateDocNumbers", "citesAffected"}) 
public class RtSuperQuickMetadataItem { 
    private String contentFileName; 
    private String title; 
    private String sourcePublicationDate; 
    private List<AlternateDocNumber> alternateDocNumbers; 
    private List<Cite> citesAffected; 

    public List<AlternateDocNumber> getAlternateDocNumbers() { 
     return alternateDocNumbers; 
    } 

    public List<Cite> getCitesAffected() { 
     return citesAffected; 
    } 

    public String getContentFileName() { 
     return contentFileName; 
    } 

    public String getSourcePublicationDate() { 
     return sourcePublicationDate; 
    } 

    public String getTitle() { 
     return title; 
    } 

    public void setAlternateDocNumbers(
      List<AlternateDocNumber> alternateDocNumbers) { 
     this.alternateDocNumbers = alternateDocNumbers; 
    } 

    public void setCitesAffected(List<Cite> citesAffected) { 
     this.citesAffected = citesAffected; 
    } 

    public void setContentFileName(String contentFileName) { 
     this.contentFileName = contentFileName; 
    } 

    public void setSourcePublicationDate(String sourcePublicationDate) { 
     this.sourcePublicationDate = sourcePublicationDate; 
    } 

    public void setTitle(String title) { 
     this.title = title; 
    } 

} 

AlternateDocNumber

class AlternateDocNumber { 

    private String alternateDocNumber; 

    public String getAlternateDocNumber() { 
     return alternateDocNumber; 
    } 

    public void setAlternateDocNumber(String alternateDocNumber) { 
     this.alternateDocNumber = alternateDocNumber; 
    } 

} 

引用

class Cite { 

    private String cite; 

    public String getCite() { 
     return cite; 
    } 

    public void setCite(String cite) { 
     this.cite = cite; 
    } 

}