2011-06-14 14 views
11

me gustaría tener métodos de navegación bidireccionales en las clases entre el objeto hijo y el objeto principal. IDREF no es suficiente en mi caso porque no deseo especificar el ID de padre. Para que quede claro, a partir de un xsd así:Navegación padre-hijo-padre JAXB/XJC

<complexType name="A"> 
    <xs:sequence> 
     <element name="b" type="B" minOccurs="0" maxOccurs="unbounded"></element> 
    </xs:sequence> 
    <attribute name="id" type="ID"></attribute> 
</complexType> 
<complexType name="B"> 
    <attribute name="id" type="ID"></attribute> 
</complexType> 

me gustaría clases se parece a esto:

class A { 
    ... 
    public List<B> getB() { ...} 
    ... 
    } 
class B { 
    ... 
    public A getA() { 
    ... 
} 

y mi XML debe ve así:

<a id="a1"> 
    <b id="b1"/> 
    <b id="b2"/> 
    ... 
</a> 

Después unmarshal , Me gustaría poder navegar de A a Bs AND de B a A (a través de b.getA()) !! Es una característica muy básica, pero no encuentro una manera simple de lograr eso ...

¿Alguna idea?

Gracias de antemano

+0

Esto podría ayudar usted: http: //stackoverflow.com/questions/5319024/using-jaxb-to-cross-reference-xmlids-from-two-xml-files – Cris

Respuesta

13

Puede create a methodvoid afterUnmarshal(Unmarshaller, Object parent) que es llamada ... bueno, después de unmarshalling y configurar el árbol de objetos que lo necesite.

+0

muchas gracias es la solución más simple basada en el xsd. – fedevo

+0

Sin embargo, ¿cómo puedo utilizar este método si las clases se crean desde el XSD en cada ejecución de compilación? No puedo modificar las clases creadas por XJC. – migu

+0

Ahora entiendo: el comentario de javadoc de Unmarshaller es muy engañoso diciendo que los métodos de devolución de eventos de eventos 'definidos por clase' permiten a cualquier clase mapeada de JAXB especificar sus propios métodos específicos de devolución de llamada definiendo métodos con la siguiente firma de método. " - ¡En realidad, el oyente no necesita ser una clase mapeada por JAXB! Simplemente implemente una clase de oyente que haga el trabajo y regístrelo a la instancia de unmarshaller. Eso es. – migu

0
<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> 
    <xs:complexType name="A"> 
    <xs:sequence> 
     <xs:element name="b" type="B" minOccurs="0" maxOccurs="unbounded"> 
     </xs:element> 
    </xs:sequence> 
    <xs:attribute name="id" type="xs:ID"></xs:attribute> 
</xs:complexType> 
<xs:complexType name="B"> 
<xs:sequence> 
    <xs:element name="a" type="A" minOccurs="1" maxOccurs="1"/> 
    </xs:sequence> 
</xs:complexType> 
<xs:attribute name="id" type="xs:ID"></xs:attribute> 
</xs:schema> 

Prueba esto ...

3

Nota: Soy el plomo EclipseLink JAXB (MOXy), y un miembro de la JAXB (JSR-222) grupo de expertos.

Eclipse JAXB (MOXy) ofrece la extensión @XmlInverseReference para manejar este caso de uso. Actualmente no se puede generar mediante XJC y debe ser aplicada al modelo de dominio directamente:

class A { 
    ... 
    public List<B> getB() { ...} 
    ... 
    } 

class B { 
    ... 
    @XmlInverseReference(mappedBy="b") 
    public A getA() { 
    ... 
} 

Para más información

+0

gracias pero mi punto de entrada es el xsd ... – fedevo

3

Además de Musikk respuesta en caso de que esté utilizando xjc para generar clases de modelo de dominio de xsd. añadir una referencia a la clase de los padres en todas las clases del modelo se debe:

  1. Crear la clase base que se extiende Unmarshaller.Listener

    public abstract class BaseClass extends Unmarshaller.Listener { 
        protected Object parent; 
    
        public void afterUnmarshal(Unmarshaller unmarshaller, Object parent)  { 
         this.parent = parent; 
        } 
    
        public Object getParent(){ 
         return parent; 
        } 
    } 
    
  2. Dile xjc que todas las clases del modelo deben extender sus BaseClass mediante la creación de xjc global vinculante configuración

    <jaxb:globalBindings> 
        <xjc:superClass name="com.acme.BaseClass" /> 
    </jaxb:globalBindings> 
    
Cuestiones relacionadas