JAXB / XJC родитель-потомок-родительская навигация - PullRequest
13 голосов
/ 14 июня 2011

Я хотел бы иметь двунаправленные методы навигации в классах между дочерним объектом и родительским объектом. IDREF недостаточно в моем случае, потому что я не хочу указывать идентификатор файла родителя. чтобы быть понятным, из XSD, как это:

<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>

я бы хотел, чтобы классы выглядели так:

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

и мой xml должен выглядеть так:

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

После демаршала я бы хотел иметь возможность перемещаться от A к Bs и от B к A (через b.getA ()) !! Это очень простая функция, но я не нахожу простой способ добиться этого ...

Есть идеи ??

Заранее спасибо

Ответы [ 4 ]

14 голосов
/ 14 июня 2011

Вы можете создать метод void afterUnmarshal(Unmarshaller, Object parent), который будет вызываться ... ну, после демаршаллинга, и настроить дерево объектов так, как вам нужно.

5 голосов
/ 14 июня 2011

Примечание: Я являюсь лидером EclipseLink JAXB (MOXy) и членом группы экспертов JAXB ( JSR-222 ).

Eclipse JAXB (MOXy) предлагает расширение @XmlInverseReference для обработки этого варианта использования.В настоящее время он не может быть сгенерирован XJC и должен применяться непосредственно к модели домена:

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

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

Для получения дополнительной информации

4 голосов
/ 28 мая 2015

В дополнение к musiKk ответ, если вы используете xjc для создания классов модели домена из xsd. Чтобы добавить ссылку на родительский класс во все классы модели, вы должны:

  1. Создать базовый класс, который расширяется 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. Скажите xjc, что все классы модели должны расширять ваш BaseClass путем создания глобальной конфигурации связывания xjc

    <jaxb:globalBindings>
        <xjc:superClass name="com.acme.BaseClass" />
    </jaxb:globalBindings>
    
0 голосов
/ 14 июня 2011
<?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>

Попробуйте это ...

...