如何在解组期间使用 JAXB XmlAdapter 处理 XML IDREF 的前向引用? [英] How to handle forward references of XML IDREF with JAXB XmlAdapter during unmarshal?

查看:36
本文介绍了如何在解组期间使用 JAXB XmlAdapter 处理 XML IDREF 的前向引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以在解组过程中处理 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>

其中 guardian 字段可以引用文档中其他位置的另一个 Person 类型元素.我目前在编组时使用 XmlAdapter,以便第一次编组对象时,它由包含编组,并且此对象的任何后续出现都通过引用编组.请参阅我的的上一个问题.但是,由于我的 XML 实例文档的创建方式,Person 元素的第一次出现可能发生在 IDREF 之后.

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:

选项 #1 - @XmlID/@XmlIDREF

如果你所有的 Person 对象都是通过嵌套表示的,并且你想引入一些基于键的关系,那么你最好使用 @XmlID 来标记一个字段/属性作为键,@XmlID 将字段/属性映射为外键.你的 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;
}

了解更多信息

选项 #2 - 使用 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>

这篇关于如何在解组期间使用 JAXB XmlAdapter 处理 XML IDREF 的前向引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