SelectNodes () is a Microsoft extension for the Document Object Model (DOM) ( msdn ). SelectNodes, as Welbog mentions, and others accept an XPath expression. I would like to mention the difference with GetElementsByTagName () when xml node removal is required.
Answer and provided chilberto user code in msdn forum
The following test illustrates the difference by performing the same function (deleting human nodes), but using the GetElementByTagName () method to select the nodes. Although the same type of object is returned, its design is different. SelectNodes () is a collection of links to an xml document. This means that we can remove from the document in foreach without affecting the list of links. This is evidenced by the calculation of the nodelist, which is not affected. GetElementByTagName () is a collection that directly reflects the nodes in the document. This means that when deleting elements in the parent element, we actually affect the set of nodes. This is why the nodelist cannot be manipulated in foreach, but it needs to be changed to a while loop.
.NET SelectNodes ()
[TestMethod] public void TestSelectNodesBehavior() { XmlDocument doc = new XmlDocument(); doc.LoadXml(@"<root> <person> <id>1</id> <name>j</name> </person> <person> <id>2</id> <name>j</name> </person> <person> <id>1</id> <name>j</name> </person> <person> <id>3</id> <name>j</name> </person> <business></business> </root>"); XmlNodeList nodeList = doc.SelectNodes("/root/person"); Assert.AreEqual(5, doc.FirstChild.ChildNodes.Count, "There should have been a total of 5 nodes: 4 person nodes and 1 business node"); Assert.AreEqual(4, nodeList.Count, "There should have been a total of 4 nodes"); foreach (XmlNode n in nodeList) n.ParentNode.RemoveChild(n); Assert.AreEqual(1, doc.FirstChild.ChildNodes.Count, "There should have been only 1 business node left in the document"); Assert.AreEqual(4, nodeList.Count, "There should have been a total of 4 nodes"); }
.NET GetElementsByTagName ()
[TestMethod] public void TestGetElementsByTagNameBehavior() { XmlDocument doc = new XmlDocument(); doc.LoadXml(@"<root> <person> <id>1</id> <name>j</name> </person> <person> <id>2</id> <name>j</name> </person> <person> <id>1</id> <name>j</name> </person> <person> <id>3</id> <name>j</name> </person> <business></business> </root>");; XmlNodeList nodeList = doc.GetElementsByTagName("person"); Assert.AreEqual(5, doc.FirstChild.ChildNodes.Count, "There should have been a total of 5 nodes: 4 person nodes and 1 business node"); Assert.AreEqual(4, nodeList.Count, "There should have been a total of 4 nodes"); while (nodeList.Count > 0) nodeList[0].ParentNode.RemoveChild(nodeList[0]); Assert.AreEqual(1, doc.FirstChild.ChildNodes.Count, "There should have been only 1 business node left in the document"); Assert.AreEqual(0, nodeList.Count, "All the nodes have been removed"); }
Using SelectNodes () we get a collection / list of links to the nodes of the XML document. We can manipulate these links. If we remove the node, the change will be visible for the xml document, but the collection / list of links will be the same (although the node that was deleted now points to null -> System.NullReferenceException) Although I do not know how this is implemented. I suppose if we use XmlNodeList nodeList = GetElementsByTagName () and remove the node with nodeList [i] .ParentNode.RemoveChild (nodeList [i]) frees / removes the link in the nodeList variable.