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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/883987/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:39:04  来源:igfitidea点击:

Java appending XML docs to existing docs

javaxmlmergeappend

提问by ravun

I have two XML docs that I've created and I want to combine these two inside of a new envelope. So I have

我已经创建了两个 XML 文档,我想将这两个文档合并到一个新信封中。所以我有

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

and

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

What I'd like to do is combine the two inside a root node: < DataSet> combined docs < /DataSet>

我想做的是将两者结合在一个根节点中:<DataSet>combined docs</DataSet>

I've tried creating a temporary doc and replacing children with the root nodes of the documents:

我尝试创建一个临时文档并用文档的根节点替换子节点:

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

And I was hoping to replace the two blanks with the root elements of the two documents but I get "WRONG_DOCUMENT_ERR: A node is used in a different document than the one that created it." I tried adopting and importing the root nodes but I get the same error.

我希望用两个文档的根元素替换这两个空白,但我得到“WRONG_DOCUMENT_ERR:一个节点用在与创建它的文档不同的文档中。” 我尝试采用并导入根节点,但出现相同的错误。

Is there not some easy way of combining documents without having to read through and create new elements for each node?

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

EDIT: Sample code snippets Just trying to move one to the "blank" document for now... The importNode and adoptNode functions cannot import/adopt Document nodes, but they can't import the element node and its subtree... or if it does, it does not seem to work for appending/replacing still.

编辑:示例代码片段现在只是想将一个移到“空白”文档...确实如此,它似乎仍然不适用于附加/替换。

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

All of these throw the DOMException: WRONG_DOCUMENT_ERR: A node is used in a different document than the one that created it.

所有这些都会抛出 DOMException: WRONG_DOCUMENT_ERR: 一个节点在与创建它的文档不同的文档中使用。

I think I'll have to figure out how to use stax or just reread the documents and create new elements... That kinda seems like too much work just to combine documents, though.

我想我必须弄清楚如何使用 stax 或者只是重新阅读文档并创建新元素......不过,这似乎只是合并文档的工作太多了。

采纳答案by Andreas Dolk

It's a bit tricky, but the following example runs:

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

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

回答by Jonik

I know you got the issue solved already, but I still wanted to take a stab at this problem using the XOMlibrary that I'm currently testing out (related to this question), and while doing that, offer a different approach than that of Andreas_D's answer.

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

(To simplify this example, I put your <alert-set>and <weather-set>into separate files, which I read into nu.xom.Documentinstances.)

(为了简化这个例子,我把你的<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());

The key is to make a copy of the elements to be inserted into mainDoc; otherwise you'll get a complain that "child already has a parent".

关键是复制要插入的元素mainDoc;否则你会抱怨“孩子已经有父母了”。

Outputting mainDoc now gives:

现在输出 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>

To my delight, this turned out to be very straight-forward to do with XOM. It only took a few minutes to write this, even though I'm definitely notvery experienced with the library yet. (It would have been even easier without the <blank/>elements, i.e., starting with simply <DataSet></DataSet>.)

令我高兴的是,这对 XOM 来说非常直接。只用了几分钟的时间来写这篇文章,虽然我绝对很与库经历呢。(如果没有<blank/>元素会更容易,即从 simple 开始<DataSet></DataSet>。)

So, unless you have compelling reasons for using only the standard JDK tools, I warmly recommend trying out XOM as it can make XML handling in Java much more pleasant.

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