2011-12-02 18 views
6

Estoy trabajando en un proyecto de Scala, y queremos usar XML para inicializar nuestros objetos con JAXB (no Spring). Tengo una jerarquía en la que se agregan más miembros de datos en las subclases. Un ejemplo sencillo sería algo como esto:¿JAXB puede inicializar valores en clases base?

class Animal 
{ 
    string name 
} 

class Cat extends Animal 
{ 
    int numLives 
} 

class Dog extends Animal 
{ 
    bool hasSpots 
} 

Me gustaría ser capaz de inicializar una lista de animales a partir de un bloque de XML que se ve algo como esto:

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

¿Cómo podemos configurar la anotaciones en las clases para poder manejar esto?

Respuesta

0

En tales casos, prefiero crear un esquema XSD y generar código a partir de él, por lo que está seguro. Pero para responder a su pregunta, sí, puede. Las anotaciones son XMLElement, XMLAttribute, XMLRootElement.

3

Para este ejemplo, querrá hacer uso de las anotaciones @XmlElementRef y @XmlRootElement. Esto corresponde al concepto de esquema XML de grupos de sustitución. Esto le permitirá tener una lista de objetos de una jerarquía de herencia diferenciada por elemento.

Animales

Esto servirá como el objeto raíz para el modelo de dominio. Tiene una propiedad List anotada con @XmlElementRef. Esto significa que coincidirá los valores basados ​​en el valor de sus anotaciones @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; 
} 

gato

Nos anotará la clase Cat con una anotación @XmlRootElement. Esto se usa en tándem con la anotación @XmlElementRef en Animals.

package forum8356849; 

import javax.xml.bind.annotation.*; 

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

perro

también vamos a añadir una anotación @XmlRootElement a la clase Dog.

package forum8356849; 

import javax.xml.bind.annotation.*; 

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

demostración

Puede utilizar la siguiente clase para ver que todo funciona como se esperaba. input.xml corresponde al XML proporcionado en su pregunta.

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

} 

Para más inforation

+1

Gracias! ¡Lo intentaré! – fbl

+0

Ahh, me encontré con un pequeño inconveniente ...Mi aplicación necesita compatibilidad con complementos, el '@XmlSeeAlso ({Cat.class, Dog.class})' implica que necesito saber sobre mis descendencias en tiempo de compilación. De cualquier manera alrededor de eso? – fbl

+0

@fbl: no necesita usar XmlSeeAlso, pero el JAXBContext necesita estar al tanto de las subclases. Puede encontrar el siguiente enfoque un mejor ajuste: http://blog.bdoughan.com/2010/08/using-xmlanyelement-to-build-generic.html –

Cuestiones relacionadas