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>";
在下面提到的两个代码示例中.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);
}
}
}
}
码2:
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>
执行Code 的第二个示例后,ParentDoc.OuterXML
<Root>
<InsertHere>
<child1>
<childnodes>data</childnodes>
<childnodes>data1</childnodes>
</child1>
</InsertHere>
</Root>
答案 0 :(得分:3)
我已经对代码进行了一些调试,它表明xnNewNode.ChildNodes
最初也会返回2个子节点。在循环中进行一次迭代后,第一个子项将从ChildNodes
中删除,因此循环过早结束。
如果要使用ChildNodes
属性,一种解决方法是将子节点引用“转移”到数组或列表,如下所示:
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
您正在访问原始集合。
答案 1 :(得分:1)
这是Anders G发布的内容的清除,更多的解释。
我很惊讶foreach在这种情况下没有失败(抛出异常),但是地狱。
在code1。
1.创建新的节点集合
2.选择节点
3.追加到其他节点=&gt;从原始集合中删除,但不删除新创建的集合
4您要从新集合中删除要添加的节点。
1.引用ORIGINAL节点集合
{child1,child2}
2.将第一节点附加到另一个集合=&gt;将其从原始集合中删除
{}的child2
3.现在当foreach在索引1时,它看到它通过了集合的结尾。并退出。
在更改受迭代影响的集合时会发生很多这种情况 但大多数时候,IEnumerator会在发生这种情况时抛出异常。
希望我一切都清楚答案 2 :(得分:1)
我遇到了同样的问题并观察到,空白节点似乎有一个附加到节点的值,而其他节点则不然(至少在我的应用程序中)。这个方法从节点中删除了空白节点。 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;
}
答案 3 :(得分:0)
在回答您的问题时,Node.childNodes
是全部的子节点,而Node.SelectNodes(/*)
是与/*
匹配的所有子节点。只有XML元素匹配/*
,因此将排除任何属性,CDATA节点,文本节点等。
然而,问题出现的原因是您在迭代节点时更改节点集合。你不能这样做。 select nodes方法返回节点的引用列表。这就是为什么有效。