JAXB Unmarshalling派生类型

时间:2014-12-10 07:51:25

标签: java xml jaxb

根据以下程序,它会打印出我们正确的预期。 如果使用ClassA和ClassB类,这样的程序是否可以正确解组 相同的XmlRootElement名称?例如,如果它们都被定义为“typeA”......?可不可能是 可以用JAXB做那样的事情吗?

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.*;
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Date;

public class JaxbABCTest {
    public static void main(String[] args) throws JAXBException, UnsupportedEncodingException {
        final JAXBContext context = JAXBContext.newInstance(ABC.class);
        final Marshaller marshaller = context.createMarshaller();
        final Unmarshaller unmarshaller = context.createUnmarshaller();

        ABC class1 = new ClassA();
        ABC class2 = new ClassB();

        final ByteArrayOutputStream baosA = new ByteArrayOutputStream();
        final ByteArrayOutputStream baosB = new ByteArrayOutputStream();

        // Marshall to XML
        marshaller.marshal(class1, baosA);
        marshaller.marshal(class2, baosB);

        String xmlA = baosA.toString(Charset.defaultCharset().name());
        String xmlB = baosB.toString(Charset.defaultCharset().name());

        System.out.println(xmlA);
        System.out.println(xmlB);

        // Now attempt the reverse.
        Object unmarshalA = unmarshaller.unmarshal(new StringReader(xmlA));
        Object unmarshalB = unmarshaller.unmarshal(new StringReader(xmlB));

        System.out.println(unmarshalA.getClass());
        System.out.println(unmarshalB.getClass());
    }
}

@XmlTransient
@XmlSeeAlso({
    ClassA.class,
    ClassB.class
})
abstract class ABC {
    private int a;

    @XmlAttribute
    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }
}

@XmlRootElement(name = "typeA")
class ClassA extends ABC {
    private String b;
    private Date c;

    @XmlAttribute
    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }

    @XmlAttribute
    public Date getC() {
        return c;
    }

    public void setC(Date c) {
        this.c = c;
    }
}

@XmlRootElement(name = "typeB")
class ClassB extends ABC {
    private String b;
    private Date c;
    private boolean d;
    private float e;

    @XmlAttribute
    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }

    @XmlAttribute
    public Date getC() {
        return c;
    }

    public void setC(Date c) {
        this.c = c;
    }

    @XmlAttribute
    public boolean isD() {
        return d;
    }

    public void setD(boolean d) {
        this.d = d;
    }

    @XmlAttribute
    public float getE() {
        return e;
    }

    public void setE(float e) {
        this.e = e;
    }
}

1 个答案:

答案 0 :(得分:1)

对于简单的JAXB解组,(root)一个元素名称是指具有特定结构的元素,该结构映射到某个Java类。

当然,您可以定义一个包含A和B字段并集的类 - 只要两个类中出现的字段匹配即可。你必须有一些属性,让你决定它真正是两个“子类”中的哪一个。 (这与使用包含对属性或元素的存在(或甚至值)的测试的XPath表达式的精神相似。)

您也可以采用更精细的方法,在阅读XML之后将此元素解组,调查DOM树并根据检测到的内容创建JAXBContext。这将允许您使用与XML类型完全匹配的Java类型相同的元素名称。当然,必须有一个明确的标准,你必须编写基于原始DOM树数据进行分析的代码。