2009-05-19 110 views
17

我有两个XML文档是我创建的,我想将这两个文档合并到一个新的信封中。所以,我有将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和adoptNode函数不能导入/采用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 2009-05-19 17:29:53

回答

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 2009-05-19 19:23:29

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元素的副本;否则你会抱怨“孩子已经有了父母”。

1.4.3 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,因为它可以使Java中的XML处理更加愉快。

+0

非常感谢。因为他们毫无意义,所以我最终没有使用这个元素......我只是想把自己的头围绕在DOM上。 使用XOM构建文档绝对看起来比我所做的要容易。我是一名实习生,所以我只是浑身湿透,但回想起来,我已经可以告诉大部分我几周前写的代码非常难看。 我已经学会了如何使用XSLT和javax.xml.Transform,这使事情变得更容易。 再次感谢您的回复并链接到XOM。我相信我会很快使用它。 – ravun 2009-06-09 14:17:43

相关问题