parse - Convierte el fragmento de String XML en Document Node en Java
xml document java (8)
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 = "<node>value</node>"; // Convert this to XML
Luego inserte este nodo en org.w3c.dom.Document como hijo de un nodo determinado?
... y si estás usando puramente XOM, algo como esto:
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 usa fakeRoot internamente para hacer casi lo mismo, por lo que debería ser seguro, si no exactamente elegante.
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 = "<node>value</node>"; // 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("<root><given></given></root>", "");
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()
):
<?xml version="1.0"?>
<root><given><node>value</node></given></root>
(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 e.g. from DOMImplementationRegistry
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 = "<node>value</node>"; // 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("<root><given></given></root>"));
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:
<?xml version="1.0" encoding="utf-8"?>
<root>
<given>
<node>value</node>
</given>
</root>
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.
Pruebe jcabi-xml , con un trazador de líneas:
Node node = new XMLDocument("<node>value</node>").node();
Puede usar el método de import (o adopt ) 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);
}
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;
}
Element node = DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.parse(new ByteArrayInputStream("<node>value</node>".getBytes()))
.getDocumentElement();