2009-05-19 2 views
17

У меня есть два документа XML, которые я создал, и я хочу объединить эти два внутри нового конверта. Так что у меняJava, добавляющий документы XML в существующие документы

<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> комбинированные документы </DataSet>

Я попытался создать временный документ и заменить детей корневыми узлами документов:

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

И я надеялся заменить два пробела корневыми элементами двух документов, но я получил «WRONG_DOCUMENT_ERR: Узел используется в другом документе, чем тот, который его создал». Я попытался принять и импортировать корневые узлы, но получаю ту же ошибку.

Не существует ли какой-либо простой способ комбинирования документов без необходимости прочтения и создания новых элементов для каждого узла?

EDIT: фрагменты кода кода Просто перетащите его в «пустой» документ на данный момент ... Функции importNode и acceptNode не могут импортировать/принимать узлы Document, но они не могут импортировать узел элемента и его поддерево ... или если это так, то, похоже, не работает для добавления/замены.

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

Все они бросают DOMException: WRONG_DOCUMENT_ERR: узел используется в другом документе, чем тот, который его создал.

Я думаю, мне нужно выяснить, как использовать stax или просто перечитать документы и создать новые элементы ... Это похоже на работу слишком много, чтобы скомбинировать документы.

+0

Можете ли вы опубликовать пример кода, показывающего, как вы пытаетесь их объединить? – Jonik

ответ

28

Это немного сложнее, но следующий пример работает:

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

Спасибо, что работает. Я импортировал корневой узел в свой собственный документ вместо документа, к которому я пытался объединить все. Иногда перерыв на обед решает все. Спасибо. – ravun

7

Я знаю, что вы получили этот вопрос решается уже, но я все еще хотел взять удар на эту проблему с помощью XOM библиотеки, что я в настоящее время тестируется (относится к this question), и при этом предлагает другой подход, отличный от ответа Andreas_D.

(Чтобы упростить этот пример, я ставлю ваш <alert-set> и <weather-set> в отдельные файлы, которые я прочитал в nu.xom.Document случаях.)

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

Ключ, чтобы сделать копию элементов, которые будут вставлены в mainDoc ; в противном случае вы получите жалобу, что «у ребенка уже есть родитель».

Выведение mainDoc теперь дает:

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

К моему удовольствию, это оказалось очень прямолинейно сделать с XOM. Потребовалось всего несколько минут, чтобы написать это, хотя я определенно не очень опытный в библиотеке. (Это было бы еще проще без элементов <blank/>, то есть, начиная с просто <DataSet></DataSet>.)

Итак, если у вас нет веских оснований для использования только стандартных инструментов JDK, я настоятельно рекомендую попробовать XOM, поскольку он может сделать обработку XML на Java намного приятнее.

+0

Большое спасибо. Я делал это без элементов , так как они были бессмысленными ... Я просто пытался обернуть голову вокруг DOM. Строительные документы с XOM определенно выглядят легче, чем то, что я делал. Я стажер, поэтому я просто мокрыю, но оглядываясь назад, я уже могу сказать большую часть кода, который я написал всего пару недель назад, довольно уродливо. С тех пор я научился использовать XSLT и javax.xml.Transform, и это упростило ситуацию. Еще раз спасибо за ваш ответ и ссылку на XOM. Я уверен, что скоро буду использовать его. – ravun

+0

Рад помочь! Без элементов вы должны сделать root.appendChild (alertDoc.getRootElement(). Copy()) и так далее. Кстати, посмотрите http://www.xom.nu/apidocs/nu/xom/xslt/XSLTransform.html, чтобы узнать, может ли XOM помочь вам с XSLT. – Jonik

Смежные вопросы