2012-10-05 45 views
6

Tôi đang cố gắng để unmarshall một tài liệu XML từ một hệ thống di sản bằng cách sử dụng JAXB. Tôi có cấu trúc xml như sau:JAXB unmarshalling với java Generics

<response> 
    <id>000000</id> 
    <results> 
     <result> 
<!-- Request specific xml content --> 
      <year>2003</year> 
      <title>Lorem Ipsum</title> 
      <items> 
       <item>I1</item> 
       <item>I2</item> 
      </items> 
     </result> 
     <result> 
      <year>2007</year> 
      <title>Dolor sit amet</title> 
      <items> 
       <item>K1</item> 
       <item>K2</item> 
      </items> 
     </result> 
    </results> 
</response> 

Thẻ bên trong một phần được chỉ định bởi <result> sẽ thay đổi tùy theo yêu cầu của tôi. Kể từ khi nội dung có thể thay đổi tôi quyết định sử dụng Generics cho các hạng mục kết quả và tôi đã chuẩn bị đậu java của tôi với các chú thích như sau:

// imports here 
@XmlRootElement(name="response") 
@XmlAccessorType(XmlAccessType.FIELD) 
public class XResponse<T>{ 
    private String id; 

    @XmlElementWrapper(name="results") 
    @XmlElement(name="result") 
    private List<T> results; 

// setters and getters 
} 

... 

@XmlRootElement(name="result") 
@XmlAccessorType(XmlAccessType.FIELD) 
public class X1Result{ 
    private String year; 
    private String title; 
    @XmlElementWrapper(name="items") 
    @XmlElement(name="item") 
    private List<String> items; 

// setters and getters 
} 
... 

Tôi đã cố gắng unmarshalling tài liệu xml qua vào mã bên dưới:

JAXBContext context = JAXBContext.newInstance(XResponse.class, X1Result.class); 
Unmarshaller um = context.createUnmarshaller(); 
XResponse<X1Result> response = (XResponse<X1Result>) um.unmarshal(xmlContent); 

List<X1Result> results = unmarshal.getResults(); 
for (X1Result object : results) { 
    System.out.println(object.getClass()); 
} 

Tôi có một vấn đề trong unmarshalling rằng nó không thể đúc các mục danh sách vào lớp X1Result. Thay vào đó, nó sử dụng org.apache.xerces.dom.ElementNSImpl.

Tôi nên làm gì để khiến JAXB Unmarshaller sử dụng lớp X1Result?

Cảm ơn trước

Trả lời

2

Tôi nghĩ bạn nên sử dụng thừa kế thay vì Generics. Được cung cấp một XML như thế này:

<?xml version="1.0" encoding="UTF-8"?> 
<response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <id>000000</id> 
    <results> 
     <result xsi:type="X1Result"> 
      <year>2003</year> 
      <title>Lorem Ipsum</title> 
      <items> 
       <item>I1</item> 
       <item>I2</item> 
      </items> 
     </result> 
     <result xsi:type="X1Result"> 
      <year>2007</year> 
      <title>Dolor sit amet</title> 
      <items> 
       <item>K1</item> 
       <item>K2</item> 
      </items> 
     </result> 
    </results> 
</response> 

Bạn có thể tự động ràng buộc các mục nhập <result> của mình. Bạn có một loại cấp cao nhất:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "XResult") 
@XmlSeeAlso({ 
    X1Result.class 
})public abstract class XResult { 

} 

Và bạn có các lớp học thực hiện:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "X1Result") 
public class X1Result extends XResult { 
    @XmlElement(name = "year") 
    private String year; 

    @XmlElement(name = "title") 
    private String title; 

    @XmlElementWrapper(name = "items") 
    @XmlElement(name = "item") 
    private List<String> items; 
    ... 
} 

Sử dụng loại cấp cao nhất trong lớp XResponse của bạn:

@XmlRootElement(name = "response") 
@XmlAccessorType(XmlAccessType.FIELD) 
public class XResponse { 
    @XmlElement(name = "id") 
    private String id; 

    @XmlElementWrapper(name = "results") 
    @XmlElement(name = "result") 
    private List<XResult> results; 
    ... 
} 

Và bạn có thể unmarshall sử dụng loại cấp cao nhất:

context = JAXBContext.newInstance(XResponse.class, XResult.class); 
Unmarshaller unmarshaller = context.createUnmarshaller(); 
XResponse response = (XResponse) unmarshaller.unmarshal(new File("testfile.xml")); 

List<XResult> results = response.getResults(); 
for (XResult object : results) { 
    System.out.println(object.getClass()); 
} 
+0

Mã trên init ializes 'XResult' thay vì' X1Result' và do đó nó cho lỗi vì nó là một lớp trừu tượng. Bên cạnh đó nội dung của xml đến từ một hệ thống kế thừa và không có sẵn thông tin 'xsi: type'. (mặc dù tôi có thể thêm nó theo chương trình) – Alper

+0

Mã sẽ khởi tạo một 'X1Result' nếu' xsi: type' ở đó. Ít nhất, đó là những gì nó làm cho tôi. Chúc may mắn. – davidfmatheson

+0

Điều này làm việc tốt cho tôi mà không có 'xsi: type' hiện diện trong XML. Tôi đang sử dụng Java 1.7.0_15. –