Currently I am dealing with this is the type of XML: XML FILE
With reference to the XML file, I want to check for a node, if the node is not found, I have to append the node to the file. I have tried the following code:
private void button12_Click(object sender, EventArgs e)
{
// XmlNodeList func_name_value = doc.GetElementsByTagName("FUNCTION-NAME-VALUE");
XmlNodeList list_def_ref = doc.GetElementsByTagName("DEFINITION-REF");
foreach (XmlNode nodeDef in list_def_ref)
{
if (nodeDef.InnerText == "/AUTOSAR/Com/ComConfig/ComSignal")
{
if (nodeDef.ParentNode.HasChildNodes)
{
XmlNodeList list = nodeDef.ParentNode.ChildNodes;
foreach (XmlNode node in list)
{
if (node.Name == "PARAMETER-VALUES")
{
XmlNodeList param_list = node.ChildNodes;
foreach (XmlNode paramNode in param_list)
{
if (paramNode.Name == "FUNCTION-NAME-VALUE")
{
XmlNodeList func_child_list = paramNode.ChildNodes;
foreach (XmlNode funChild in func_child_list)
{
if (funChild.Name == "DEFINITION-REF")
{
string tout = "/AUTOSAR/Com/ComConfig/ComSignal/ComTimeoutNotification";
string comnotify = "/AUTOSAR/Com/ComConfig/ComSignal/ComNotification";
string invalid = "/AUTOSAR/Com/ComConfig/ComSignal/ComInvalidNotification";
if (funChild.InnerText != tout)
{
if (funChild.InnerText != comnotify)
{
//ADD ComInvalidNotification tags
XmlNode newNode = doc.CreateElement("FUNCTION-NAME-VALUE");
paramNode.AppendChild(newNode);
XmlNode defRefNode = doc.CreateElement("DEFINITION-REF");
XmlAttribute attr = doc.CreateAttribute("DEST");
attr.Value = "FUNCTION-NAME-DEF";
defRefNode.Attributes.SetNamedItem(attr);
newNode.AppendChild(defRefNode);
XmlNode val = doc.CreateElement("VALUE");
val.InnerText = "ComInvalidNotification";//ComInvalidNotification + shortName ;
newNode.AppendChild(val);
}
else
{
//ADD ComNotification tags
XmlNode newNode = doc.CreateElement("FUNCTION-NAME-VALUE");
paramNode.AppendChild(newNode);
XmlNode defRefNode = doc.CreateElement("DEFINITION-REF");
XmlAttribute attr = doc.CreateAttribute("DEST");
attr.Value = "FUNCTION-NAME-DEF";
defRefNode.Attributes.SetNamedItem(attr);
newNode.AppendChild(defRefNode);
XmlNode val = doc.CreateElement("VALUE");
val.InnerText = "ComNotification Node";//ComNotification + shortName;
newNode.AppendChild(val);
}
}
else
{
//ADD ComTimeOutNotification tags
XmlNode newNode = doc.CreateElement("FUNCTION-NAME-VALUE");
paramNode.AppendChild(newNode);
XmlNode defRefNode = doc.CreateElement("DEFINITION-REF");
XmlAttribute attr = doc.CreateAttribute("DEST");
attr.Value = "FUNCTION-NAME-DEF";
defRefNode.Attributes.SetNamedItem(attr);
newNode.AppendChild(defRefNode);
XmlNode val = doc.CreateElement("VALUE");
val.InnerText = "ComTimeoutNotification node";//ComInvalidNotification + shortName;
newNode.AppendChild(val);
}
}
}
}
}
}
}
}
}
}
doc.Save(openFileDialog1.FileName);
The Error I am getting is: the element list has changed. the enumeration operation failed to continue.
After the 1st execution of the foreach loop, I am getting this error, how should I overcome this error?
You have two problems here:
You are modifying your
XmlNodeList
collections while iterating through them. It is standard practice by Microsoft to throw an exception when a collection is modified during iteration, see for instance the documentation forIEnumerator.MoveNext
:To avoid this exception, you can use a
for
loop and index through theXmlNodeList
manually, or snapshot to a staticList<T>
and iterate through that.You are searching for XML nodes named
<DEFINITION-REF>
and<FUNCTION-NAME-VALUE>
, but you are also creating nodes with this name. This means that nodes you create early in the iteration might be found later in the iteration, causing recursive creation of even more nodes. I reckon you do not want this. If my reckoning is correct, you should snapshot all nodes meeting your search criteria, then iterate through the snapshots, like so:Then, if I count the number of XML nodes before and after:
I see that 342 nodes were added to the
XmlDocument
.