首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于任意XML的JAXB @XmlAdapter

用于任意XML的JAXB @XmlAdapter
EN

Stack Overflow用户
提问于 2013-08-16 11:14:58
回答 1查看 8.1K关注 0票数 6

我有一个从XmlAdapter返回的XmlAdapter,用于定制@XmlElement,我希望将它作为JAXB对象的一部分,作为任意的@XmlElement(我知道我必须手工制作XSD)。然而,JAXB抱怨

代码语言:javascript
复制
org.w3c.dom.Element is an interface, and JAXB can't handle interfaces.

显然,w3c XML类型是不支持Java类型,这是一个遗憾。但更重要的是,当我使用明显受支持的javax.xml.transform.Result时,我会得到相同的错误。

如何将任意XML元素作为元素包含在JAXB中?

注意:根据https://forums.oracle.com/thread/1668210,我也尝试过

代码语言:javascript
复制
MessageFactory factory = MessageFactory.newInstance();
message = factory.createMessage();          
SOAPElement element = message.getSOAPBody().addDocument(doc);

但这也带来了同样的错误。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-08-20 17:45:15

TL;DR

只要将值类型指定为XmlAdapter (而不是Element),就可以有一个将域对象转换为org.w3c.dom.Element实例的Object

下面是一个完整的例子。

XmlAdapter

类型为java.lang.Object的字段/属性将将未知内容保留为DOM节点。通过将XmlAdapter中的值类型指定为Object,可以在用例中利用这一点。您需要确保从marshal方法返回的根元素与@XmlElement注释定义的字段/属性匹配。

代码语言:javascript
复制
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.parsers.*;
import org.w3c.dom.*;

public class BarAdapter extends XmlAdapter<Object, Bar>{

    private DocumentBuilder documentBuilder;

    public BarAdapter() {
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            documentBuilder = dbf.newDocumentBuilder();
        } catch(Exception e) {
            // TODO - Handle Exception
        }
    }

    @Override
    public Bar unmarshal(Object v) throws Exception {
        Bar bar = new Bar();
        Element element = (Element) v;
        bar.value = element.getTextContent();
        return bar;
    }

    @Override
    public Object marshal(Bar v) throws Exception {
        Document document = documentBuilder.newDocument();
        Element root = document.createElement("bar");
        root.setTextContent(v.value);
        return root;
    }

}

Java模型

Foo

@XmlJavaTypeAdapter注释用于引用XmlAdapter

代码语言:javascript
复制
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

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

    @XmlJavaTypeAdapter(BarAdapter.class)
    private Bar bar;

}

Bar

代码语言:javascript
复制
import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class Bar {

    String value;

}

演示代码

Demo

由于创建DocumentBuilderFactory需要付出一定的代价,所以我们可以利用JAXB通过在Marshaller上设置一个实例来处理XmlAdapter的有状态实例的能力。

代码语言:javascript
复制
import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Foo.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum18272059/input.xml");
        Foo foo = (Foo) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setAdapter(new BarAdapter());
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(foo, System.out);
    }

}

input.xml/Output

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<foo>
    <bar>Hello World</bar>
</foo>
票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18272059

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档