如何将 JAXB 对象编组到 org.w3c.dom.Document?

Posted

技术标签:

【中文标题】如何将 JAXB 对象编组到 org.w3c.dom.Document?【英文标题】:how to marshal a JAXB object to org.w3c.dom.Document? 【发布时间】:2013-06-09 07:42:59 【问题描述】:

这给了我一个没有子节点的***节点的 Document 对象:

public static Document getDocument(Object jaxb)

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    //dbf.setNamespaceAware(true);
    Document doc = dbf.newDocumentBuilder().newDocument(); 

    JAXBContext context = JAXBContext.newInstance(jaxb.getClass());
    context.createMarshaller().marshal(jaxb, doc);

    return doc;

这是一种变通方法,似乎效率更低,因为它先转换为字符串,然后再转换为文档。

public static Document getDocument(Object jaxb)
                           
    StringWriter writer = new StringWriter();       
    JAXBContext context = JAXBContext.newInstance(jaxb.getClass());
    context.createMarshaller().marshal(jaxb, writer);

    return DocumentBuilderFactory.newInstance().newDocumentBuilder().
parse(new InputSource(new StringReader(writer.toString()));

是否有可能完成我想要完成的事情?

【问题讨论】:

原来问题不是从 JAXB 编组到文档。问题在于,由于某种原因,与命名空间无关的 XPath 查询不能与第一种方法返回的 Document 对象一起使用,但可以很好地与第二种方法返回的 Document 对象一起使用。解决方案 - 至少目前 - 是重写我的 Xpath 查询。 作为迟来的评论:如果您解析编组的数据,与命名空间无关的 XPath 查询之所以起作用,是因为文档构建器默认情况下不支持命名空间。当 JAXB 构建 DOM 时,DocumentBuilder 设置不相关,因为不涉及解析。 【参考方案1】:

试试这个

    DOMResult res = new DOMResult();
    JAXBContext context = JAXBContext.newInstance(obj.getClass());
    context.createMarshaller().marshal(obj, res);
    Document doc = (Document) res.getNode();

【讨论】:

原来问题不是从 JAXB 编组到文档。问题在于,由于某种原因,与命名空间无关的 XPath 查询不能与第一种方法返回的 Document 对象一起使用,但可以与第二种方法返回的 Document 对象一起正常工作。解决方案——至少目前是这样——是重写我的 Xpath 查询。 不错的解决方案,比公认的更简单。【参考方案2】:

你正在做的应该工作。这是一个例子:

领域模型(Foo)

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Foo 

    private String bar;

    public String getBar() 
        return bar;
    

    public void setBar(String bar) 
        this.bar = bar;
    


演示

import javax.xml.bind.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

public class Demo 

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

        // Create the Object
        Foo foo = new Foo();
        foo.setBar("Hello World");

        // Create the Document
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document document = db.newDocument();

        // Marshal the Object to a Document
        Marshaller marshaller = jc.createMarshaller();
        marshaller.marshal(foo, document);

        // Output the Document
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer t = tf.newTransformer();
        DOMSource source = new DOMSource(document);
        StreamResult result = new StreamResult(System.out);
        t.transform(source, result);
    


输出

<?xml version="1.0" encoding="UTF-8" standalone="no"?><foo><bar>Hello World</bar></foo>

【讨论】:

尝试向示例 XML 文档添加名称空间,然后使用不考虑名称空间的 Xpath 表达式查询该文档。例如: //foo/bar 与 //ns:foo/ns:bar @JSmith - 如果文档是命名空间感知的,那么您应该让 XPath 命名空间感知。在编组到 DOMSourceDocument 时,您会看到不同的行为这一事实就是证明。如果您交换解析器或 JAXB 提供程序,您可能会看到不同的结果。

以上是关于如何将 JAXB 对象编组到 org.w3c.dom.Document?的主要内容,如果未能解决你的问题,请参考以下文章

在 JaxB 编组期间将字符串截断到最大限制

JAXB:如何编组列表中的对象?

JAXB - 如何在没有标题的情况下编组java对象

将对象编组为枚举类型时不调用 JAXB XmlJavaTypeAdapter

带有 java.lang.Object 字段的 JAXB 编组对象

编组时出现 JAXB 错误