2011-12-02 4 views
6

Sto lavorando a un progetto Scala e vogliamo utilizzare XML per inizializzare i nostri oggetti con JAXB (non Spring). Ho una gerarchia in cui più membri di dati vengono aggiunti nelle sottoclassi. Un semplice esempio potrebbe essere simile a questa:JAXB può inizializzare i valori nelle classi base?

class Animal 
{ 
    string name 
} 

class Cat extends Animal 
{ 
    int numLives 
} 

class Dog extends Animal 
{ 
    bool hasSpots 
} 

mi piacerebbe essere in grado di inizializzare una lista di animali da un blocco XML che sembra qualcosa di simile:

<Animals> 
    <Cat> 
     <name>Garfield</name> 
     <numLives>9</numLives> 
    </Cat> 
    <Dog> 
     <name>Odie</name> 
     <hasSpots>false</hasSpots> 
    </Dog> 
</Animals> 

come potremmo configurare il annotazioni nelle classi per essere in grado di gestire questo?

risposta

0

In questi casi, preferisco creare uno schema XSD e generare codice da esso, quindi siete dalla parte della sicurezza. Ma per rispondere alla tua domanda, sì, puoi. Le annotazioni sono XMLElement, XMLAttribute, XMLRootElement.

3

Per questo esempio si desidera utilizzare le annotazioni @XmlElementRef e @XmlRootElement. Ciò corrisponde al concetto di schema XML dei gruppi di sostituzione. Questo ti permetterà di avere una lista di oggetti da una gerarchia di eredità differenziata per elemento.

Animali

questo servirà come l'oggetto principale per il modello di dominio. Ha una proprietà List annotata con @XmlElementRef. Ciò significa che corrisponderà ai valori in base al valore delle loro annotazioni @XmlRootElement.

package forum8356849; 

import java.util.List; 

import javax.xml.bind.annotation.*; 

@XmlRootElement(name="Animals") 
@XmlAccessorType(XmlAccessType.FIELD) 
@XmlSeeAlso({Cat.class, Dog.class}) 
public class Animals { 

    @XmlElementRef 
    private List<Animal> animals; 
} 

Animal

package forum8356849; 

import javax.xml.bind.annotation.*; 

@XmlAccessorType(XmlAccessType.FIELD) 
class Animal 
{ 
    String name; 
} 

Cat

Ci sarà annotare la classe Cat con una @XmlRootElement annotazione. Questo è usato in tandem con l'annotazione @XmlElementRef su Animals.

package forum8356849; 

import javax.xml.bind.annotation.*; 

@XmlRootElement(name="Cat") 
class Cat extends Animal 
{ 
    int numLives; 
} 

Dog

ci sarà anche aggiungere un @XmlRootElement un'annotazione alla classe Dog.

package forum8356849; 

import javax.xml.bind.annotation.*; 

@XmlRootElement(name="Dog") 
class Dog extends Animal 
{ 
    boolean hasSpots; 
} 

Demo

È possibile utilizzare la seguente classe per vedere che tutto funziona come previsto. input.xml corrisponde all'XML fornito nella domanda.

package forum8356849; 

import java.io.File; 
import javax.xml.bind.*; 

public class Demo { 

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

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     File xml = new File("src/forum8356849/input.xml"); 
     Animals animals = (Animals) unmarshaller.unmarshal(xml); 

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

} 

Per ulteriori inforation

+1

Grazie! Gli darò un colpo! – fbl

+0

Ah, mi sono imbattuto in un piccolo intoppo ...La mia applicazione deve supportare i plugin, il '@XmlSeeAlso ({Cat.class, Dog.class})' implica che ho bisogno di conoscere i miei discendenti in fase di compilazione. In ogni modo? – fbl

+0

@fbl - Non è necessario utilizzare XmlSeeAlso ma JAXBContext deve essere a conoscenza delle sottoclassi. Potresti trovare il seguente approccio più adatto: http://blog.bdoughan.com/2010/08/using-xmlanyelement-to-build-generic.html –