2013-02-05 81 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; 
    } 

}