Java anexando documentos XML para documentos existentes
Pergunta
Eu tenho dois documentos XML que eu criei e eu quero combinar estes dois dentro de um novo envelope. Então, eu tenho
<alert-set>
<warning>National Weather Service...</warning>
<start-date>5/19/2009</start-date>
<end-date>5/19/2009</end-date>
</alert-set>
e
<weather-set>
<chance-of-rain type="percent">31</chance-of-rain>
<conditions>Partly Cloudy</conditions>
<temperature type="Fahrenheit">78</temperature>
</weather-set>
O que eu gostaria de fazer é combinar os dois dentro de um nó de raiz:
Eu tentei criar um documento temporário e substituindo as crianças com os nós raiz dos documentos:
<DataSet>
<blank/>
<blank/>
</DataSet>
E eu estava esperando para substituir os dois espaços em branco com os elementos raiz dos dois documentos, mas eu recebo "WRONG_DOCUMENT_ERR:. Nó A é usado em um documento diferente daquele que o criou" Tentei adotar e importar os nós raiz, mas eu recebo o mesmo erro.
Não existe alguma maneira fácil de combinar documentos sem ter de ler e criar novos elementos para cada nó?
Editar: Sample trechos de código Apenas tentando mover um ao documento "em branco" por agora ... As funções ImportNode e adoptNode não pode importação / adotar nós do documento, mas não pode importar o nó elemento e sua subárvore ... ou se isso acontecer, ele faz não parecem trabalhar para acrescentar / substituir ainda.
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 estes lance do DOMException: WRONG_DOCUMENT_ERR:. Um nó é usado em um documento diferente daquele que o criou
Eu acho que vou ter que descobrir como usar Stax ou apenas reler os documentos e criar novos elementos ... Isso parece um bocado como muito trabalho só para combinar documentos, no entanto.
Solução
É um pouco complicado, mas o exemplo a seguir é executado:
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));
}
Outras dicas
Eu sei que você tem o problema já resolvido, mas eu ainda queria tomar uma facada em este problema utilizando a XOM biblioteca que eu estou testando para fora (relacionado a esta questão ), e ao fazer isso, oferecem uma abordagem diferente do que a resposta de Andreas_D.
(Para simplificar este exemplo, eu coloco seu <alert-set>
e <weather-set>
em arquivos separados, que eu li em 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());
A chave é fazer uma cópia dos elementos a serem inseridos no mainDoc
; caso contrário, você vai ter um queixam de que "a criança já tem um pai".
Produzindo mainDoc agora dá:
<?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 minha alegria, este acabou por ser muito direto a ver com XOM. Levou apenas alguns minutos para escrever isso, mesmo que eu sou definitivamente não muito experiente com a biblioteca ainda. (Teria sido ainda mais fácil sem os elementos <blank/>
, ou seja, começando com simplesmente <DataSet></DataSet>
.)
Assim, a menos que tenha razões para usando apenas as ferramentas do JDK padrão, recomendo vivamente a experimentar XOM, pois ele pode fazer XML manipulação em Java muito mais agradável.