Convierte el fragmento de String XML en Document Node en Java

En Java, ¿cómo se puede convertir una cadena que representa un fragmento de XML para su inserción en un documento XML?

p.ej

String newNode = "value"; // Convert this to XML 

Luego inserte este nodo en org.w3c.dom.Document como hijo de un nodo determinado?

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

Puede usar el método de importación (o adopción ) del documento para agregar fragmentos 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); } 

Por lo que vale, aquí hay una solución que se me ocurrió usando la biblioteca dom4j . (Verifiqué que funciona).

Lea el fragmento XML en un org.dom4j.Document (nota: todas las clases XML utilizadas a continuación son de org.dom4j; consulte el Apéndice):

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

A continuación, obtenga el documento en el que se inserta el nuevo nodo y el elemento principal (que debe ser) a partir de él. (Su org.w3c.dom.Document debería convertirse a org.dom4j.Document aquí). Para fines de prueba, creé uno como este:

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

Agregar el nuevo elemento hijo es muy simple:

  givenNode.add(newNodeDocument.getRootElement()); 

Hecho. La salida de originalDoc ahora produce:

    value   

Apéndice : como su pregunta habla sobre org.w3c.dom.Document , aquí le org.w3c.dom.Document cómo convertir eso y 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); 

(Si necesita ambos tipos de Document regularidad, podría tener sentido ponerlos en métodos de utilidad XMLUtils , tal vez en una clase llamada XMLUtils o algo así).

Quizás haya mejores formas de hacerlo, incluso sin bibliotecas de terceros. Pero de las soluciones presentadas hasta ahora, en mi opinión, esta es la forma más fácil, incluso si necesita hacer las conversiones dom4j <-> w3c.

Actualización (2011): antes de agregar la dependencia de dom4j a su código, tenga en cuenta que no es un proyecto activamente mantenido, y tiene algunos otros problemas también . La versión mejorada 2.0 ha estado en proceso durante siglos, pero solo hay una versión alfa disponible. Es posible que desee considerar una alternativa, como XOM, en su lugar; Lea más en la pregunta vinculada arriba.

Aquí hay otra solución, usando la biblioteca XOM , que compite con mi respuesta dom4j . (Esto es parte de mi búsqueda para encontrar un buen reemplazo de dom4j donde se sugirió XOM como una opción).

Primero lea el fragmento XML en un documento nu.xom.Document .

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

Luego, obtenga el Documento y el Nodo bajo los cuales se agrega el fragmento. Nuevamente, para fines de prueba, crearé el documento a partir de una cadena:

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

Ahora, agregar el nodo hijo es simple y similar a dom4j (excepto que XOM no le permite agregar el elemento raíz original que ya pertenece a newNodeDocument ):

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

La salida del documento produce el resultado correcto XML (y es notablemente fácil con XOM: simplemente imprima la cadena devuelta por originalDoc.toXML() ):

  value 

(Si desea formatear el XML muy bien (con sangrías y avances de línea), use un Serializer , gracias a Peter Štibraný por señalarlo).

Por lo tanto, es cierto que esto no es muy diferente de la solución dom4j. 🙂 Sin embargo, XOM puede ser un poco mejor para trabajar, ya que la API está mejor documentada, y debido a su filosofía de diseño, hay una manera canónica para hacer cada cosa.

Apéndice : De nuevo, aquí se org.w3c.dom.Document cómo convertir entre org.w3c.dom.Document y nu.xom.Document . Use los métodos de ayuda en la clase DOMConverter de XOM:

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

Si está usando dom4j, puede hacer:

Documento documental = DocumentHelper.parseText (texto);

(dom4j ahora se encuentra aquí: https://github.com/dom4j/dom4j )

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

… y si estás usando puramente XOM, algo como esto:

  String xml = "" + xml + ""; 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 usa fakeRoot internamente para hacer casi lo mismo, por lo que debería ser seguro, si no exactamente elegante.

Pruebe jcabi-xml , con un trazador de líneas:

 Node node = new XMLDocument("value").node();