简体   繁体   English

使用JAXB,如何将具有属性定义类型的XMLelement解组到基于该属性的对象?

[英]Using JAXB, how can I unmarshal an XMLelement with an attribute-defined type to an object based on that attribute?

My application is receiving an object payload marshalled into XML, eg: 我的应用程序正在接收编入XML的对象有效负载,例如:

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

The payload class (Foo in example) can be one of a number of classes with a common inheritance structure. 有效负载类(例如,Foo)可以是具有公共继承结构的多个类之一。

Each has a corresponding class in my application: 每个应用程序中都有一个对应的类:

@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
}

and an enum can be used to find the local class of the object based on the foreign classpath: 枚举可用于根据外部类路径查找对象的本地类:

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
}

I also have a TargetedMessage class to capture meta info regarding the message itself: 我还有一个TargetedMessage类来捕获有关消息本身的元信息:

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

What annotation would be required to unmarshal the XML properly? 要正确解组XML,需要什么注释? I've tried using an XmlAdapter on the Baz field in the TargetedMessage class, but the ValueType parameter is always null. 我尝试在TargetedMessage类的Baz字段上使用XmlAdapter,但ValueType参数始终为null。

@XmlAttribute doesn't appear as though it could work either, as the value of the class attributes are not the same as their corresponding local class names. 由于class属性的值与其对应的本地类名不同,因此@XmlAttribute似乎也不起作用。

You have at least two options. 您至少有两个选择。 First, you can map the "class" attribute to an enumeration of strings and implement instantiation logic in the #getBaz() method of your TargetedMessage. 首先,您可以将“ class”属性映射到字符串枚举,并在TargetedMessage的#getBaz()方法中实现实例化逻辑。 The XSD would be as shown below (rename types as necessary): 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>

Second, you can transform your initial XML, so as the "payload" element is renamed according to its "class" attribute content. 其次,您可以转换您的初始XML,以便根据其“类”属性内容重命名“有效载荷”元素。 For example, it could be "payloadFoo", "payloadBar", etc. Then, you can map it directly to the desired classes. 例如,它可以是“ payloadFoo”,“ payloadBar”等。然后,您可以将其直接映射到所需的类。 The respective XSD is shown below. 相应的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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM