Reputation: 402
I'm trying to delete every note with type"deletable", but after it has hit 1 deletable, the foreach stops. In this case, only passing test2.exe and test.exe.
This is what my XML file looks like:
<folder name="bin">
<file name="test2.exe" type="undeletable">test</file>
<file name="test.exe" type="deletable">test</file>
<file name="test1.exe" type="deletable">test</file>
<file name="kernel.sys" type="undeletable">test</file>
</folder>
And this the C#:
XmlNodeList fileNodeLIst = fileNode.SelectNodes("file");
foreach(XmlNode file in fileNodeLIst) {
if (file.Attributes["type"].Value == "undeletable") {
TerminalSystemAddMessage("Error: Unable to delete " + file.Attributes["name"].Value);
} else if (file.Attributes["type"].Value == "deletable") {
file.ParentNode.RemoveChild(file);
TerminalSystemAddMessage("Deleted: " + file.Attributes["name"].Value);
}
}
Am I doing something wrong? Why is the foreach loop breaking and how can I fix it?
Upvotes: 0
Views: 840
Reputation: 117084
You might find this approach to be cleaner:
var messages =
(
from file in fileNode.SelectNodes("file").Cast<XmlNode>()
let deletable = file.Attributes["type"].Value == "deletable"
let name = file.Attributes["name"].Value
select String.Format(
deletable
? "Deleted: {0}"
: "Error: Unable to delete {0}",
name)
).ToList();
var deletables =
(
from file in fileNode.SelectNodes("file").Cast<XmlNode>()
where file.Attributes["type"].Value == "deletable"
select file
).ToList();
deletables.ForEach(file => file.ParentNode.RemoveChild(file));
messages.ForEach(message => TerminalSystemAddMessage(message));
This separates the deleting of the node from the iterating through the list - so stops the problem you're experiencing.
Upvotes: 0
Reputation: 66
Use "for" iteration statement instead of "foreach" iteration statement like lines below:
XmlNodeList fileNodeLIst = fileNode.SelectNodes("file");
for(int iNode = fileNodeList.Count - 1; iNode >= 0; iNode --)
{
XmlNode file = fileNodeLIst[iNode];
if(file.Attributes["type"].Value == "undeletable"){
TerminalSystemAddMessage("Error: Unable to delete " + file.Attributes["name"].Value);
}else if(file.Attributes["type"].Value == "deletable"){
file.ParentNode.RemoveChild(file);
TerminalSystemAddMessage("Deleted: " + file.Attributes["name"].Value);
}
}
The foreach statement repeats a group of embedded statements for each element in an array or an object collection that implements the System.Collections.IEnumerable or System.Collections.Generic.IEnumerable interface. The foreach statement is used to iterate through the collection to get the information that you want, but can not be used to add or remove items from the source collection to avoid unpredictable side effects. If you need to add or remove items from the source collection, use a for loop. source: https://msdn.microsoft.com/en-us/library/ttw7t8t6.aspx
Upvotes: 2