【问题标题】:how to marshal a JAXB object to org.w3c.dom.Document?如何将 JAXB 对象编组到 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 设置不相关,因为不涉及解析。

标签: java xml dom jaxb marshalling


【解决方案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 提供程序,您可能会看到不同的结果。
猜你喜欢
  • 1970-01-01
  • 2015-12-12
  • 1970-01-01
  • 2023-03-23
  • 2016-10-27
  • 1970-01-01
  • 2011-04-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多