Jaxb可以使用一个ValueObject在Unmarshalling By XmlAdapter中映射不同的xml

时间:2013-05-27 12:25:59

标签: jaxb unmarshalling

我有两个Xml文件 一个是

<A>
    <B>xxx</B>
</A>

另一个是

<A>
<B>
<C>xxx</C>
</B>
</A>

对于B元素,我创建了一个ValueObject字段String。 另外,我为XmlAdapter<Object, ValueObject>元素创建了一个boolean属性, 当你解组时我可以B 所以当尝试从setAdapter(BXmlAdapter.class, new BxmlAdaper(boolean))转换时尝试转换为BxmlAdaper时,我可以告诉String

如果元素ValueObject具有第一个xml的属性Bxsi:type="prefix:ValueObject"为第二个xsi:type="xs:string"。它运作良好。我可以用一个解组所有这些 xml。 但是没有ValueObject,我在xsi:type unmarshall方法中得到了org.apache.xerces.dom.ElementNSImpl的实例。 我该如何解决这个案子。

这两个XmlAdapter文件也有两个模式文件,所以我想也许我可以使用xml文件 告诉JAXB schema元素的类型是什么。但似乎JAXB只使用模式文件来检查。 我想念一下吗?

这是samle代码 A类

B

B类

package example.dto;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import example.adapter.BXmlAdapter;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class A {

    @XmlJavaTypeAdapter(BXmlAdapter.class)
    private B b;

    public B getB() {
        return b;
    }

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

包信息

    package example.dto;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="B")
public class B {

    private String test;

    public String getTest() {
        return test;
    }

    public void setTest(String test) {
        this.test = test;
    }

}

jaxb.in​​dex

@javax.xml.bind.annotation.XmlSchema(elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, namespace = "http://test/test", xmlns = @javax.xml.bind.annotation.XmlNs(prefix = "test", namespaceURI = "http://test/test"))
package example.dto;

BXmlAdapter.java

A
B

A1.xml

    package example.adapter;

import javax.xml.bind.annotation.adapters.XmlAdapter;

import example.dto.B;

public class BXmlAdapter extends XmlAdapter<Object, B> {

    private final boolean flg;

    public BXmlAdapter() {
        this.flg = false;
    }

    public BXmlAdapter(boolean flg) {
        this.flg = flg;
    }

    @Override
    public Object marshal(B v) throws Exception {
        if (flg) {
            return v.getTest();
        } else {
            return v;
        }
    }

    @Override
    public B unmarshal(Object v) throws Exception {
        if (flg) {
            B b = new B();
            b.setTest((String) v);
            return b;
        } else {
            return (B) v;
        }
    }
}

A2.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<test:a xmlns:test="http://test/test">
    <test:b xsi:type="test:B" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <test:test>xxxx</test:test>
    </test:b>
</test:a>

Xml2JavaObject.java

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<test:a xmlns:test="http://test/test">
    <test:b xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema">xxxx2</test:b>
</test:a>

上面的代码工作正常, 但是如果在xml文件中没有xsi:type。 这是行不通的。 BXmlAdapter中unmarshal方法的参数是。的实例 ElementNSImpl ....

我的问题是

  1. 如何处理ElementNSImpl实例

  2. 如果xml文件中没有xsi:type,则JAXB可以使用一个ValueObject处理不同的xml文件

  3. xsi:type也在模式文件中。 JAXB可以使用模式文件来决定类型吗?看来JAXB 只是在验证中使用模式文件。

  4. 由于

1 个答案:

答案 0 :(得分:0)

我发现使用@XmlMixed和XmlAdapter来解决这个问题有点难看。 这是代码 A级

package example.dto;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import example.adapter.BXmlAdapter;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class A {

    @XmlJavaTypeAdapter(value=BXmlAdapter.class)
    private B b;

    public B getB() {
        return b;
    }

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

}

B级

package example.dto;

public class B {

    private String test;

    public String getTest() {
        return test;
    }

    public void setTest(String test) {
        this.test = test;
    }

}

类XmlB

package example.dto;

import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlMixed;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "B")
public class XmlB {

    @XmlMixed
    private List<Object> tempElement;

    private String test;

    public String getTest() {
        return test;
    }

    public void setTest(String test) {
        this.test = test;
    }

