2011-02-03 39 views
5

Tôi đang chuyển từ Castor để JAXB2 để thực hiện marshaling/unmarshaling giữa XML và đối tượng Java. Tôi đang gặp sự cố khi cố định cấu hình tập hợp các đối tượng đa hình.Cấu hình bộ sưu tập của các đối tượng đa hình để làm việc trong JAXB2

mẫu XML

<project name="test project"> 
    <orange name="fruit orange" orangeKey="100" /> 
    <apple name="fruit apple" appleKey="200" /> 
    <orange name="fruit orange again" orangeKey="500" /> 
</project> 

lớp Project

Danh sách oranges hoạt động tốt, tôi nhìn thấy 2 cam trong danh sách. Nhưng, tôi không chắc chắn làm thế nào để cấu hình fruitList. Các fruitList nên có 3 trái cây: 2 quả cam và 1 quả táo.

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Project { 

    @XmlAttribute 
    private String   name; 

    @XmlElement(name = "orange") 
    private List<Orange> oranges  = new ArrayList<Orange>(); 

    // Not sure how to configure this... help! 
    private List<Fruit>  fruitList = new ArrayList<Fruit>(); 
} 

lớp Fruit

trái cây là một lớp trừu tượng. Đối với một số lý do, việc xác định lớp này là một bản tóm tắt dường như đang gây ra rất nhiều vấn đề.

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public abstract class Fruit { 

    @XmlAttribute 
    private String name; 
} 

Orange lớp

public class Orange extends Fruit { 

    @XmlAttribute 
    private String orangeKey; 
} 

của Apple lớp

public class Apple extends Fruit { 

    @XmlAttribute 
    private String appleKey; 
} 

Làm thế nào để cấu hình của tôi fruitList trong Project để đạt được những gì tôi muốn ở đây?

Cảm ơn nhiều!

Trả lời

4

Bạn muốn tận dụng @XmlElementRef này là tương ứng với khái niệm lược đồ XML của các nhóm thay thế tương ứng với câu hỏi của bạn.

Bước 1 - Sử dụng @XmlElementRef

Thuộc tính fruitList được chú thích với @XmlElementRef:

import java.util.ArrayList; 
import java.util.List; 

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlElementRef; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Project { 

    @XmlAttribute 
    private String name; 

    @XmlElementRef 
    private List<Fruit> fruitList = new ArrayList<Fruit>(); 

} 

Bước 2 - Chú thích Apple và Orange với @XmlRootElement

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Apple extends Fruit { 

    @XmlAttribute 
    private String appleKey; 

} 

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Orange extends Fruit { 

    @XmlAttribute 
    private String orangeKey; 

} 

Demo Mã

Các mã sau đây có thể được sử dụng để chứng minh các giải pháp:

import java.io.File; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Marshaller; 
import javax.xml.bind.Unmarshaller; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Project.class, Apple.class, Orange.class); 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     Project project = (Project) unmarshaller.unmarshal(new File("input.xml")); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(project, System.out); 
    } 

} 

Để biết thêm thông tin:

+0

Tôi đang thử cách tiếp cận của bạn ... Tôi đã chú thích 'fruitList' thuộc tính với '@ XmlElementRef' và các lớp' Orange' và 'Apple' được chú thích có' @ XmlRootElement'. Tôi chạy mã, và 'fruitList' xuất hiện trống. Tôi làm gì sai ở đây? Cảm ơn. – limc

+1

Tôi đã tìm ra vấn đề, tôi phải thêm 'Orange.class' và' Apple.class' vào 'JAXBContext.newInstance (..)' cùng với 'Project'. Hoạt động ngay bây giờ. Cảm ơn. – limc

0

Đặt XmlAnyElement chú thích:

@XmlAnyElement(lax = true) 
private List<Fruit>  fruitList = new ArrayList<Fruit>(); 
+0

Đó không làm việc ... 'fruitList' chứa một 'apple' kiểu' ElementNSImpl'. – limc

+0

Đối với @XmlAnyElement, bạn cần phải thêm @XmlRootElement vào mỗi lớp con. Điều này có nghĩa là nhiều hơn cho phần thẻ hoang dã mặc dù. Vì các đối tượng con nằm trong một mối quan hệ kế thừa @XmlElementRef là một lựa chọn tốt hơn ở đây. Để biết thêm thông tin về @XmlAnyElement, hãy xem: http: //bdoughan.blogspot.com/2010/08/using-xmlanyelement-to-build-generic.html –

2

Sau futzing xung quanh ... Tôi nghĩ rằng tôi đã nhận nó làm việc bây giờ: -

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Project { 

    @XmlAttribute 
    private String  name; 

    // this has to be commented out, or else oranges won't show up in fruitList 
    // @XmlElement(name = "orange") 
    // private List<Orange> oranges = new ArrayList<Orange>(); 

    @XmlElements({ 
      @XmlElement(name = "orange", type = Orange.class), 
      @XmlElement(name = "apple", type = Apple.class) 
    }) 
    private List<Fruit> fruitList = new ArrayList<Fruit>(); 

} 
+1

@XmlElements sẽ hoạt động, nhưng mỗi lần bạn thêm một lớp con mới, bạn sẽ phải chỉnh sửa lớp Project. Nếu bạn sử dụng @XmlElementRef thay vào đó, bạn sẽ chỉ cần chú thích lớp con mới với @XmlRootElement. @XmlElements là nhiều hơn để đại diện cho các cấu trúc lựa chọn: http://bdoughan.blogspot.com/2010/10/jaxb-and-xsd-choice-xmlelements.html –

Các vấn đề liên quan