18

作成した 2 つの XML ドキュメントがあり、これら 2 つを新しいエンベロープ内で結合したいと考えています。ので、私は持っています

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

私がやりたいのは、ルート ノード内で 2 つを結合することです。

一時的なドキュメントを作成し、子をドキュメントのルート ノードに置き換えてみました。

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

そして、2 つの空白を 2 つのドキュメントのルート要素に置き換えたいと思っていましたが、「WRONG_DOCUMENT_ERR: ノードは、それを作成したドキュメントとは別のドキュメントで使用されています。」というメッセージが表示されます。ルート ノードを採用してインポートしようとしましたが、同じエラーが発生します。

ノードごとに新しい要素を読んで作成することなく、ドキュメントを結合する簡単な方法はありませんか?

編集: サンプル コード スニペット 1 つを「空白の」ドキュメントに移動しようとしているだけです... importNode および adaptNode 関数はドキュメント ノードをインポート/採用できませんが、要素ノードとそのサブツリーをインポートできません... またはそれは、まだ追加/置換には機能していないようです。

    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 の使い方を理解するか、ドキュメントを読み直して新しい要素を作成する必要があると思います。ドキュメントを結合するだけでも、ちょっと大変な作業のように思えます。

4

2 に答える 2

29

少しトリッキーですが、次の例が実行されます。

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));   
}
于 2009-05-19T18:31:29.943 に答える
7

問題はすでに解決されていると思いますが、現在テストしている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ツールのみを使用するやむを得ない理由がない限り、JavaでのXML処理をはるかに快適にするXOMを試してみることを強くお勧めします。

于 2009-06-08T20:38:14.253 に答える