1

我有两个 Xml 文件,一个是

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

另一个是

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

对于B元素,我ValueObject用一个String字段做了一个。另外,我用元素XmlAdapter<Object, ValueObject>boolean属性制作了 a ,并且在解组时可以,所以我可以判断何时尝试从 a 转换,何时尝试从 a 转换。BsetAdapter(BXmlAdapter.class, new BxmlAdaper(boolean))BxmlAdaperStringValueObject

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

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

这是 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(BXmlAdapter.class)
    private B b;

    public B getB() {
        return b;
    }

    public void setB(B b) {
        this.b = 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;
    }

}

包信息

@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
B

BXmlAdapter.java

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

A1.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>

A2.xml

<?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>

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

    }

}

上面的代码可以正常工作,但是如果 xml 文件中没有 xsi:type。这没用。BXmlAdapter 中 unmarshal 方法的参数是 ElementNSImpl 的一个实例......

我的问题是

  1. 如何处理 ElementNSImpl 实例

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

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

谢谢

4

1 回答 1

0

我发现使用@XmlMixed And 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;
    }

}

包信息.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();
        }
    }

}

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

于 2013-05-29T04:25:24.037 回答