Convertir un fragment XML Ssortingng en un nœud de document en Java

En Java, comment pouvez-vous convertir une chaîne qui représente un fragment de XML pour l’insérer dans un document XML?

par exemple

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

Ensuite, insérez ce noeud dans un org.w3c.dom.Document en tant qu’enfant d’un noeud donné?

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

Vous pouvez utiliser la méthode d’ importation (ou d’ adoption ) du document pour append des fragments 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, Ssortingng fragment) throws IOException, SAXException { Document doc = parent.getOwnerDocument(); Node fragmentNode = docBuilder.parse( new InputSource(new SsortingngReader(fragment))) .getDocumentElement(); fragmentNode = doc.importNode(fragmentNode, true); parent.appendChild(fragmentNode); } 

Pour ce que ça vaut, voici une solution que j’ai imaginée en utilisant la bibliothèque dom4j . (J’ai vérifié que ça marche.)

Lire le fragment XML dans un org.dom4j.Document (note: toutes les classes XML utilisées ci-dessous sont issues de org.dom4j; voir Annexe):

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

Ensuite, récupérez le document dans lequel le nouveau noeud est inséré et l’élément parent (à être). (Votre org.w3c.dom.Document devrait être converti en org.dom4j.Document ici.) A des fins de test, j’en ai créé un comme ceci:

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

L’ajout du nouvel élément enfant est très simple:

  givenNode.add(newNodeDocument.getRootElement()); 

Terminé. La sortie de originalDoc donne maintenant:

    value   

Annexe : Parce que votre question parle de org.w3c.dom.Document , voici comment convertir entre cela et 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 vous aviez besoin des deux types de Document régulièrement, il pourrait être judicieux de les mettre dans des méthodes utilitaires, peut-être dans une classe appelée XMLUtils ou quelque chose du genre.)

Peut-être y a-t-il de meilleurs moyens de le faire, même sans bibliothèques tierces. Mais à mon avis, parmi les solutions présentées jusqu’à présent, c’est le moyen le plus simple, même si vous devez effectuer les conversions dom4j <-> w3c.

Mise à jour (2011): avant d’append une dépendance dom4j à votre code, notez qu’il ne s’agit pas d’ un projet activement géré et qu’il présente également d’autres problèmes . La version 2.0 améliorée est en cours depuis longtemps, mais il n’ya qu’une version alpha disponible. Vous pouvez envisager une alternative, comme XOM, à la place; lire plus dans la question liée ci-dessus.

Voici encore une autre solution, utilisant la bibliothèque XOM , qui rivalise avec ma réponse dom4j . (Cela fait partie de ma quête pour trouver un bon remplacement dom4j où XOM a été suggéré comme une option.)

Lisez d’abord le fragment XML dans un nu.xom.Document :

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

Ensuite, récupérez le document et le nœud sous lequel le fragment est ajouté. Encore une fois, à des fins de test, je créerai le document à partir d’une chaîne:

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

Maintenant, l’ajout du nœud enfant est simple et similaire à celui de dom4j (sauf que XOM ne vous permet pas d’append l’élément racine d’origine qui appartient déjà à newNodeDocument ):

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

La sortie du document donne le bon résultat XML (et est remarquablement facile avec XOM: il suffit d’imprimer la chaîne renvoyée par originalDoc.toXML() ):

  value 

(Si vous voulez formater le XML correctement (avec des indentations et des sauts de ligne), utilisez un Serializer , merci à Peter Štibraný de l’avoir signalé.)

Donc, certes, ce n’est pas très différent de la solution dom4j. 🙂 Cependant, XOM est peut-être un peu plus agréable à utiliser, car l’API est mieux documentée, et en raison de sa philosophie de conception, il existe un moyen canonique de faire chaque chose.

Annexe : Encore une fois, voici comment convertir entre org.w3c.dom.Document et nu.xom.Document . Utilisez les méthodes d’aide dans la classe 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 vous utilisez dom4j, vous pouvez simplement faire:

Document document = DocumentHelper.parseText (texte);

(dom4j maintenant trouvé ici: https://github.com/dom4j/dom4j )

 /** * * Convert a ssortingng to a Document Object * * @param xml The xml to convert * @return A document Object * @throws IOException * @throws SAXException * @throws ParserConfigurationException */ public static Document ssortingng2Document(Ssortingng 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; } 

… et si vous utilisez purement XOM, quelque chose comme ceci:

  Ssortingng 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 utilise fakeRoot en interne pour faire à peu près la même chose, il doit donc être sûr, sinon élégant.

Essayez jcabi-xml , avec un seul liner:

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