2011-02-15 110 views
8

我有一個動物類和動物的延伸叫做AnimalExtension。JAXB @XmlElements,不同類型但名稱相同?

public class Animal 

public class AnimalExtension extends Animal 

這兩個類之間的唯一區別是AnimalExtension具有另一個名爲animalId的實例變量。動物沒有這個實例變量。

我也有我自己的數據類型,我想編組和unamarshal到XML。這個數據類型被稱爲AnimalList。在AnimalList中,有一個動物列表作爲實例變量。

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

animalList可以同時包含Animal和AnimalExtension。但是,在XML上,我不希望元素被命名爲AnimalExtension;我希望他們都擁有Animal的元素名稱。我只想在JAXB知道Animal實際上是AnimalExtension的一個實例時顯示額外的屬性。所以,如果我有一個列表看起來像

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); 

我想要的XML看起來像

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

這是我試圖做

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

的代碼編譯,但當我嘗試運行我的服務器時。它給了我這個與正在發生的事情無關的奇怪錯誤(BeanCreationException)。我試着讓XmlElement的名稱對於每種類型都有所不同,但是這裏面臨的挑戰是使名稱相同。

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

給定一個XML的JAXB應該如何確定使用Java對象創建哪一類?是否存在'id'屬性?如果有其他具有id屬性的名爲'AnimalEnhacement'的類呢? –

+0

好點大聲笑。沒有想到這一點。 – denniss

回答

9

要映射這種使用情況下,你可以利用以下XmlAdapters:

AnimalAdapter

由於AnimalExtension是一個超集動物,我們將用它來生產/使用XML。然後,我們將利用animalId屬性的值來確定Animal或AnimalExtension的實例是否會返回給AnimalList。

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

我們將需要第二XmlAdapter打壓animalId如果它的值是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); 
    } 

} 

如下您的模型類將被註釋:

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; 
    } 

} 

動物

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; 
    } 

} 

演示代碼

下面演示代碼可以用來演示此解決方案:

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); 
    } 

} 

以下輸出將製作:

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> 

相關信息

您可能會發現有用的下列信息:

相關問題