4
        string XML1 = "<Root><InsertHere></InsertHere></Root>";
        string XML2 = "<Root><child1><childnodes>data</childnodes><childnodes>data1</childnodes></child1><child2><childnodes>data</childnodes><childnodes>data1</childnodes></child2></Root>";

以下に示す2つのコードサンプルのうち、childNodesを使用しても、XML2からすべての子ノードがコピーされるわけではありません。<child1>コピーされているだけです。

        string strXpath = "/Root/InsertHere";

        XmlDocument xdxmlChildDoc = new XmlDocument();
        XmlDocument ParentDoc = new XmlDocument();
        ParentDoc.LoadXml(XML1);
        xdxmlChildDoc.LoadXml(XML2);

        XmlNode xnNewNode = ParentDoc.ImportNode(xdxmlChildDoc.DocumentElement.SelectSingleNode("/Root"), true);

        if (xnNewNode != null)
        {
            XmlNodeList xnChildNodes = xnNewNode.SelectNodes("/*");
            if (xnChildNodes != null)
            {
                foreach (XmlNode xnNode in xnChildNodes)
                {
                    if (xnNode != null)
                    {
                        ParentDoc.DocumentElement.SelectSingleNode(strXpath).AppendChild(xnNode);
                    }
                }
            }
        }

code2:

    if (xnNewNode != null)
    {
        XmlNodeList xnChildNodes = xnNewNode.ChildNodes;
        if (xnChildNodes != null)
        {
            foreach (XmlNode xnNode in xnChildNodes)
            {
                if (xnNode != null)
                {
                    ParentDoc.DocumentElement.SelectSingleNode(strXpath).AppendChild(xnNode);
                }
            }
        }
    }

コードの最初のサンプルを実行した後のParentDoc.OuterXML:

<Root>
    <InsertHere>
        <child1>
            <childnodes>data</childnodes>
            <childnodes>data1</childnodes>
        </child1>
        <child2>
            <childnodes>data</childnodes>
            <childnodes>data1</childnodes>
        </child2>
    </InsertHere>
</Root>

コードの2番目のサンプルを実行した後のParentDoc.OuterXML

<Root>
    <InsertHere>
        <child1>
            <childnodes>data</childnodes>
            <childnodes>data1</childnodes>
        </child1>
    </InsertHere>
</Root>
4

4 に答える 4

3

コードのデバッグを行ったところ、xnNewNode.ChildNodes最初は 2 つの子ノードも返されることがわかりました。ただし、ループの 1 回の反復の後、最初の子は から削除されるChildNodesため、ループは途中で終了します。

このプロパティを使用する場合のChildNodes回避策の 1 つは、次のように、子ノードの参照を配列またはリストに「転送」することです。

var xnChildNodes = xnNewNode.ChildNodes.Cast<XmlNode>().ToArray();

アップデート

Tomer W が彼の回答で指摘したように、XmlNode.AppendChildを使用すると、挿入されたノードも元の場所から削除されます。MSDNのドキュメントに記載されているように:

If the newChild is already in the tree, it is removed from 
its original position and added to its target position.

SelectNodes新しいノード コレクションは既に作成されていますChildNodesが、元のコレクションにアクセスしています。

于 2012-06-28T06:45:28.667 に答える
1

これは、Anders G が投稿した内容のクリアリングであり、より多くの説明が含まれています。

この状況で foreach が失敗 (Throw Exception) しないことに驚いていますが、地獄です。

コード 1 で。
1. ノードの新しいコレクションを作成します
2. それにノードを選択し
ます 3. 他のノードに追加 => 元のコレクションから削除しますが、新しく作成されたコレクションは削除しません。
4 新しいコレクションから追加するノードを削除しています。

コード 2 で
1. 元のノード コレクション
{child1, child2} を参照し
ます。 2. 1 番目のノードを別のコレクションに追加 => 元のコレクション
{child2}から削除します。コレクションの終わり。そして終了します。

これは、反復の対象となるコレクションを変更するときによく発生します。
しかし、ほとんどの場合、IEnumerator は例外が発生したときに例外をスローしています。

私はそれをすべて明確にしたことを願っています

于 2012-06-28T06:59:48.000 に答える
1

私は同じ問題を抱えていて、空白ノードにノードに値が付加されているように見えることを観察しましたが、これは他のノードには当てはまりません (少なくとも私のアプリケーションでは)。このメソッドは、node.ChildNodes リストから空白ノードを削除します。

private List<XmlNode> findChildnodes(XmlNode node)
    {
        List<XmlNode> result = new List<XmlNode>();
        foreach (XmlNode childnode in node.ChildNodes) 
        {
            if(childnode.Value == null)
            {
                result.Add(childnode);
            }
        }
        return result;
    }
于 2012-09-18T11:11:13.447 に答える
0

あなたの質問に答えて、Node.childNodesすべての子ノードですが、Node.SelectNodes(/*)はに一致するすべての子ノードです/*。XML要素のみが一致/*するため、属性、CDATAノード、テキストノードなどはすべて除外されます。

それでも、ノードを反復処理しているときにノードのコレクションを変更しているため、問題が発生します。それをしてはいけない。select ノードメソッドは、ノードへの参照のリストを返します。これが作品である理由です。

于 2012-06-28T06:56:44.200 に答える