update – see edit at the bottom
IDRefs/keyrefs seem to be possible in JAXB annotations, but the ref ends up being element text.
I would like the ref to be an attribute of an element.
For example, given this object model:
@XmlType
public class Employee {
@XmlID
@XmlAttribute
String name;
@XmlAttribute
int years;
@XmlAttribute
String foo;
}
@XmlType
public class Office {
@XmlAttribute
String name;
@XmlElementWrapper
@XmlElement(name = "employee")
List<Employee> employees;
}
@XmlRootElement
public class Company {
@XmlElementWrapper
@XmlElement(name = "office")
List<Office> offices;
@XmlElementWrapper
@XmlElement(name = "employee")
List<Employee> employees;
}
I would like the externalized xml format to end up looking like this:
<company>
<offices>
<office name="nyc">
<employees>
<!--*** id ref to employee name ***-->
<employee ref="alice"/>
<employee ref="bob"/>
</employees>
</office>
<office name="sf">
<employees>
<employee ref="connie"/>
<employee ref="daphne"/>
</employees>
</office>
</offices>
<employees>
<!-- *** name is the id *** -->
<employee name="alice" years="3" foo="bar"/>
<employee name="bob" years="3" foo="bar"/>
<employee name="connie" years="3" foo="bar"/>
<employee name="daphne" years="3" foo="bar"/>
</employees>
</company>
Instead, the best I can do is this (with the annotations listed above in the java code):
<company>
<offices>
<office name="nyc">
<employees>
<employee>alice</employee>
<employee>bob</employee>
</employees>
</office>
<office name="sf">
<employees>
<employee>connie</employee>
<employee>daphne</employee>
</employees>
</office>
</offices>
<employees>
<employee name="alice" years="3" foo="bar"/>
<employee name="bob" years="3" foo="bar"/>
<employee name="connie" years="3" foo="bar"/>
<employee name="daphne" years="3" foo="bar"/>
</employees>
</company>
Is there a way I can force the idref value to be an attribute of employee, rather than element body text? I know I can do this with an XML Schema, but I’d like to stick to annotations if at all possible.
Thank you.
Edit The solution by Torious below almost works, but it doesn’t quite work under some circumstances.
unmarshalling fails if the “offices” elements come before (in the xml file) the “employee” elements that the office references. The employee references are not found, and the EmployeeRef wrapper has a null employee object. If the “employee” are first, it works.
This wouldn’t be so much of a problem, but the marshal method will put “offices” first, so that trying to unmarshal what has just been marshalled fails.
Edit 2 comment in Torious’ answer solves the ordering problem.
The solution is to use an
XmlAdapterwhich wraps anEmployeein an instance of a new type,EmployeeRef, which specifies how to map the XML id ref:Good luck.