如何在unmarshal期间使用JAXB XmlAdapter处理XML IDREF的前向引用? [英] How to handle forward references of XML IDREF with JAXB XmlAdapter during unmarshal?
问题描述
在解组过程中,是否可以在JAXB XmlAdapter
中处理XML IDREF
元素的前向引用?例如,我有以下XML complexType
:
Is it possible to handle forward references of XML IDREF
elements in JAXB XmlAdapter
during the unmarshal process? For example, I have the following 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>
其中监护人
字段可以引用另一个文件中其他位置的人
-type元素。我正在编组时使用XmlAdapter,以便第一次对象进行编组时,它会被包含编组,并且此对象的任何后续出现都将通过引用进行编组。请参阅我的上一个问题。但是,由于我的XML实例文档的创建方式,在$ code> IDREF 之后,第一次出现 Person
元素它发生了。
where the guardian
field could reference another Person
-type element elsewhere in the document. I am currently using an XmlAdapter when marshalling so that the first time an object is marshalled, it is marshalled by containment, and any subsequent occurances of this object are marshalled by reference. See a previous question of mine. However, due to how my XML instance documents are created, the first occurrence of a Person
element could happen after an IDREF
to it occurs.
这是可能的吗?或者我需要以不同的方式处理这个问题?谢谢!
Is this something that is possible? Or do I need to approach this differently? Thanks!
推荐答案
我对你的答案相关问题我概述了 XmlAdapter
可用于实现一个用例,其中第一次出现的对象通过包含/嵌套进行编组,所有其他出现的内容都通过引用编组:
I have an answer to your related question I outlined how an XmlAdapter
could be used to implement the use case where the first occurrence of an object was marshalled via containment/nesting and all other occurrences were marshalled by reference:
- Can JAXB marshal by containment at first then marshal by @XmlIDREF for subsequent references?
选项#1 - @XmlID
/ @XmlIDREF
Option #1 - @XmlID
/@XmlIDREF
如果您的所有 Person
对象都是通过嵌套表示的,并且您想要引入一些基于关键字的关系你最好使用 @XmlID
将字段/属性标记为键,并使用 @XmlID
来映射a字段/属性作为外键。您的 Person
类看起来像:
If all of your Person
objects are all represented through nesting and you want to introduce some key based relationships then you are best of using @XmlID
to mark a field/property as the key, and @XmlID
to map a field/property as a foreign key. Your Person
class would look something like:
@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
Option #2 - Using XmlAdapter
如果您更新了 XmlAdapter
来自我的上一个答案为:
If you updated the XmlAdapter
from my previous answer to be:
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文档如下所示:
Then you will be able to unmarshal XML documents that look like the following where the reference happens first:
<?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>
这篇关于如何在unmarshal期间使用JAXB XmlAdapter处理XML IDREF的前向引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!