Convert String XML fragment to Document Node in Java

JavaXmlString

Java Problem Overview


In Java how can you convert a String that represents a fragment of XML for insertion into an XML document?

e.g.

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?

Java Solutions


Solution 1 - Java

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

Solution 2 - Java

You can use the document's import (or adopt) method to add XML fragments:

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

Solution 3 - Java

For what it's worth, here's a solution I came up with using the dom4j library. (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):

  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. (Your org.w3c.dom.Document would need to be converted to org.dom4j.Document here.) For testing purposes, I created one like this:

    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:

<?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.

// 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 Documents regularly, it might make sense to put these in neat utility methods, maybe in a class called XMLUtils or something like that.)

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.

Update (2011): before adding dom4j dependency to your code, note that it is not an actively maintained project, and has some other problems too. Improved version 2.0 has been in the works for ages, but there's only an alpha version available. You may want to consider an alternative, like XOM, instead; read more in the question linked above.

Solution 4 - Java

Here's yet another solution, using the XOM library, that competes with my dom4j answer. (This is part of my quest to find a good dom4j replacement where XOM was suggested as one option.)

First read the XML fragment into a 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 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):

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 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.)

So, admittedly this isn't very different from the dom4j solution. :) 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.

Appendix: Again, here's how to convert between org.w3c.dom.Document and nu.xom.Document. Use the helper methods in XOM's DOMConverter class:

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

Solution 5 - Java

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

Solution 6 - Java

If you're using dom4j, you can just do:

Document document = DocumentHelper.parseText(text);

(dom4j now found here: https://github.com/dom4j/dom4j)

Solution 7 - Java

...and if you're using purely XOM, something like this:

    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.

Solution 8 - Java

Try jcabi-xml, with a one liner:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJames WardleView Question on Stackoverflow
Solution 1 - JavaizbView Answer on Stackoverflow
Solution 2 - JavaMcDowellView Answer on Stackoverflow
Solution 3 - JavaJonikView Answer on Stackoverflow
Solution 4 - JavaJonikView Answer on Stackoverflow
Solution 5 - JavaGiordano MaestroView Answer on Stackoverflow
Solution 6 - JavaronzView Answer on Stackoverflow
Solution 7 - JavaatamarView Answer on Stackoverflow
Solution 8 - Javayegor256View Answer on Stackoverflow