如何将 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 命名空间感知。在编组到DOMSource
与 Document
时,您会看到不同的行为这一事实就是证明。如果您交换解析器或 JAXB 提供程序,您可能会看到不同的结果。以上是关于如何将 JAXB 对象编组到 org.w3c.dom.Document?的主要内容,如果未能解决你的问题,请参考以下文章
将对象编组为枚举类型时不调用 JAXB XmlJavaTypeAdapter