有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用JAXB,如何将attributedefined类型的XMLelement解组到基于该属性的对象?

我的应用程序正在接收编组为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
}

枚举可用于根据外部类路径查找对象的本地类:

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需要什么注释?我尝试在TargetedMessage类中的Baz字段上使用XmlAdapter,但ValueType参数始终为null

@XmlAttribute似乎也不起作用,因为class属性的值与其对应的本地类名不同


共 (1) 个答案

  1. # 1 楼答案

    你至少有两个选择。首先,可以将“class”属性映射到字符串枚举,并在TargetedMessage的#getBaz()方法中实现实例化逻辑。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,以便根据其“class”属性内容重命名“payload”元素。例如,它可以是“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>