Java anexando documentos XML para documentos existentes

votos
17

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: <DataSet> docs combinadas </ DataSet>

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:. Um nó é 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 há alguma maneira fácil de combinar documentos sem ter de ler e criar novos elementos para cada nó?

EDIT: trechos de código Amostra Apenas tentando mover um ao documento em branco por agora ... As funções ImportNode e adoptNode não pode importar / adotar nós do documento, mas não pode importar o nó elemento e sua subárvore ... ou se isso acontecer, ele não parece 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 jogar a DOMException: WRONG_DOCUMENT_ERR: Um nó é usado em um documento diferente daquele que o criou.

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.

Publicado 19/05/2009 em 18:11
fonte usuário
Em outras línguas...                            


2 respostas

votos
28

É 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));   
}
Respondeu 19/05/2009 em 19:31
fonte usuário

votos
7

Eu sei que você tem o problema já resolvido, mas eu ainda queria tomar uma facada em este problema usando o XOM biblioteca que eu estou testando para fora (relacionado a esta pergunta ), e ao fazer isso, oferecem uma abordagem diferente do que a de A resposta de Andreas_D.

(Para simplificar este exemplo, eu colocar o seu <alert-set>e <weather-set>em arquivos separados, que eu li em nu.xom.Documentinstâncias.)

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".

Produzir 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 <blank/>elementos, ou seja, começando com simplesmente <DataSet></DataSet>.)

Então, 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.

Respondeu 08/06/2009 em 21:38
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more