Используя JAXB, как я могу демонтировать XML-элемент с типом, определенным атрибутом, в объект, основанный на этом атрибуте? - PullRequest
0 голосов
/ 29 мая 2018

Мое приложение получает полезную нагрузку объекта, упорядоченную в XML, например:

<targetedMessage>
   <sender>external application</sender>
   <payload class="class.path.from.external.application.Foo">
      <id>1</id>
   </payload>
</targetedMessage>

Класс полезной нагрузки (например, Foo) может быть одним из нескольких классов с общей структурой наследования.

Каждый из них имеет соответствующий класс в моем приложении:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Foo extends Baz {
    private Long id;
    //other fields, getters, setters
}

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Bar extends Baz {
    private Long id;
    // other fields, getters, setters
}

, и enum может использоваться для поиска локального класса объекта на основе стороннего пути к классам:

public enum ForeignClass {

FOO("class.path.from.external.application.Foo", Foo.class),
BAR("class.path.from.external.application.Bar", Bar.class);

public static getClassFromForeignClassPath(String foreignClassPath) {
  // return class
}

У меня также есть класс TargetedMessage для сбора мета-информации, касающейся самого сообщения:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class TargetedMessage {
    private String sender;
    private Baz baz;
}

Какая аннотация потребуется для правильной разборки XML-кода?Я пытался использовать XmlAdapter для поля Baz в классе TargetedMessage, но параметр ValueType всегда равен нулю.

@XmlAttribute не выглядит так, как будто он может работать, так как значения атрибутов class не совпадают с их соответствующими именами локальных классов.

1 Ответ

0 голосов
/ 29 мая 2018

У вас есть как минимум два варианта.Во-первых, вы можете сопоставить атрибут «class» с перечислением строк и реализовать логику реализации в методе #getBaz () вашего TargetedMessage.XSD будет выглядеть так, как показано ниже (при необходимости переименуйте типы):

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/XMLSchema" xmlns:tns="http://www.example.org/XMLSchema" elementFormDefault="qualified">

    <include schemaLocation=""></include>

    <simpleType name="simpleTypeClass">
        <restriction base="string">
            <enumeration value="class.path.from.external.application.Foo"></enumeration>
            <enumeration value="class.path.from.external.application.Bar"></enumeration>
        </restriction>
    </simpleType>

    <complexType name="payloadType">
        <sequence>
            <element name="id" type="string"></element>
        </sequence>
        <attribute name="class" type="tns:simpleTypeClass"></attribute>
    </complexType>

    <complexType name="targetedMessageType">
        <sequence>
            <element name="sender" type="string"></element>
            <element name="payload" type="tns:payloadType"></element>
        </sequence>
    </complexType>
</schema>

Во-вторых, вы можете преобразовать исходный XML-код, так как элемент «полезной нагрузки» переименовывается в соответствии с его содержимым атрибута «класс».Например, это могут быть «payloadFoo», «payloadBar» и т. Д. Затем вы можете отобразить его непосредственно на нужные классы.Соответствующий XSD показан ниже.

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/XMLSchema" xmlns:tns="http://www.example.org/XMLSchema" elementFormDefault="qualified">

    <simpleType name="simpleTypeFoo">
        <restriction base="string">
            <enumeration value="class.path.from.external.application.Foo"></enumeration>
        </restriction>
    </simpleType>

    <simpleType name="simpleTypeBar">
        <restriction base="string">
            <enumeration value="class.path.from.external.application.Bar"></enumeration>
        </restriction>
    </simpleType>

    <complexType name="payloadTypeFoo">
        <sequence>
            <element name="id" type="string"></element>
        </sequence>
        <attribute name="class" type="tns:simpleTypeFoo"></attribute>
    </complexType>

    <complexType name="payloadTypeBar">
        <sequence>
            <element name="id" type="string"></element>
        </sequence>
        <attribute name="class" type="tns:simpleTypeBar"></attribute>
    </complexType>

    <complexType name="payloadType">
        <choice>
            <element name="payloadFoo" type="tns:payloadTypeFoo" minOccurs="0" maxOccurs="1"></element>
            <element name="payloadBar" type="tns:payloadTypeBar" minOccurs="0" maxOccurs="1"></element>
        </choice>
    </complexType>

    <complexType name="targetedMessageType">
        <sequence>
            <element name="sender" type="string"></element>
            <element name="payload" type="tns:payloadType"></element>
        </sequence>
    </complexType>
</schema>
...