Как обрабатывать прямые ссылки на XML IDREF с помощью JAXB XmlAdapter во время демаршала?

Можно ли обрабатывать прямые ссылки XML IDREF элементы в JAXB XmlAdapter во время процесса маршала? Например, у меня есть следующий 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 с этим происходит.

Это то, что возможно? Или мне нужно подходить к этому по-другому? Спасибо!

1 ответ

Решение

У меня есть ответ на ваш связанный вопрос, я обрисовал, как XmlAdapter может быть использован для реализации варианта использования, где первое вхождение объекта было маршалировано с помощью локализации / вложенности, а все другие вхождения были маршалированы посредством ссылки:

Опция 1 - @XmlID / @XmlIDREF

Если все ваши Person все объекты представлены через вложение, и вы хотите ввести некоторые ключевые отношения, тогда вам лучше всего использовать @XmlID пометить поле / свойство как ключ и @XmlID сопоставить поле / свойство как внешний ключ. Ваш Person класс будет выглядеть примерно так:

@XmlAccessorType(XmlAccessType.FIELD)
public class Person {

    @XmlID
    private String id;

    @XmlIDREF
    private Person guardian;
}

Для дополнительной информации

Вариант № 2 - Использование XmlAdapter

Если вы обновили 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>
Другие вопросы по тегам