    public List<Object> getTempElement() {
        return tempElement;
    }

    public void setTempElement(List<Object> tempElement) {
        this.tempElement = tempElement;
    }

}

package-info.java

@javax.xml.bind.annotation.XmlSchema(elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, namespace = "http://test/test", xmlns = @javax.xml.bind.annotation.XmlNs(prefix = "test", namespaceURI = "http://test/test"))
package example.dto;

jaxb.in​​dex

A
XmlB

A1.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<test:a xmlns:test="http://test/test">
    <test:b>
        <test:test>xxxx</test:test>
    </test:b>
</test:a>

A2.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<test:a xmlns:test="http://test/test">
    <test:b>xxxx2</test:b>
</test:a>

BXmlAdapter.java

package example.adapter;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.adapters.XmlAdapter;

import example.dto.B;
import example.dto.XmlB;

public class BXmlAdapter extends XmlAdapter<XmlB, B> {

    private final boolean flg;

    public BXmlAdapter() {
        this.flg = false;
    }

    public BXmlAdapter(boolean flg) {
        this.flg = flg;
    }

    @Override
    public XmlB marshal(B v) throws Exception {

        XmlB xmlb = new XmlB();

        if (flg) {
            List<Object> tempElement = new ArrayList<>();
            tempElement.add(v.getTest());
            xmlb.setTempElement(tempElement);
        } else {
            xmlb.setTest(v.getTest());
        }

        return xmlb;
    }

    @Override
    public B unmarshal(XmlB v) throws Exception {
        B b = new B();
        if (flg) {
            if (v.getTempElement() != null && v.getTempElement().size() == 1) {
                b.setTest((String) v.getTempElement().get(0));
            }
        } else {
            b.setTest(v.getTest());
        }

        return b;
    }

}

JavaObject2Xml.java

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import example.adapter.BXmlAdapter;
import example.dto.A;
import example.dto.B;

public class JavaObject2Xml {

    public static void main(String[] args) throws ClassNotFoundException {

        A a1 = new A();
        A a2 = new A();
        B b1 = new B();
        B b2 = new B();
        b1.setTest("xxxx");
        b2.setTest("xxxx2");

        a1.setB(b1);
        a2.setB(b2);

        try {

            File fileA1 = new File("D:\\jaxb\\A1.xml");

            JAXBContext jaxbContext = JAXBContext.newInstance("example.dto");
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

            // output pretty printed
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            jaxbMarshaller.setAdapter(BXmlAdapter.class, new BXmlAdapter(false));
            jaxbMarshaller.marshal(a1, fileA1);

        } catch (JAXBException e) {
            e.printStackTrace();
        }

        try {

            File fileA2 = new File("D:\\jaxb\\A2.xml");

            JAXBContext jaxbContext = JAXBContext.newInstance("example.dto");
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

            // output pretty printed
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            jaxbMarshaller.setAdapter(BXmlAdapter.class, new BXmlAdapter(true));
            jaxbMarshaller.marshal(a2, fileA2);

        } catch (JAXBException e) {
            e.printStackTrace();
        }

    }

}

Xml2JavaObject.java

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.xml.sax.SAXException;

import example.adapter.BXmlAdapter;
import example.dto.A;

public class Xml2JavaObject {

    public static void main(String[] args) throws ClassNotFoundException,
            SAXException {
        try {
            File file = new File("D:\\jaxb\\A1.xml");
            JAXBContext jaxbContext = JAXBContext.newInstance("example.dto");
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            jaxbUnmarshaller.setAdapter(BXmlAdapter.class, new BXmlAdapter(false));
            A a = (A) jaxbUnmarshaller.unmarshal(file);
            System.out.println(a.getB().getTest());
        } catch (JAXBException e) {
            e.printStackTrace();
        }

        try {
            File file = new File("D:\\jaxb\\A2.xml");
            JAXBContext jaxbContext = JAXBContext.newInstance("example.dto");
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            jaxbUnmarshaller.setAdapter(BXmlAdapter.class,new BXmlAdapter(true));
            A a = (A) jaxbUnmarshaller.unmarshal(file);
            System.out.println(a.getB().getTest());
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

}

上面的代码可以帮助我使用一组Classes来处理2个或更多xml文件