2009-05-19 22 views
17

Mam dwa dokumenty XML, które utworzyłem i chcę je połączyć w nowej kopercie. Więc mamJava dołączanie dokumentów XML do istniejących dokumentów

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

i

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

Co chciałbym zrobić, to połączyć dwa wewnątrz węzła głównego: < DataSet> łączone docs </DataSet>

mam próbowałem utworzyć dokument tymczasowy i zamienić elementy potomne na węzły główne dokumentów:

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

I miałem nadzieję zastąpić dwa puste elementy pierwiastkami z dwóch dokumentów, ale otrzymałem "WRONG_DOCUMENT_ERR: Węzeł jest używany w innym dokumencie niż ten, który go utworzył." Próbowałem adoptować i importować węzły główne, ale pojawia się ten sam błąd.

Czy istnieje prosty sposób łączenia dokumentów bez konieczności ich odczytywania i tworzenia nowych elementów dla każdego węzła?

EDYCJA: Przykładowe fragmenty kodu Po prostu próbuję przenieść jeden do "pustego" dokumentu ... Funkcje importNode i adoptNode nie mogą importować/adoptować węzłów dokumentów, ale nie mogą importować węzła elementu i jego poddrzewa ... lub jeśli tak, to wydaje się nie działać do uzupełniania/zastępowania nadal.

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

Wszystkie te rzucić DOMException: WRONG_DOCUMENT_ERR: węzeł jest używany w innym dokumencie niż ten, który go stworzył.

Myślę, że będę musiał wymyślić, jak używać stax lub po prostu ponownie przeczytać dokumenty i stworzyć nowe elementy ... Jednak wydaje się, że zbyt wiele pracy polega na łączeniu dokumentów.

+0

Czy możesz podać przykładowy kod pokazujący, jak próbujesz je połączyć? – Jonik

Odpowiedz

28

To trochę skomplikowane, ale w poniższym przykładzie działa:

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

Dzięki, że działa. Importowałem węzeł główny z własnego dokumentu zamiast dokumentu, do którego próbowałem połączyć wszystko. Czasami przerwa na lunch rozwiązuje wszystko. Dzięki. – ravun

7

Wiem, że masz problem już rozwiązany, ale nadal chciał wziąć ukłucie na ten problem przy użyciu biblioteki XOM że jestem obecnie testowanie (związane z this question), a przy tym oferuje inne podejście niż odpowiedź Andreas_D.

(Aby uprościć ten przykład, umieścić swoją <alert-set> i <weather-set> w oddzielnych plikach, które czytałem na nu.xom.Document przypadkach.)

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

Kluczem jest, aby kopia elementów do umieszczenia w mainDoc ; inaczej dostaniesz skargę, że "dziecko ma już rodzica".

Wyprowadzanie mainDoc teraz daje:

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

Ku mojemu zadowoleniu, okazało się to być bardzo prosta do zrobienia z Xóm. Napisanie tego zajęło mi tylko kilka minut, mimo że zdecydowanie nie mam jeszcze żadnych doświadczeń z biblioteką . (Byłoby jeszcze łatwiejsze bez elementów <blank/>, tj. Zaczynając od zwykłego <DataSet></DataSet>.)

Tak więc, jeśli nie ma się nieodpartych powodów, aby używać tylko standardowych narzędzi JDK, gorąco polecam wypróbowanie XOM, ponieważ może to znacznie ułatwić obsługę XML w języku Java.

+0

Wielkie dzięki. Zrobiłem to bez elementów , ponieważ były bezcelowe ... Chciałem tylko objąć głowę DOMem. Budowanie dokumentów za pomocą XOM zdecydowanie wygląda łatwiej niż to, co robiłem. Jestem stażystą, więc po prostu mam mokre stopy, ale patrząc wstecz mogę już powiedzieć, że większość kodu, który napisałem kilka tygodni temu, jest dość brzydka. Od tego czasu nauczyłem się korzystać z XSLT i javax.xml.Transform, co znacznie ułatwiło mi pracę. Jeszcze raz dziękuję za odpowiedź i link do XOM. Jestem pewien, że wkrótce to wykorzystam. – ravun

+0

Cieszę się, że pomogłem :) Bez elementów wystarczy, że wykonasz polecenie root.appendChild (alertDoc.getRootElement(). Copy()) i tak dalej. Przy okazji spójrz na http://www.xom.nu/apidocs/nu/xom/xslt/XSLTransform.html, aby sprawdzić, czy XOM może ci pomóc w XSLT. – Jonik

Powiązane problemy