I have an answer to your related question . I talked about how the XmlAdapter can be used to implement a use case when the first occurrence of an object was distributed via containment / nesting and all other occurrences were ordered by reference:
Option # 1 - @XmlID / @XmlIDREF
If all your Person objects are represented via nesting, and you want to introduce some key-based relationships, it is best to use @XmlID to designate the field / property as the key and @XmlID to display the field / property as a foreign key. Your Person class will look something like this:
@XmlAccessorType(XmlAccessType.FIELD) public class Person { @XmlID private String id; @XmlIDREF private Person guardian; }
Additional Information
Option # 2 - Using the XmlAdapter
If you updated the XmlAdapter from my previous answer :
package forum7587095; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.adapters.XmlAdapter; public class PhoneNumberAdapter extends XmlAdapter<PhoneNumberAdapter.AdaptedPhoneNumber, PhoneNumber>{ private List<PhoneNumber> phoneNumberList = new ArrayList<PhoneNumber>(); private Map<String, PhoneNumber> phoneNumberMap = new HashMap<String, PhoneNumber>(); @XmlSeeAlso(AdaptedWorkPhoneNumber.class) @XmlType(name="phone-number") public static class AdaptedPhoneNumber { @XmlAttribute public String id; public String number; public AdaptedPhoneNumber() { } public AdaptedPhoneNumber(PhoneNumber phoneNumber) { id = phoneNumber.getId(); number = phoneNumber.getNumber(); } public PhoneNumber getPhoneNumber() { PhoneNumber phoneNumber = new PhoneNumber(); phoneNumber.setId(id); phoneNumber.setNumber(number); return phoneNumber; } } @XmlType(name="work-phone-number") public static class AdaptedWorkPhoneNumber extends AdaptedPhoneNumber { public String extension; public AdaptedWorkPhoneNumber() { } public AdaptedWorkPhoneNumber(WorkPhoneNumber workPhoneNumber) { super(workPhoneNumber); extension = workPhoneNumber.getExtension(); } @Override public WorkPhoneNumber getPhoneNumber() { WorkPhoneNumber phoneNumber = new WorkPhoneNumber(); phoneNumber.setId(id); phoneNumber.setNumber(number); phoneNumber.setExtension(extension); return phoneNumber; } } @Override public AdaptedPhoneNumber marshal(PhoneNumber phoneNumber) throws Exception { AdaptedPhoneNumber adaptedPhoneNumber; if(phoneNumberList.contains(phoneNumber)) { if(phoneNumber instanceof WorkPhoneNumber) { adaptedPhoneNumber = new AdaptedWorkPhoneNumber(); } else { adaptedPhoneNumber = new AdaptedPhoneNumber(); } adaptedPhoneNumber.id = phoneNumber.getId(); } else { if(phoneNumber instanceof WorkPhoneNumber) { adaptedPhoneNumber = new AdaptedWorkPhoneNumber((WorkPhoneNumber)phoneNumber); } else { adaptedPhoneNumber = new AdaptedPhoneNumber(phoneNumber); } phoneNumberList.add(phoneNumber); } return adaptedPhoneNumber; } @Override public PhoneNumber unmarshal(AdaptedPhoneNumber adaptedPhoneNumber) throws Exception { PhoneNumber phoneNumber = phoneNumberMap.get(adaptedPhoneNumber.id); if(null != phoneNumber) { if(adaptedPhoneNumber.number != null) { phoneNumber.setNumber(adaptedPhoneNumber.number); } return phoneNumber; } phoneNumber = adaptedPhoneNumber.getPhoneNumber(); phoneNumberMap.put(phoneNumber.getId(), phoneNumber); return phoneNumber; } }
You can then decouple the XML documents, which look like this, where the link first occurs:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <customer> <phone-number id="A"/> <phone-number id="B"> <number>555-BBBB</number> </phone-number> <phone-number id="A"> <number>555-AAAA</number> </phone-number> <phone-number xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="work-phone-number" id="W"> <number>555-WORK</number> <extension>1234</extension> </phone-number> <phone-number xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="work-phone-number" id="W"/> </customer>
source share