繁体   English   中英

基于子元素值的JAXB Unmarshal子类

[英]JAXB Unmarshal subclass based in child element value

我需要根据元素类型的值映射以下xml。 BaseEntity超类具有Machine和Robot类的公共元素。 每个子类都有不同的元素... XML结构是固定的,我无法更改。 每个entry元素应映射到各自的类,entry / type = Machine应映射到Machine的子类,依此类推...

在JAXB中可以吗? 我该如何实施? 有什么建议吗?

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

不幸的是,您的XML布局确实很糟糕。 当JAXB解析器进入一个入口节点时,该节点无法分辨它是否是机器机器人。 因此,它必须猜测要用于编组的类型。 通常,您将使用类型作为节点名称(1)或为属性提供类型参数(2)。

1:

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

2:

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

因此,我对您的问题的解决方案与您的XML一样,就像科学怪人一样。

具有适应的类,该类扩展了基类并具有可用子类的所有属性:

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

}

使用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