在 Java 中将字符串 XML 片段转换为文档节点

在 Java 中,如何将表示 XML 片段的 String 转换为插入到 XML 文档中?

例如:。

String newNode =  "<node>value</node>"; // Convert this to XML

然后将此节点作为给定节点的子节点插入到 Org.w3c.dom 文件中?

134001 次浏览
Element node =  DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.parse(new ByteArrayInputStream("<node>value</node>".getBytes()))
.getDocumentElement();

您可以使用文档的 (http://java.sun.com/javase/6/docs/api/org/w3c/dom/Document.html # import Node (org.w3c.dom. Node,% 20boolean))(或 采用)方法来添加 XML 片段:

  /**
* @param docBuilder
*          the parser
* @param parent
*          node to add fragment to
* @param fragment
*          a well formed XML fragment
*/
public static void appendXmlFragment(
DocumentBuilder docBuilder, Node parent,
String fragment) throws IOException, SAXException {
Document doc = parent.getOwnerDocument();
Node fragmentNode = docBuilder.parse(
new InputSource(new StringReader(fragment)))
.getDocumentElement();
fragmentNode = doc.importNode(fragmentNode, true);
parent.appendChild(fragmentNode);
}

无论如何,下面是我使用 Dom4j 库想出的一个解决方案。(我确实检查过它是否有效。)

将 XML 片段读入 org.dom4j.Document(注意: 下面使用的所有 XML 类都来自 org.dom4j; 参见附录) :

  String newNode = "<node>value</node>"; // Convert this to XML
SAXReader reader = new SAXReader();
Document newNodeDocument = reader.read(new StringReader(newNode));

然后获取插入新节点的 Document,以及它的父 Element (将要)。(你的 org.w3c.dom。文档需要转换为 org.dom4j。请按此处查阅文件。)为了测试的目的,我创建了这样一个:

    Document originalDoc =
new SAXReader().read(new StringReader("<root><given></given></root>"));
Element givenNode = originalDoc.getRootElement().element("given");

添加新的子元素非常简单:

    givenNode.add(newNodeDocument.getRootElement());

完成。输出 originalDoc现在产生:

<?xml version="1.0" encoding="utf-8"?>


<root>
<given>
<node>value</node>
</given>
</root>

附录 : 因为您的问题讨论的是 org.w3c.dom.Document,下面介绍如何在 org.w3c.dom.Documentorg.dom4j.Document之间进行转换。

// dom4j -> w3c
DOMWriter writer = new DOMWriter();
org.w3c.dom.Document w3cDoc = writer.write(dom4jDoc);


// w3c -> dom4j
DOMReader reader = new DOMReader();
Document dom4jDoc = reader.read(w3cDoc);

(如果您经常需要这两种 Document,那么将它们放在整洁的实用程序方法中可能是有意义的,也许放在一个名为 XMLUtils的类中或类似的地方。)

也许有更好的方法可以做到这一点,即使没有任何第三方库。但是在目前提供的解决方案中,我认为这是最简单的方法,即使需要进行 dom4j <-> w3c 转换。

更新 (2011) : 在向代码添加 dom4j 依赖项之前,请注意 它是一个积极维护的项目,并且还有其他一些问题。改进版本2.0已经工作了很长时间,但是只有 alpha 版本可用。您可能需要考虑其他选择,比如 XOM; 请阅读上面链接的问题。

这里还有另一个解决方案,使用 < strong > XOM 库,与 我的 dom4j 回答竞争。(这是我的 寻找一个好的 dom4j 替代品的一部分,其中建议将 XOM 作为一个选项。)

首先将 XML 片段读入 nu.xom.Document:

String newNode = "<node>value</node>"; // Convert this to XML
Document newNodeDocument = new Builder().build(newNode, "");

然后,获取添加片段的 Document 和 Node。同样,出于测试目的,我将从一个字符串创建 Document:

Document originalDoc = new Builder().build("<root><given></given></root>", "");
Element givenNode = originalDoc.getRootElement().getFirstChildElement("given");

现在,添加子节点非常简单,类似于 dom4j (除了 XOM 不允许您添加已经属于 newNodeDocument的原始根元素) :

givenNode.appendChild(newNodeDocument.getRootElement().copy());

输出文档将生成正确的结果 XML (使用 XOM 非常简单: 只需打印由 originalDoc.toXML()返回的字符串) :

<?xml version="1.0"?>
<root><given><node>value</node></given></root>

(如果您想要很好地格式化 XML (使用缩进和 linefeeds) ,那么使用 Serializer; 感谢 Peter tibraný 指出了这一点。)

因此,不可否认,这与 dom4j 解决方案没有很大的不同。:)然而,使用 XOM 可能会更好一些,因为 API 有更好的文档说明,而且因为它的设计理念,每件事情都有一种规范的方法。

附录 : 同样,这里介绍了如何在 org.w3c.dom.Documentnu.xom.Document之间进行转换:

// w3c -> xom
Document xomDoc = DOMConverter.convert(w3cDoc);


// xom -> w3c
org.w3c.dom.Document w3cDoc = DOMConverter.convert(xomDoc, domImplementation);
// You can get a DOMImplementation instance e.g. from DOMImplementationRegistry

如果你正在使用 dom4j,你可以这样做:

Document Document = DocumentHelper.parseText (text) ;

(dom4j 现在在这里找到: https://github.com/dom4j/dom4j)

如果您使用的是纯 XOM,比如:

    String xml = "<fakeRoot>" + xml + "</fakeRoot>";
Document doc = new Builder( false ).build( xml, null );
Nodes children = doc.getRootElement().removeChildren();
for( int ix = 0; ix < children.size(); ix++ ) {
otherDocumentElement.appendChild( children.get( ix ) );
}

XOM 在内部使用 fakeRoot 执行大致相同的操作,因此即使不是完全优雅,也应该是安全的。

/**
*
* Convert a string to a Document Object
*
* @param xml The xml to convert
* @return A document Object
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
*/
public static Document string2Document(String xml) throws IOException, SAXException, ParserConfigurationException {


if (xml == null)
return null;


return inputStream2Document(new ByteArrayInputStream(xml.getBytes()));


}




/**
* Convert an inputStream to a Document Object
* @param inputStream The inputstream to convert
* @return a Document Object
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
*/
public static Document inputStream2Document(InputStream inputStream) throws IOException, SAXException, ParserConfigurationException {
DocumentBuilderFactory newInstance = DocumentBuilderFactory.newInstance();
newInstance.setNamespaceAware(true);
Document parse = newInstance.newDocumentBuilder().parse(inputStream);
return parse;
}

试试 Jcabi-xml,它只有一行:

Node node = new XMLDocument("<node>value</node>").node();