2010-09-07 10 views
16

C'è una risposta segnaposto su the unofficial guide con un collegamento a un articolo che (per me) sembra del tutto estraneo.Perché JAXB a volte si associa a JAXBElement?

Io uso XJC per generare le mie classi JAXB e mentre la maggior parte di esse si mappa l'una con l'altra come previsto, alcuni elementi vengono mappati su JAXBElement<Foo>. Questo è molto fastidioso per i grafici con cicli, dove a volte il nodo genitore di un elemento Foo sarà il JAXBElement<Foo>, che non ha una proprietà genitore, rompendo il ciclo.

Posso pensare a vari metodi, ma sarebbe molto più bello se qualcuno potesse spiegarmi questo comportamento. Perché JAXB a volte associa un elemento <Foo> a JAXBElement<Foo> anziché a Foo?

+0

Vedere http://stackoverflow.com/questions/3639313/xsd-formatting-elementcomplextype-vs-complextype-element/3639375#3639375 per una spiegazione – skaffman

+0

@skaffman: Eh? Non vedo come la tua risposta si riferisce a se xjc sceglie 'JAXBElement ' su 'Foo'. –

+1

@Chris: perché è determinato in parte dalla scelta di tipi anonimi o tipi di nomi nello schema di origine. – skaffman

risposta

10

JAXBElement viene utilizzato per conservare il nome dell'elemento/spazio dei nomi nei casi d'uso in cui non sono presenti informazioni sufficienti nel modello dell'oggetto. L'avvenimento più comune è con i gruppi di sostituzione:

con la sostituzione Gruppo:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://www.example.org" 
    xmlns="http://www.example.org" 
    elementFormDefault="qualified"> 

    <xs:element name="root"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="anElement"/> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 

    <xs:element name="anElement" type="xs:string"/> 

    <xs:element name="aSubstituteElement" type="xs:string" substitutionGroup="anElement"/> 

</xs:schema> 

genererà:

package org.example; 

import javax.xml.bind.JAXBElement; 
import javax.xml.bind.annotation.*; 

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "", propOrder = { 
    "anElement" 
}) 
@XmlRootElement(name = "root") 
public class Root { 

    @XmlElementRef(name = "anElement", namespace = "http://www.example.org", type = JAXBElement.class) 
    protected JAXBElement<String> anElement; 

    public JAXBElement<String> getAnElement() { 
     return anElement; 
    } 

    public void setAnElement(JAXBElement<String> value) { 
     this.anElement = ((JAXBElement<String>) value); 
    } 

} 

senza sostituzione Gruppo:

Se si rimuove il gruppo di sostituzione:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://www.example.org" 
    xmlns="http://www.example.org" 
    elementFormDefault="qualified"> 

    <xs:element name="root"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="anElement"/> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 

    <xs:element name="anElement" type="xs:string"/> 

</xs:schema> 

La classe seguente verrà generato:

package org.example; 

import javax.xml.bind.annotation.*; 

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "", propOrder = { 
    "anElement" 
}) 
@XmlRootElement(name = "root") 
public class Root { 

    @XmlElement(required = true) 
    protected String anElement; 

    public String getAnElement() { 
     return anElement; 
    } 

    public void setAnElement(String value) { 
     this.anElement = value; 
    } 

} 

Si può anche ottenere un JAXBElement quando unmarshalling, confrontare i seguenti esempi:

+0

Grazie, i gruppi di sostituzione sono effettivamente dove sta succedendo. Quindi è un bug che in 'afterUnmarshal (Unmarshaller u, Object parent)' queste classi sostituibili vengono passate al loro JAXBElement come loro 'parent'? Soprattutto perché non sembra esserci un modo per ottenere l'elemento genitore reale da JAXBElement. –

+0

Questo sembra essere un bug in Metro JAXB (l'implementazione di riferimento, inclusa in Java SE 6). Nell'implementazione di MOXy JAXB (http://www.eclipse.org/eclipselink/moxy.php) l'oggetto genitore corretto viene passato al metodo afterUnmarshal. –

0

Per evitare di mappare a JAXBElement? ho fatto cose che lavorano per me:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
      xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
      jaxb:extensionBindingPrefixes="xjc" 
      jaxb:version="2.0"> 

    <xs:annotation> 
     <xs:appinfo> 
      <jaxb:globalBindings generateValueClass="false"> 
      <xjc:simple /> 
      </jaxb:globalBindings> 
     </xs:appinfo> 
    </xs:annotation> 

</xs:schema> 

Salva il file nel file XML e la fornitura di file come vincolanti.

Riferimento Link

generare classi JAXB con Eclipse non dimenticate di dare file di collegamento creati con sopra xml e controllare "Consenti estensioni del fornitore", come di seguito:

enter image description here

Con i cambiamenti sono in grado Get liberarsi di JAXBElement nelle classi generate xjc per convertire le classi generate da xsd a JAXB.

Problemi correlati