简体   繁体   English

基于子元素值的JAXB Unmarshal子类

[英]JAXB Unmarshal subclass based in child element value

I need to mapper the follow xml based in the value of element type. 我需要根据元素类型的值映射以下xml。 The BaseEntity superclass have the common elements to the Machine and Robot classes. BaseEntity超类具有Machine和Robot类的公共元素。 Each subclasse have different elements... The XML structure is fixed and I can't change it. 每个子类都有不同的元素... XML结构是固定的,我无法更改。 Each entry element should be mapped to the respective class, entry/type=Machine should be mapped to subclass Machine and so on... 每个entry元素应映射到各自的类,entry / type = Machine应映射到Machine的子类,依此类推...

It is possible in JAXB? 在JAXB中可以吗? How can I implement this? 我该如何实施? Any suggestion? 有什么建议吗?

<root>
    <entries>
        <entry>
            <name>RTM</name>
            <description>RealTime Machine</description>
            <code>RTM1</code>
            <type>Machine</type>
        </entry>
        <entry>
            <name>RTM</name>
            <description>RealTime Machine</description>
            <type>Robot</type>
            <serial>RS123<serial>
        </entry>
    </entries>
</root>

public abstract class BaseEntity {
    private String name;
    private String description;
}
public class Machine extends BaseEntity{
    private String code;
}
public class Robot extends BaseEntity{
    private String serial;
}

Unfortunately your XML layout is really bad. 不幸的是,您的XML布局确实很糟糕。 When the JAXB parser enters an entry node, it can't tell by the node whether it is a machine oder robot. 当JAXB解析器进入一个入口节点时,该节点无法分辨它是否是机器机器人。 So it must guess which type to use for unmarshlling. 因此,它必须猜测要用于编组的类型。 Normally you would use the type as node name (1) or provide an attribute with the type parameter (2). 通常,您将使用类型作为节点名称(1)或为属性提供类型参数(2)。

1: 1:

<entries>
    <machine>...</machine>
    <robot>...</robot>
</entries>

2: 2:

<entries>
    <entry type="machine">...</entry>
    <entry type="robot">...</entry>
</entries>

So my solution to your problem is as frankenstein as your XML. 因此,我对您的问题的解决方案与您的XML一样,就像科学怪人一样。

Have an adapted class, which extends the base class and has all the attributes of the available subclasses: 具有适应的类,该类扩展了基类并具有可用子类的所有属性:

@XmlRootElement(name = "ENTRY")
@XmlAccessorType(XmlAccessType.FIELD)
public class AdaptedBaseEntry extends BaseEntry
{


    @XmlElement(name = "CODE", required = false)
    public String code;

    @XmlElement(name = "SERIAL", required = false)
    public String serial;

    public AdaptedBaseEntry()
    {
        super();
    }

    public AdaptedBaseEntry(BaseEntry entry)
    {
        super(entry.type, entry.description, entry.name);
        if (entry instanceof Machine)
        {
            this.code = ((Machine) entry).code;
        } else if (entry instanceof Robot)
        {
            this.serial = ((Robot) entry).serial;
        }
    }

}

Use an XmlAdapter to bind the adapter class to XML and vice versa: 使用XmlAdapter将适配器类绑定到XML,反之亦然:

public class BaseEntryAdapter extends XmlAdapter<AdaptedBaseEntry, BaseEntry>
{

    @Override
    public BaseEntry unmarshal(AdaptedBaseEntry v) throws Exception
    {
        switch (v.type)
        {
        case Machine:
            return new Machine(v.name, v.description, v.code);
        case Robot:
            return new Robot(v.name, v.description, v.serial);
        default:
            return null;
        }
    }

    @Override
    public AdaptedBaseEntry marshal(BaseEntry v) throws Exception
    {
        return new AdaptedBaseEntry(v);
    }

}

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

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