EclipseLink Moxy unmarshall Коллекция с разными именами элементов

У меня есть класс, который содержит свойство ArrayList (SuperClass). Теперь я хочу удалить следующий XML-файл, который содержит разные имена элементов в этой коллекции, потому что это подклассы суперкласса. Есть ли способ сделать это с Мокси?

<?xml version="1.0" encoding="UTF-8"?>
<SmMessageSet xmlns:nav="urn:ccsds:recommendation:navigation:schema:ndmxml:R1.5"
    xmlns="urn:ccsds:recommendation:service_management:schema:sccs:R1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="urn:ccsds:recommendation:service_management:schema:sccs:R1.0 file:/C:/CCSDS-910.11-B-1_XML_schemas/CCSDS-910.11-B-1_XML_schemas/SmSchema-v1.0.0.xsd">
    <sccsSmVersionRef>sccsSmVersionRef0</sccsSmVersionRef>
    <smSource>smSource0</smSource>
    <smDestination>smDestination0</smDestination>
    <serviceAgreementRef>serviceAgreementRef0</serviceAgreementRef>
    <smMessages>
        <querySpaceCommunicationServiceProfileFailedReturn>
            <messageSequenceNumber>50</messageSequenceNumber>
            <messageTimestamp>2006-05-04T18:13:51.0</messageTimestamp>
            <invocationMessageSequenceNumber>50</invocationMessageSequenceNumber>
            <spaceCommunicationServiceProfileRef>spaceCommunicationServiceProfileRef0
            </spaceCommunicationServiceProfileRef>
            <qscspError>
                <erroredItem>erroredItem0</erroredItem>
                <diagnostic>operation timeout</diagnostic>
            </qscspError>
            <qscspError>
                <erroredItem>erroredItem1</erroredItem>
                <diagnostic>operation timeout</diagnostic>
            </qscspError>
        </querySpaceCommunicationServiceProfileFailedReturn>
        <createUserAccountInvocation1>
            <messageSequenceNumber>50</messageSequenceNumber>
            <messageTimestamp>2006-05-04T18:13:51.0</messageTimestamp>
            <username>createdUser</username>
            <password>createdPassword</password>
            <firstname>Test</firstname>
            <lastname>User</lastname>
            <email>test.user@host.de</email>
            <role>SCHEDULING_OFFICER</role>
            <superuser>0</superuser>
        </createUserAccountInvocation1>
    </smMessages>
</SmMessageSet>

QuerySpaceCommunicationServiceProfileFailedReturn и createUserAccountInvocation находятся в моих подклассах объектной модели java базового класса SmMessage, который содержится классом SmMessageSet в, как описано выше, ArrayList классов SmMessage.

Я также хотел бы не изменять текущую структуру XML (т.е. создать элемент-оболочку вокруг SmMessages в файле XML).

Любая помощь будет оценена:)

1 ответ

Решение

Вы могли бы сделать следующее используя @XmlElementWrapper а также @XmlElementRef:

Модель Java

SmMessageSet

Вы можете использовать @XmlElementWrapper аннотация для добавления группирующего элемента вокруг коллекции (см.: http://blog.bdoughan.com/2010/09/jaxb-collection-properties.html). Вы также можете использовать @XmlElementRef аннотация для моделирования имени элемента в качестве индикатора наследования (группы подстановок в XML-схеме см. по адресу: http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-substitution.html).

package forum20745762;

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement(name="SmMessageSet")
@XmlAccessorType(XmlAccessType.FIELD)
public class SmMessageSet {

    @XmlElementWrapper
    @XmlElementRef
    private List<SmMessage> smMessages;

}

SmMessage

JAXB / MOXy не будет автоматически извлекать все подклассы класса, поэтому вы можете использовать @XmlSeeAlso аннотация, чтобы они втянули.

package forum20745762;

import javax.xml.bind.annotation.XmlSeeAlso;

@XmlSeeAlso({CreateUserAccountInvocation.class, QuerySpaceCommunicationServiceProfileFailedReturn1.class})
public class SmMessage {

}

CreateUserAccountInvocation

По одному на каждый из подклассов, которые нужно аннотировать @XmlRootElement, Это имя элемента, которое @XmlElementRef аннотация будет соответствовать на.

package forum20745762;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class CreateUserAccountInvocation extends SmMessage {

}

QuerySpaceCommunicationServiceProfileFailedReturn1

package forum20745762;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class QuerySpaceCommunicationServiceProfileFailedReturn1 extends SmMessage {

}

Пакет-инфо

Мы будем использовать уровень пакета @XmlSchema аннотация для сопоставления пространств имен (см.: http://blog.bdoughan.com/2010/08/jaxb-namespaces.html).

@XmlSchema(
    namespace="urn:ccsds:recommendation:service_management:schema:sccs:R1.0",
    elementFormDefault=XmlNsForm.QUALIFIED
)
package forum20745762;

import javax.xml.bind.annotation.*;

Демонстрационный код

демонстрация

Следующий демонстрационный код прочитает XML из вашего вопроса, а затем выпишет его обратно.

package forum20745762;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(SmMessageSet.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum20745762/input.xml");
        SmMessageSet smMessageSet = (SmMessageSet) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(smMessageSet, System.out);
    }

}

Выход

Вывод ниже соответствует только подмножеству вашего XML-документа, который я сопоставил:

<?xml version="1.0" encoding="UTF-8"?>
<SmMessageSet xmlns="urn:ccsds:recommendation:service_management:schema:sccs:R1.0">
   <smMessages>
      <querySpaceCommunicationServiceProfileFailedReturn1/>
      <createUserAccountInvocation/>
   </smMessages>
</SmMessageSet>
Другие вопросы по тегам