在解组过程中是否可以在JAXB XmlAdapter中处理XML IDREF元素的前向引用?例如,我有以下XML complexType:
<xs:complexType name="person"> <xs:complexContent> <xs:sequence> <xs:element name="dateOfBirth" type="xs:dateTime" minOccurs="0"/> <xs:element name="firstName" type="xs:string" minOccurs="0"/> <xs:element name="gender" type="xs:string" minOccurs="0"/> <xs:element name="guardian" type="xs:IDREF" minOccurs="0"/> <xs:element name="homePhone" type="xs:string" minOccurs="0"/> <xs:element name="lastName" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:complexContent> </xs:complexType>
监护人字段可以在文档中的其他位置引用另一个Person类型元素.我正在编组时使用XmlAdapter,以便第一次对象进行编组时,它会被包含编组,并且此对象的任何后续出现都将通过引用进行编组.请参阅上一个mine的问题.但是,由于我的XML实例文档的创建方式,Person元素的第一次出现可能发生在IDREF发生之后.
这是可能的吗?或者我需要以不同的方式处理这个问题?谢谢!
我对你的
related question有一个答案我概述了如何使用XmlAdapter来实现一个用例,其中第一次出现的对象是通过包含/嵌套编组的,所有其他出现都是通过引用编组的:
> Can JAXB marshal by containment at first then marshal by @XmlIDREF for subsequent references?
选项#1 – @ XmlID / @ XmlIDREF
如果您的所有Person对象都通过嵌套表示,并且您想要引入一些基于键的关系,那么您最好使用@XmlID将字段/属性标记为键,将@XmlID用于将字段/属性标记为外部键.您的Person类看起来像:
@XmlAccessorType(XmlAccessType.FIELD) public class Person { @XmlID private String id; @XmlIDREF private Person guardian; }
了解更多信息
> http://blog.bdoughan.com/2010/10/jaxb-and-shared-references-xmlid-and.html
选项#2 – 使用XmlAdapter
如果您将我的previous answer中的XmlAdapter更新为:
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; } }
然后,您将能够解组首先出现引用的XML文档:
<?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>