JAXB / XJC parent-child-parent navigation

2020-03-01 08:20发布

i would like to have bidirectional navigation methods in classes between child object and parent object. IDREF is not enough in my case because I don't want to specify le id of parent. to be clear, from an xsd like that:

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

i would like classes looks like this:

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

and my xml must looks like this:

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

After unmarshal, I would like to be able to navigate A to Bs AND from B to A (via b.getA()) !! It a very basic feature, but I don't find a simple way to achieve that ...

Any idea ??

Thanks in advance

标签: java jaxb xjc
4条回答
够拽才男人
2楼-- · 2020-03-01 08:34
<?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>

Try this...

查看更多
兄弟一词,经得起流年.
3楼-- · 2020-03-01 08:44

You can create a method void afterUnmarshal(Unmarshaller, Object parent) that gets called... well, after unmarshalling and set up your object tree as you need it.

查看更多
Anthone
4楼-- · 2020-03-01 08:47

Note: I'm the EclipseLink JAXB (MOXy) lead, and a member of the JAXB (JSR-222) expert group.

Eclipse JAXB (MOXy) offers the @XmlInverseReference extension to handle this use case. Currently it can not be generated by XJC and must be applied to the domain model directly:

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

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

For More Information

查看更多
神经病院院长
5楼-- · 2020-03-01 08:55

In addition to musiKk answer in case you are using xjc to generate domain model classes from xsd. To add reference to parent class in all model classes you should:

  1. Create base class which extends 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. Tell xjc that all model classes should extend your BaseClass by creating global xjc binding configuration

    <jaxb:globalBindings>
        <xjc:superClass name="com.acme.BaseClass" />
    </jaxb:globalBindings>
    
查看更多
登录 后发表回答