Java добавление XML-документов в существующие документы - PullRequest
18 голосов
/ 19 мая 2009

У меня есть два документа 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>
  <blank/>
  <blank/>
</DataSet>

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

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

РЕДАКТИРОВАТЬ: образец кода фрагменты Просто пытаясь переместить одну в «пустой» документ на данный момент ... Функции 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 или просто перечитать документы и создать новые элементы ... Хотя это просто слишком сложная работа для объединения документов.

Ответы [ 2 ]

29 голосов
/ 19 мая 2009

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

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));   
}
7 голосов
/ 09 июня 2009

Я знаю, что вы уже решили проблему, но я все же хотел попробовать ее, используя библиотеку XOM , которую я сейчас тестирую (относится к этому вопросу ) и при этом предлагайте иной подход, чем в ответе 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 намного более приятной.

...