And want to bi" /> And want to bi" /> And want to bi"/>

JAXB: XMLIDRef in attribute?

114 Views Asked by At

I have an XML which looks like this :

<MyClass id="abc-123">
   <SomeAttribute idref="cde-456" />
</MyClass>

<SomeOtherClass id="cde-456">

And want to bind this using JAXB / Moxy. The best I could achieve so far is

 @XmlIDREF
 @XmlElement(name="SomeAttribute ")
 //@XmlPath("SomeAttribute /@idref")
 protected SomeOtherClass someAttribute ;

but this gives only <SomeAttribute>cde-456</SomeAttribute>

Any idea, how binding of the idref attribute might work ? The @XmlPath does not work.

2

There are 2 best solutions below

0
BATMAN_2008 On

This should work for you:

XML:

<root>
    <MyClass id="abc-123">
        <SomeAttribute idref="cde-456"/>
    </MyClass>
    <SomeOtherClass id="cde-456"/>
</root>

Root:

@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
@Data
public class Root {
    private MyClass MyClass;
    private SomeOtherClass SomeOtherClass;
}

MyClass:

@XmlAccessorType(XmlAccessType.FIELD)
@Data
public class MyClass {
    @XmlAttribute
    private String id;
    private SomeAttribute SomeAttribute;
}

SomeAttribute:

@XmlAccessorType(XmlAccessType.FIELD)
@Data
public class SomeAttribute {
    @XmlAttribute
    private String idref;
}

SomeOtherClass:

@XmlAccessorType(XmlAccessType.FIELD)
@Data
public class SomeOtherClass {
    @XmlAttribute
    private String id;
}

Main:

public class Main {
    public static void main(String[] args) throws JAXBException, XMLStreamException {
        final InputStream inputStream = Main.class.getClassLoader().getResourceAsStream("sample.xml");
        final XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
        final Unmarshaller unmarshaller = JAXBContext.newInstance(Root.class).createUnmarshaller();
        final Root root = unmarshaller.unmarshal(xmlStreamReader, Root.class).getValue();
        System.out.println(root.toString());

        Marshaller marshaller = JAXBContext.newInstance(Root.class).createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.marshal(root, System.out);
    }
}

Output:

Root(MyClass=MyClass(id=abc-123, SomeAttribute=SomeAttribute(idref=cde-456)), SomeOtherClass=SomeOtherClass(id=cde-456))
<root>
   <MyClass id="abc-123">
      <SomeAttribute idref="cde-456"/>
   </MyClass>
   <SomeOtherClass id="cde-456"/>
</root>
0
Carsten Zerbst On

now I solved it for a small example, real world still to be done :-)

  1. Use Moxy and add jaxb.properties to your resources for that package. javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
  2. Root class
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
    @XmlElement(name="MyClass")
    MyClass myClass;

    @XmlElement(name="SomeOtherClass")
    List<SomeOtherClass> someOtherClasses = new ArrayList<>();
}
  1. MyClass
@XmlAccessorType(XmlAccessType.FIELD)
public class MyClass {
    @XmlID
    @XmlPath("@id")
    String id = UUID.randomUUID().toString();
    @XmlIDREF
    @XmlPath("SomeAttribute/@idref")
    SomeOtherClass someAttribute;
    @XmlElement(name = "Name")
    String name;
}
  1. SomeOtherClass
@XmlSeeAlso({DerivedClass.class})
@XmlAccessorType(XmlAccessType.FIELD)
public class SomeOtherClass {
    @XmlID
    @XmlPath("@id")
    String id = UUID.randomUUID().toString();
    @XmlElement(name="Name")
    String name;
}
  1. DerivedClass
@XmlType(name = "DerivedClass")
@XmlAccessorType(XmlAccessType.FIELD)
public class DerivedClass extends SomeOtherClass{
    String inDerived;
}

Now I could load and write this:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <MyClass id="64c80ae9-1d2b-4b79-98d1-0dfe0915f6a2">
      <SomeAttribute idref="335f0edb-6873-4acc-8c49-2c92cf6b3fcd"/>
      <Name>CDE</Name>
   </MyClass>
   <SomeOtherClass id="23a0dee0-fe06-45cc-a280-efb4a4bad345">
      <Name>ABC</Name>
   </SomeOtherClass>
   <SomeOtherClass id="335f0edb-6873-4acc-8c49-2c92cf6b3fcd" xsi:type="DerivedClass">
      <Name>FGH</Name>
      <inDerived>IJK</inDerived>
   </SomeOtherClass>
</root>