Convert String XML fragment to Document Node in Java

前端 未结 8 2134
迷失自我
迷失自我 2020-11-28 04:00

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

e.g.

String newNode =  \"valu         


        
相关标签:
8条回答
  • 2020-11-28 04:04

    Try jcabi-xml, with a one liner:

    Node node = new XMLDocument("<node>value</node>").node();
    
    0 讨论(0)
  • 2020-11-28 04:06

    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);
      }
    
    0 讨论(0)
  • 2020-11-28 04:06

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

    Document document = DocumentHelper.parseText(text);

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

    0 讨论(0)
  • 2020-11-28 04:07

    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.

    0 讨论(0)
  • 2020-11-28 04:07

    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
    
    0 讨论(0)
  • 2020-11-28 04:07

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

    0 讨论(0)
提交回复
热议问题