"; string XML2 = "

What is the difference between Node.SelectNodes (/ *) and Node.childNodes?

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

Among the two code examples below. using childNodes does not copy all child nodes from XML2. only <child1> copied.

  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 after executing the first code sample:

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

ParentDoc.OuterXML after executing the second code sample

 <Root> <InsertHere> <child1> <childnodes>data</childnodes> <childnodes>data1</childnodes> </child1> </InsertHere> </Root> 
+4
source share
4 answers

this is an explanation of what Anders G posted, with a more detailed explanation.

I am surprised that foreach does not fail (Throw Exception) in this situation, but hell.

In code 1.
1. Create a NEW COLLECTION of Nodes
2. Select nodes in it
3. add to another node => deletion from the original collection, but not to the newly created one.
4 you remove the node that you are adding from the new collection.

in Code2
1. Link to the original collection node {child1, child2}
2. add the 1st node to another collection => removing it from the original collection
{} Child2 3. Now that foreach is at index 1, he sees that he has passed the end of the collection. and exit.

This happens very often when changing collections that are subject to iteration.
but in most cases, IEnumerator throws an exception when this happens.

hope i made everything clear

+1
source

I did some debugging of the code and it shows that xnNewNode.ChildNodes initially also returns 2 child nodes. After one iteration in the loop, the first child, however, is removed from ChildNodes , and therefore the loop ends prematurely.

If you want to use the ChildNodes property, one of the ways is to "pass" the node's child links to an array or list, for example:

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

UPDATE

As Tomer W pointed out in his answer, when using XmlNode.AppendChild, the inserted node is also removed from the original location. As indicated in the MSDN documentation:

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

With SelectNodes you have already created a new node collection, but with ChildNodes you get access to the original collection.

+3
source

I had the same problem and it was observed that the white nodes seem to have a value attached to the node, which does not apply to other nodes (at least in my application). This method removes space nodes from node. ChildNodes List:

 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; } 
+1
source

In answer to your question, Node.childNodes contains All child nodes, while Node.SelectNodes(/*) is all child nodes that match /* . Only XML elements will match /* , so any attributes, CDATA nodes, text nodes, etc. Will be excluded.

However, the problem arises because you are changing the collection of nodes during iteration over them. You cannot do this. The select nodes method returns a list of links to nodes. That is why they work.

0
source

All Articles