Java 将 XML 文档附加到现有文档

Posted

技术标签:

【中文标题】Java 将 XML 文档附加到现有文档【英文标题】:Java appending XML docs to existing docs 【发布时间】:2010-10-27 09:45:42 【问题描述】:

我创建了两个 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:一个节点用于与创建它的文档不同的文档中”。我尝试采用和导入根节点,但我得到了同样的错误。

是否有一些简单的方法可以组合文档而无需通读并为每个节点创建新元素?

编辑:示例代码 sn-ps 现在只是试图将一个移动到“空白”文档...... importNode 和adoptNode 函数无法导入/采用文档节点,但它们不能导入元素节点及其子树......或者如果确实如此,它确实似乎仍然无法追加/替换。

    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,或者只是重新阅读文档并创建新元素……不过,仅仅合并文档似乎工作量太大了。

【问题讨论】:

您能否发布示例代码来展示您如何尝试将它们结合起来? 【参考方案1】:

这有点棘手,但运行以下示例:

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

【讨论】:

谢谢,这行得通。我正在将根节点导入它自己的文档,而不是我试图将所有内容组合到的文档。有时午休可以解决一切。谢谢。【参考方案2】:

我知道你已经解决了这个问题,但我仍然想使用我目前正在测试的 XOM 库(与 this question 相关)来解决这个问题,并且在这样做的同时,提供与 Andreas_D 的答案不同的方法。

(为了简化此示例,我将您的 &lt;alert-set&gt;&lt;weather-set&gt; 放入单独的文件中,我将它们读入 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 来说非常简单。写这篇文章只花了几分钟,尽管我绝对不是对这个库非常有经验。 (如果没有 &lt;blank/&gt; 元素会更容易,即,只需从 &lt;DataSet&gt;&lt;/DataSet&gt; 开始。)

因此,除非您有令人信服的理由只使用标准 JDK 工具,否则我强烈建议您尝试 XOM,因为它可以使 Java 中的 XML 处理更加愉快。

【讨论】:

非常感谢。我最终在没有 元素的情况下这样做了,因为它们毫无意义......我只是想把我的头绕在 DOM 上。用 XOM 构建文档肯定比我做的要容易。我是一名实习生,所以我的脚刚刚湿透,但回顾过去,我已经可以看出我几周前编写的大部分代码都非常难看。从那以后,我学会了如何使用 XSLT 和 javax.xml.Transform,这让事情变得容易多了。再次感谢您的回复和 XOM 的链接。我相信我很快就会使用它。 很高兴能提供帮助 :) 如果没有 元素,您只需执行 root.appendChild(alertDoc.getRootElement().copy()) 等等。顺便说一下,看看xom.nu/apidocs/nu/xom/xslt/XSLTransform.html,看看 XOM 是否也可以帮助你处理 XSLT。

以上是关于Java 将 XML 文档附加到现有文档的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java DocumentBuilder 中解析 XSD 文件期间将元素附加到现有节点列表

将多个相似的 XML 节点附加到 XML 文档

如何使用 pymongo 将新的值数组附加到 mongodb 中的现有数组文档?

将节点插入另一个 XML,创建新元素(或更新现有元素)并重新排序结果文档

将 XML 保存到相对文件位置。

java - 如何将节点附加到Java中的现有XML文件