Click here to Skip to main content
15,891,136 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hello,

I am trying to delete the child nodes of a node. During the execution of the foreach loop I am having an error- "The element list has changed. The enumeration operation failed to continue." I think because I am changing the XMLfile I am having that error but dont know how to fix it. Can someone correct my code?

MSIL
XmlDocument xmlDocument = new XmlDocument();
           xmlDocument.Load(@"C:\Users\Orcun Iyigun\Desktop\Projects\Rules.xml");

           XmlNodeList ratingNodes = xmlDocument.GetElementsByTagName("Rule/Rating");
           XmlNodeList mailtoNodes = xmlDocument.GetElementsByTagName("Rule/Mailto");
           XmlNodeList ruleNodes = xmlDocument.GetElementsByTagName("Rule");
           
           foreach (ListViewItem item in lvRules.Items)
           {
               if (item.Selected)
               {
                   string ratingVal = item.SubItems[0].Text;
                   string mailtoVal = item.SubItems[1].Text;
                   string ratmailNode = ratingVal + mailtoVal;


                   foreach (XmlNode deleteXMLnode in ruleNodes)
                   {
                       if (deleteXMLnode.InnerText == ratmailNode)
                       {
                           deleteXMLnode.ParentNode.RemoveChild(deleteXMLnode);
                       }
                   }
                   lvRules.Items.Remove(item);
               }
           }
           xmlDocument.Save(@"C:\Users\Orcun Iyigun\Desktop\Projects\Rules.xml");
Posted
Updated 19-Oct-20 0:01am
v2

You can convert the foreach into a for loop, but even then every time you call RemoveChild, you must adjust the loop variable if you are using a cached length condition to exit the for loop.

Actually, even if you do not cache the for-condition, you still need to adjust the loop variable. For an example, see the code snippet below:

C#
var list = new int[] { 1, 2, 3, 4, 8, 6, 7, 5 }.ToList();
for (int i = 0; i < list.Count; i++)
{
    if (list[i] % 2 == 0)
        list.RemoveAt(i--); // <-- see what I did here!
}

foreach (var item in list)
{
    Console.WriteLine(item);
}
 
Share this answer
 
v3
Comments
Hiren solanki 3-Nov-10 1:40am    
Good Explanation Nish.
Orcun Iyigun 3-Nov-10 16:50pm    
thanks I will try and see if it works.
Your problem is that you are getting the ListViewItemCollection at the start of the foreach loop.
You need to get the ListViewItemsCollection before starting the loop.
C#
ListView.ListViewItemCollection lvIC = lvRules.Items;
foreach (ListViewItem item in lvIC)
{
    .
    .
    .
    lvRules.Items.Remove(item);
}

This is why when looping through item collections you don't make the call to get the collection a part of the loop.

For the second foreach loop you need to change how you get the rule nodes use SelectNodes with an XPath query instead like;
XmlNodeList ruleNodes = xmlDocument.SelectNodes("doc/Rule");
 
Share this answer
 
v4
Comments
Orcun Iyigun 3-Nov-10 11:44am    
Still I am having the same error on the inner(second) foreach loop. I have changed the first foreach loop as you said but it is not working.
hatelove420 9-Feb-13 4:41am    
i got the same problem can any one be clear to explain the above problem
Changing the selection from GetElementsByTagName to SelectNodes worked for me. Apparently the GetElementsByTagName method changes the result of the IEnumerable during the loop (if you debug, you'll see the count of items decrease) but the SelectNodes result stays the same.

private XmlDocument RemoveDrawingNodes(XmlDocument xmlDocument)
{
    var drawingNodes = xmlDocument.SelectNodes("//w:drawing", XmlNamespaceManager);

    foreach (XmlElement element in drawingNodes)
    {
        element.ParentNode.RemoveChild(element);
    }
    return xmlDocument;
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900