2011-02-15 32 views
8

Tôi có một lớp học Động vật và một phần mở rộng của Động vật được gọi là AnimalExtension.JAXB @XmlElements, các loại khác nhau nhưng cùng tên?

public class Animal 

public class AnimalExtension extends Animal 

Sự khác biệt duy nhất giữa hai lớp là AnimalExtension có một biến thể hiện khác được gọi là animalId. Động vật không có biến thể hiện này.

Tôi cũng có loại dữ liệu của riêng mình mà tôi muốn sắp xếp và không đối sánh với XML. Kiểu dữ liệu này được gọi là AnimalList. bên trong AnimalList, có một danh sách các loài động vật như một biến cá thể.

@XmlType(name = "AnimalList") 
public class AnimalList{ 
    private List<Animal> animalList; 
    .... 

animalList có thể chứa cả Animal and AnimalExtension. Tuy nhiên, trên XML tôi không muốn phần tử được đặt tên là AnimalExtension; Tôi muốn tất cả họ có tên yếu tố của động vật. Tôi chỉ muốn thêm thuộc tính để hiển thị khi JAXB biết rằng Động vật thực sự là một thể hiện của AnimalExtension. Vì vậy, nếu tôi có một danh sách giống như

List<Animal> animalList = new LinkedList<Animal>(); 
AnimalExtension animalExtension = new AnimalExtension(); 
animalExtension.setAnimalId(1); 
amimalExtension.setName("Don"); 

Animal animal = new Animal(); 
animal.setName("Mike"); 
animalList.add(animalExtension); 
animalList.add(animal); 

Tôi muốn XML để trông giống như

<AnimalList> 
    <Animal name="Don" id="1" /> 
    <Animal name="Mike" /> 
</AnimalList> 

Đây là những gì tôi đã cố gắng làm

@XmlElements(
    { 
      @XmlElement(name = "Animal", type = Animal.class), 
      @XmlElement(name = "Animal", type = AnimalExtension.class) 
     } 
    ) 
    public List<Animal> getEntries() { 
     return animalList; 
    } 

mã biên dịch nhưng khi tôi thử chạy máy chủ của mình. Nó mang lại cho tôi lỗi lạ này không liên quan đến những gì đang diễn ra (BeanCreationException). Tôi đã cố gắng làm cho tên của XmlElement là khác nhau cho mỗi loại và hoạt động, nhưng thách thức ở đây là làm cho tên giống nhau.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'encryptionPayloadContentProvider' 
+5

Với một XML như thế nào JAXB phải xác định lớp để sử dụng cho việc tạo đối tượng Java? Nó có tồn tại thuộc tính 'id' không? Điều gì sẽ xảy ra nếu có một lớp khác có tên 'AnimalEnhacement' có thuộc tính id? –

+0

điểm tốt lol. không nghĩ về điều đó. – denniss

Trả lời

9

Để ánh xạ trường hợp này sử dụng bạn có thể tận dụng XmlAdapters sau:

AnimalAdapter

Kể từ AnimalExtension là một tập hợp siêu Thú chúng ta sẽ sử dụng nó để sản xuất/tiêu thụ XML. Sau đó, chúng ta sẽ tận dụng giá trị của thuộc tính animalId để xác định xem một cá thể của Animal hay AnimalExtension có được trả lại cho AnimalList hay không.

import javax.xml.bind.annotation.adapters.XmlAdapter; 

public class AnimalAdapter extends XmlAdapter<AnimalExtension, Animal> { 

    @Override 
    public Animal unmarshal(AnimalExtension animalExtension) throws Exception { 
     if(0 != animalExtension.getAnimalId()) { 
      return animalExtension; 
     } 
     Animal animal = new Animal(); 
     animal.setName(animalExtension.getName()); 
     return animal; 
    } 

    @Override 
    public AnimalExtension marshal(Animal animal) throws Exception { 
     if(animal.getClass() == AnimalExtension.class) { 
      return (AnimalExtension) animal; 
     } 
     AnimalExtension animalExtension = new AnimalExtension(); 
     animalExtension.setName(animal.getName()); 
     return animalExtension; 
    } 

} 

IdAdapter

Chúng tôi sẽ cần một XmlAdapter thứ hai để ngăn chặn animalId nếu giá trị của nó là 0:

import javax.xml.bind.annotation.adapters.XmlAdapter; 

public class IdAdapter extends XmlAdapter<String, Integer> { 

    @Override 
    public Integer unmarshal(String string) throws Exception { 
     return Integer.valueOf(string); 
    } 

    @Override 
    public String marshal(Integer integer) throws Exception { 
     if(integer == 0) { 
      return null; 
     } 
     return String.valueOf(integer); 
    } 

} 

lớp mô hình của bạn sẽ được chú thích như sau:

AnimalList

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

import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 

@XmlRootElement(name="AnimalList") 
public class AnimalList { 

    private List<Animal> animalList = new ArrayList<Animal>(); 

    @XmlElement(name="Animal") 
    @XmlJavaTypeAdapter(AnimalAdapter.class) 
    public List<Animal> getEntries() { 
     return animalList; 
    } 

} 

Animal

import javax.xml.bind.annotation.XmlAttribute; 

public class Animal { 

    private String name; 

    @XmlAttribute 
    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

} 

AnimalExtension

import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 

public class AnimalExtension extends Animal { 

    private int animalId; 

    @XmlAttribute(name="id") 
    @XmlJavaTypeAdapter(IdAdapter.class) 
    public int getAnimalId() { 
     return animalId; 
    } 

    public void setAnimalId(int animalId) { 
     this.animalId = animalId; 
    } 

} 

Demo Mã

Mã giới thiệu sau đây có thể được sử dụng để chứng minh giải pháp này:

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(AnimalList.class); 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     File xml = new File("input.xml"); 
     AnimalList animalList = (AnimalList) unmarshaller.unmarshal(xml); 

     for(Animal animal : animalList.getEntries()) { 
      System.out.println(animal.getClass()); 
     } 

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

} 

Các đầu ra sau đây sẽ được sản xuất:

class AnimalExtension 
class Animal 
<?xml version="1.0" encoding="UTF-8"?> 
<AnimalList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <Animal name="Don" id="1"/> 
    <Animal name="Mike"/> 
</AnimalList> 

Thông tin liên quan

Bạn có thể tìm thấy những thông tin hữu ích sau đây:

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