2009-05-19 11 views
17

J'ai deux documents XML que j'ai créés et je veux les combiner dans une nouvelle enveloppe. J'ai doncJava ajoutant des documents XML à des documents existants

<alert-set> 
    <warning>National Weather Service...</warning> 
    <start-date>5/19/2009</start-date> 
    <end-date>5/19/2009</end-date> 
</alert-set> 

et

<weather-set> 
    <chance-of-rain type="percent">31</chance-of-rain> 
    <conditions>Partly Cloudy</conditions> 
    <temperature type="Fahrenheit">78</temperature> 
</weather-set> 

Ce que je voudrais faire est de combiner les deux dans un nœud racine: < DataSet> docs combinés </DataSet>

J'ai essayé de créer un document temporaire et de remplacer les enfants par les nœuds racine des documents:

<DataSet> 
    <blank/> 
    <blank/> 
</DataSet> 

Et j'espérais remplacer les deux espaces vides par les éléments racine des deux documents mais j'obtiens "WRONG_DOCUMENT_ERR: Un noeud est utilisé dans un document différent de celui qui l'a créé." J'ai essayé d'adopter et d'importer les noeuds racine mais j'ai la même erreur.

N'existe-t-il pas un moyen simple de combiner des documents sans avoir à lire et créer de nouveaux éléments pour chaque nœud? Essayez simplement d'en déplacer un vers le document "vide" pour l'instant ... Les fonctions importNode et adoptNode ne peuvent pas importer/adopter des noeuds Document, mais ils ne peuvent pas importer le noeud d'élément et son sous-arbre ... ou si c'est le cas, il ne semble pas fonctionner pour ajouter/remplacer encore.

Document xmlDoc;  //created elsewhere 
    Document weather = getWeather(latitude, longitude); 
    Element weatherRoot = weather.getDocumentElement(); 

    Node root = xmlDoc.getDocumentElement(); 
    Node adopt = weather.adoptNode(weatherRoot); 
    Node imported = weather.importNode(weatherRoot, true); 
    Node child = root.getFirstChild(); 

    root.replaceChild(adopt, child);  //initially tried replacing the <blank/> elements 
    root.replaceChild(imported, child); 

    root.appendChild(adopt); 
    root.appendChild(imported); 
    root.appendChild(adopt.cloneNode(true)); 

Tous ces jeter le DOMException: WRONG_DOCUMENT_ERR: Un nœud est utilisé dans un autre document que celui qui l'a créé.

Je pense que je vais devoir comprendre comment utiliser stax ou juste relire les documents et créer de nouveaux éléments ... Cela semble un peu trop de travail pour combiner des documents, cependant.

+0

Pouvez-vous publier un exemple de code montrant comment vous essayez de les combiner? – Jonik

Répondre

28

Il est un peu difficile, mais l'exemple suivant,:

public static void main(String[] args) { 

    DocumentImpl doc1 = new DocumentImpl(); 
    Element root1 = doc1.createElement("root1"); 
    Element node1 = doc1.createElement("node1"); 
    doc1.appendChild(root1); 
    root1.appendChild(node1); 

    DocumentImpl doc2 = new DocumentImpl(); 
    Element root2 = doc2.createElement("root2"); 
    Element node2 = doc2.createElement("node2"); 
    doc2.appendChild(root2); 
    root2.appendChild(node2); 

    DocumentImpl doc3 = new DocumentImpl(); 
    Element root3 = doc3.createElement("root3"); 
    doc3.appendChild(root3); 

    // root3.appendChild(root1); // Doesn't work -> DOMException 
    root3.appendChild(doc3.importNode(root1, true)); 

    // root3.appendChild(root2); // Doesn't work -> DOMException 
    root3.appendChild(doc3.importNode(root2, true)); 
} 
+3

Merci, ça fonctionne. J'importais le nœud racine de son propre document au lieu du document que j'essayais de tout combiner. Parfois, prendre une pause déjeuner résout tout. Merci. – ravun

7

Je sais que vous avez le problème déjà résolu, mais je voulais quand même prendre un coup de couteau à ce problème en utilisant la bibliothèque XOM que je suis en cours de test (lié à this question), et ce faisant, offrir une approche différente de celle de la réponse de Andreas_D.

(Pour simplifier cet exemple, je mets votre <alert-set> et <weather-set> dans des fichiers séparés, que je lis dans nu.xom.Document cas.)

import nu.xom.*; 

[...] 

Builder builder = new Builder(); 
Document alertDoc = builder.build(new File("src/xomtest", "alertset.xml")); 
Document weatherDoc = builder.build(new File("src/xomtest", "weatherset.xml")); 
Document mainDoc = builder.build("<DataSet><blank/><blank/></DataSet>", ""); 

Element root = mainDoc.getRootElement(); 
root.replaceChild(
    root.getFirstChildElement("blank"), alertDoc.getRootElement().copy()); 
root.replaceChild(
    root.getFirstChildElement("blank"), weatherDoc.getRootElement().copy()); 

La clé est de faire une copie des éléments à insérer dans mainDoc ; sinon, vous vous plaignez que "l'enfant a déjà un parent".

mainDoc donne maintenant Sortie:

<?xml version="1.0" encoding="UTF-8"?> 
<DataSet> 
    <alert-set> 
     <warning>National Weather Service...</warning> 
     <start-date>5/19/2009</start-date> 
     <end-date>5/19/2009</end-date> 
    </alert-set> 
    <weather-set> 
     <chance-of-rain type="percent">31</chance-of-rain> 
     <conditions>Partly Cloudy</conditions> 
     <temperature type="Fahrenheit">78</temperature> 
    </weather-set> 
</DataSet> 

À mon grand plaisir, cela se révèle être très simple pour faire avec XOM. Il ne m'a fallu que quelques minutes pour l'écrire, même si je ne suis pas vraiment très expérimenté avec la bibliothèque pour l'instant. (Cela aurait été encore plus facile sans les éléments <blank/>, c'est-à-dire en commençant simplement par <DataSet></DataSet>.Donc, à moins que vous n'ayez des raisons impérieuses de n'utiliser que les outils JDK standard, je vous recommande chaudement d'essayer XOM car cela rendra la gestion de XML en Java beaucoup plus agréable.

+0

Merci beaucoup. J'ai fini par le faire sans les éléments car ils étaient inutiles ... J'essayais juste d'envelopper ma tête autour de DOM. La création de documents avec XOM semble définitivement plus facile que ce que je faisais. Je suis stagiaire donc je me mouille les pieds, mais en regardant en arrière je peux déjà dire que la plupart du code que j'ai écrit il y a seulement quelques semaines est vraiment moche. Depuis, j'ai appris à utiliser XSLT et javax.xml.Transform, ce qui a rendu les choses beaucoup plus faciles. Merci encore pour votre réponse et un lien vers XOM. Je suis sûr que je l'utiliserai bientôt. – ravun

+0

Heureux d'être de l'aide :) Sans éléments, vous feriez juste root.appendChild (alertDoc.getRootElement(). Copy()) et ainsi de suite. En passant, jetez un oeil à http://www.xom.nu/apidocs/nu/xom/xslt/XSLTransform.html pour voir si XOM pourrait vous aider avec XSLT aussi. – Jonik