2009-05-19 9 views
17

Tengo dos documentos XML que he creado y quiero combinar estos dos dentro de un nuevo sobre. Así que tengoDocumentos XML de Java que se anexan a los documentos existentes

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

y

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

Lo que me gustaría hacer es combinar los dos dentro de un nodo raíz: < conjunto de datos> documentos combinados </base de datos>

tengo intentado crear un documento temporal y reemplazar hijos con los nodos raíz de los documentos:

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

Y esperaba reemplazar los dos espacios en blanco con los elementos raíz de los dos documentos, pero obtengo "WRONG_DOCUMENT_ERR: un nodo se usa en un documento diferente al que lo creó". Traté de adoptar e importar los nodos raíz, pero obtengo el mismo error.

¿No hay alguna manera fácil de combinar documentos sin tener que leer y crear nuevos elementos para cada nodo?

EDIT: Código de la muestra de fragmentos Sólo tratando de mover una al documento "en blanco" por ahora ... Las funciones ImportNode y adoptNode no pueden importar/adoptar nodos del documento, pero no pueden importar el nodo de elemento y su subárbol ... o si lo hace, parece que no funciona para anexar/reemplazar.

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)); 

Todos estos tire la DOMException: WRONG_DOCUMENT_ERR: Un nodo se utiliza en un documento diferente a la que lo creó.

Creo que tendré que averiguar cómo usar stax o simplemente volver a leer los documentos y crear nuevos elementos ... Sin embargo, parece un poco demasiado trabajo solo para combinar documentos.

+0

¿Puedes publicar un código de ejemplo que muestre cómo estás tratando de combinarlos? – Jonik

Respuesta

28

Es un poco complicado, pero el ejemplo siguiente se ejecuta:

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

Gracias, eso funciona. Estaba importando el nodo raíz como su propio documento en lugar del documento al que intentaba combinar todo. A veces tomar un almuerzo resuelve todo. Gracias. – ravun

7

Sé que tienes el problema ya resuelto, pero todavía quería tomar una puñalada en este problema mediante el XOM biblioteca que estoy Actualmente probando (relacionado con this question), y mientras lo hace, ofrezca un enfoque diferente al de la respuesta de Andreas_D.

(Para simplificar este ejemplo, que ponga a tus <alert-set> y <weather-set> en archivos separados, que leí en nu.xom.Document casos.)

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 clave es hacer una copia de los elementos a insertar en mainDoc ; de lo contrario, se queja de que "el niño ya tiene un padre".

Salida de mainDoc ahora da:

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

Para mi deleite, esto resultó ser muy recta de avance que ver con XOM. Solo me llevó unos minutos escribir esto, aunque definitivamente tengo y no con mucha experiencia en la biblioteca. (Hubiera sido aún más fácil sin los elementos <blank/>, es decir, comenzando con simplemente <DataSet></DataSet>.)

Por lo tanto, a menos que tenga razones convincentes para usar solo las herramientas JDK estándar, le recomiendo probar XOM, ya que puede hacer que el manejo de XML en Java sea mucho más agradable.

+0

Muchas gracias. Terminé haciéndolo sin los elementos ya que eran inútiles ... Estaba tratando de abarcar DOM. La construcción de documentos con XOM definitivamente parece más fácil que lo que estaba haciendo. Soy pasante, así que me estoy mojando los pies, pero mirando hacia atrás ya puedo decir que la mayoría del código que escribí hace solo un par de semanas es bastante feo. Desde entonces aprendí cómo usar XSLT y javax.xml.Transform y eso ha facilitado las cosas. Gracias de nuevo por su respuesta y enlace a XOM. Estoy seguro de que lo usaré pronto. – ravun

+0

Me alegro de ser de ayuda :) Sin los elementos , acaba de hacer root.appendChild (alertDoc.getRootElement(). Copy()) y así sucesivamente. Por cierto, eche un vistazo a http://www.xom.nu/apidocs/nu/xom/xslt/XSLTransform.html para ver si XOM también podría ayudarlo con XSLT. – Jonik

Cuestiones relacionadas