简体   繁体   English

在Java中将String XML片段转换为Document Node

[英]Convert String XML fragment to Document Node in Java

In Java how can you convert a String that represents a fragment of XML for insertion into an XML document? 在Java中,如何将表示XML片段的String转换为XML文档?

eg 例如

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

Then insert this node into an org.w3c.dom.Document as the child of a given node? 然后将此节点作为给定节点的子节点插入org.w3c.dom.Document中?

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

You can use the document's import (or adopt ) method to add XML fragments: 您可以使用文档的import (或采用 )方法添加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);
  }

For what it's worth, here's a solution I came up with using the dom4j library. 对于它的价值,这是我使用dom4j库提出的解决方案。 (I did check that it works.) (我确实检查过它是否有效。)

Read the XML fragment into a org.dom4j.Document (note: all the XML classes used below are from org.dom4j; see Appendix): 将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));

Then get the Document into which the new node is inserted, and the parent Element (to be) from it. 然后获取插入新节点的Document,以及从中获取父元素(将)。 (Your org.w3c.dom.Document would need to be converted to org.dom4j.Document here.) For testing purposes, I created one like this: (你的org.w3c.dom.Document需要在这里转换为org.dom4j.Document。)为了测试目的,我创建了一个这样的:

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

Adding the new child element is very simple: 添加新的子元素非常简单:

    givenNode.add(newNodeDocument.getRootElement());

Done. 完成。 Outputting originalDoc now yields: 输出originalDoc现在产生:

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

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

Appendix : Because your question talks about org.w3c.dom.Document , here's how to convert between that and org.dom4j.Document . 附录 :因为您的问题涉及org.w3c.dom.Document ,所以这里是如何在org.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);

(If you'd need both kind of Document s regularly, it might make sense to put these in neat utility methods, maybe in a class called XMLUtils or something like that.) (如果你需要经常使用这两种Document ,那么将它们放在简洁的实用程序方法中可能是有意义的,可能在一个名为XMLUtils的类或类似的东西中。)

Maybe there are better ways to do this, even without any 3rd party libraries. 也许有更好的方法来做到这一点,即使没有任何第三方库。 But out of the solutions presented so far, in my view this is the easiest way, even if you need to do the dom4j <-> w3c conversions. 但是到目前为止提供的解决方案中,在我看来这是最简单的方法,即使你需要进行dom4j < - > w3c转换。

Update (2011): before adding dom4j dependency to your code, note that it is not an actively maintained project, and has some other problems too . 更新 (2011):在将dom4j依赖项添加到代码之前,请注意不是一个主动维护的项目,并且还有其他一些问题 Improved version 2.0 has been in the works for ages, but there's only an alpha version available. 改进版2.0已经开始使用多年了,但是只有alpha版本可用。 You may want to consider an alternative, like XOM, instead; 您可能想要考虑替代方案,例如XOM; read more in the question linked above. 在上面链接的问题中阅读更多内容。

/**
*
* 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;
}

Here's yet another solution, using the XOM library , that competes with my dom4j answer . 这是另一个使用XOM库的解决方案,它与我的dom4j答案竞争。 (This is part of my quest to find a good dom4j replacement where XOM was suggested as one option.) (这是我寻找一个好的dom4j替代品的一部分 ,其中XOM被建议作为一个选项。)

First read the XML fragment into a nu.xom.Document : 首先将XML片段读入nu.xom.Document

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

Then, get the Document and the Node under which the fragment is added. 然后,获取文档和添加片段的节点。 Again, for testing purposes I'll create the Document from a string: 同样,出于测试目的,我将从字符串创建Document:

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

Now, adding the child node is simple, and similar as with dom4j (except that XOM doesn't let you add the original root element which already belongs to newNodeDocument ): 现在,添加子节点很简单,与dom4j类似(除了XOM不允许添加已经属于newNodeDocument的原始根元素):

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

Outputting the document yields the correct result XML (and is remarkably easy with XOM: just print the string returned by originalDoc.toXML() ): 输出文档会产生正确的结果XML(使用XOM非常容易:只需打印originalDoc.toXML()返回的字符串):

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

(If you wanted to format the XML nicely (with indentations and linefeeds), use a Serializer ; thanks to Peter Štibraný for pointing this out.) (如果你想很好地格式化XML(使用缩进和换行符),请使用Serializer ;感谢PeterŠtibraný指出这一点。)

So, admittedly this isn't very different from the dom4j solution. 所以,诚然,这与dom4j解决方案没有太大区别。 :) However, XOM may be a little nicer to work with, because the API is better documented, and because of its design philosophy that there's one canonical way for doing each thing. :)然而,XOM可能会更好一些,因为API更好地记录,并且由于其设计理念,有一种规范的方式来做每件事。

Appendix : Again, here's how to convert between org.w3c.dom.Document and nu.xom.Document . 附录 :同样,这里是如何在org.w3c.dom.Documentnu.xom.Document之间进行转换。 Use the helper methods in XOM's DOMConverter class: 使用XOM的DOMConverter类中的辅助方法:

// 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

If you're using dom4j, you can just do: 如果你正在使用dom4j,你可以这样做:

Document document = DocumentHelper.parseText(text); Document document = DocumentHelper.parseText(text);

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

试试jcabi-xml ,一个内衬:

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

...and if you're using purely XOM, something like this: ...如果你使用的是纯粹的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 uses fakeRoot internally to do pretty much the same, so it should be safe, if not exactly elegant. XOM在内部使用fakeRoot几乎一样,所以它应该是安全的,如果不是很优雅的话。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM