2011-02-03 22 views
6

Tengo una jerarquía de clases generadas por JAXB. Me gustaría organizar una clase hija como un elemento de clase base (pero con todos los atributos de clase secundaria), usando xsi: type para indicar el tipo concreto.JAXB Marshalling and Polymorphism

Por ejemplo, dado un animal y una subclase de aves:

<xs:complexType name="animal" abstract="true"> 
    <xs:sequence> 
     <xs:element name="name" type="xs:string"/> 
    </xs:sequence> 
</xs:complexType> 

<xs:complexType name="bird"> 
    <xs:complexContent> 
     <xs:extension base="animal"> 
      <xs:sequence> 
       <xs:element name="maxAltitude" type="xs:int"/> 
      </xs:sequence> 
     </xs:extension> 
    </xs:complexContent> 
</xs:complexType> 

<xs:element name="Animal" type="animal"/> 
<xs:element name="Bird" type="bird"/> 

No importa cómo lo Marshal un pájaro, por ejemplo:

Bird sparrow = new Bird(); 
sparrow.setName("Sparrow"); 
sparrow.setMaxAltitude(1000); 

JAXBContext context = JAXBContext.newInstance(Animal.class, Bird.class); 
Marshaller marshaller = context.createMarshaller(); 
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
marshaller.marshal(sparrow, System.out); 

El resultado es siempre un elemento de aves:

<Bird xmlns="http://mycompany.com/animals"> 
    <name>Sparrow</name> 
    <maxAltitude>1000</maxAltitude> 
</Bird> 

Sin embargo, lo que quiero es esto (todos los atributos de la subclase, tipo xsi, nombre de elemento de clase base):

<Animal xmlns="http://mycompany.com/animals" 
     xsi:type="bird" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <name>Sparrow</name> 
    <maxAltitude>1000</maxAltitude> 
</Animal> 

Lo curioso es que si creo un elemento de envoltorio:

<xs:complexType name="animalWrapper"> 
    <xs:sequence> 
     <xs:element name="Animal" type="animal"/> 
    </xs:sequence> 
</xs:complexType> 

<xs:element name="AnimalWrapper" type="animalWrapper"/> 

y reunir ello, utiliza el tipo de clase base:

<AnimalWrapper xmlns="http://mycompany.com/animals" 
    <Animal xsi:type="bird" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
     <name>Sparrow</name> 
     <maxAltitude>1000</maxAltitude> 
    </Animal> 
</AnimalWrapper> 

Si construyo manualmente mi XML deseado documento, JAXB no tiene ningún problema en desmantelarlo. ¿Cómo puedo autorizar mi esquema XML y/o configurar JAXB para permitir mi comportamiento de clasificación deseado?

Gracias.

Respuesta

1

que podría hacer lo siguiente:

QName qName = jc.createJAXBIntrospector().getElementName(new Animal()); 
JAXBElement<Animal> jaxbElement = new JAXBElement<Animal>(qName, Animal.class, new Bird()); 
marshaller.marshal(jaxbElement, System.out); 

Salida:

+0

Gracias. Su ejemplo tiene una envoltura alrededor de los elementos que son polimórficos, como mi ejemplo de AnimalWrapper, y no es lo que estoy buscando. Quiero el polimorfismo en el elemento raíz. – SingleShot

+0

Actualicé mi respuesta para abordar el caso raíz. –

+0

Gracias. El animal es abstracto, así que no puedo hacer eso. Podría soltar el esquema, supongo, pero prefiero no hacerlo. Voy a jugar con cosas similares a lo que sugieres. – SingleShot