解析顶部元素包含对象列表的XML文档

时间:2012-12-15 20:48:24

标签: java xml jaxb jersey

我必须查询多个返回包含一张发票或发票列表的XML文件的网址(我知道哪些网址会返回一个列表,哪些网址只返回一张发票)。

单张发票的格式(简化):

<?xml version="1.0" encoding="UTF-8"?>
  <invoice>
    <invoice-id>1</invoice-id>
</invoice>

发票清单的格式:

<?xml version="1.0" encoding="UTF-8"?>
<invoices>
  <invoice>
    <invoice-id>1</invoice-id>
  </invoice>
  <invoice>
    <invoice-id>2</invoice-id>
  </invoice>
</invoices>

Jersey可以自动处理第一个xml片段并将其转换为Java类:

@XmlRootElement
public class Invoice {
    @XmlElement(name="invoice-id")  
    Integer invoiceId;
}

使用以下代码完成:

GenericType<JAXBElement<Invoice>> invoiceType = new GenericType<JAXBElement<Invoice>>() {};
Invoice invoice = (Invoice) resource.path("invoice_simple.xml").accept(MediaType.APPLICATION_XML_TYPE).get(invoiceType).getValue(); 

上述工作。

现在我想拥有一个InvoiceList对象,如下所示:

@XmlRootElement
public class InvoiceList {
    @XmlElementWrapper(name="invoices")
    @XmlElement(name="invoice")
    List<Invoice> invoices; 
}

这是我遇到问题的地方;在以下情况之后,InvoiceList.invoices保持为空:

GenericType<JAXBElement<InvoiceList>> invoicesType = new GenericType<JAXBElement<InvoiceList>>() {};
InvoiceList invoices = (InvoiceList) resource.path("invoices_simple.xml").accept(MediaType.APPLICATION_XML_TYPE).get(invoicesType).getValue();      
// now invoices.invoices is still null!

我知道Jersey / JAXB可以处理对象列表,但是如果top元素包含列表,它似乎不起作用。

所以,我的问题是:如何指示Jersey解析由发票对象列表组成的xml文件?

1 个答案:

答案 0 :(得分:2)

第一个答案是

nillable = true放到@XmlElement

@XmlElement(name = "invoice", nillable = true)
List<Invoice> invoices; 

我会这样做的。 (您不必包装已经包装的集合。)

@XmlRootElement
public class Invoices {

    public List<Invoice> getInvoices() {
        if (invoices == null) {
            invoices = new ArrayList<Invoice>();
        }
        return invoices;
    }

    @XmlElement(name = "invoice", nillable = true)
    private List<Invoice> invoices; 
}

一些JAX-RS示例就像这样

@GET
@Path("/invoices")
public Invoices readInvoices() {
    // ...
}

@GET
@Path("/invoices/{invoice_id: \\d+}")
public Invoice readInvoice(@PathParam("invoice_id") final long invoiceId) {
    // ...
}