使用foreach循环和XmlNodeList C#将新节点附加到节点列表

目前我正在处理这是XML的类型: XML FILE

参考XML文件,我想检查节点,如果找不到节点,我必须将节点附加到文件。 我试过以下代码:

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

我得到的错误是: 元素列表已更改。 枚举操作无法继续。

在第一次执行foreach循环后,我收到此错误,我该如何克服此错误?

你有两个问题:

  1. 您正在修改XmlNodeList集合,同时迭代它们。 Microsoft在迭代期间修改集合时抛出exception是标准做法,例如,请参阅IEnumerator.MoveNext的文档:

    例外

    InvalidOperationException :在创建枚举数后修改了集合。

    要避免此exception,您可以手动使用for循环和索引通过XmlNodeList ,或者使用快照到静态List并迭代它 。

  2. 您正在搜索名为 XML节点,但您也在创建具有此名称的节点。 这意味着您在迭代早期创建的节点可能会在迭代后期找到,从而导致更多节点的递归创建。 我估计你不想要这个。 如果我的计算是正确的,您应该快照所有满足搜索条件的节点,然后遍历快照,如下所示:

     private static void AddMissingNodes(XmlDocument doc) { var query = from nodeDef in doc.GetElementsByTagName("DEFINITION-REF").Cast() where nodeDef.InnerText == "/AUTOSAR/Com/ComConfig/ComSignal" from nodeDefSibling in nodeDef.ParentNode.ChildNodes.Cast() where nodeDefSibling.Name == "PARAMETER-VALUES" from paramNode in nodeDefSibling.ChildNodes.Cast() where paramNode.Name == "FUNCTION-NAME-VALUE" select new { paramNode = paramNode, func_child_list = (from funChild in paramNode.ChildNodes.Cast() where funChild.Name == "DEFINITION-REF" select funChild).ToList() // Snapshot func_child_list by calling ToList() }; foreach (var paramNodeAndFuncChildren in query.ToList()) // Snapshot everything by calling ToList() foreach (var funChild in paramNodeAndFuncChildren.func_child_list) AddMissingNodes(doc, paramNodeAndFuncChildren.paramNode, funChild); } private static void AddMissingNodes(XmlDocument doc, XmlNode paramNode, XmlNode funChild) { 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); } } 

    然后,如果我计算之前和之后的XML节点数 :

      var fileName = @"D:\Temp\Question36740480\autosar_ecucvalues_Fx4_L.xml"; var newFileName = @"D:\Temp\Question36740480\autosar_ecucvalues_Fx4_L_NEW.xml"; var doc = new XmlDocument(); doc.Load(fileName); int countBefore = doc.SelectNodes("descendant::*").Count; AddMissingNodes(doc); int countAfter = doc.SelectNodes("descendant::*").Count; Debug.WriteLine(string.Format("Added {0} nodes", countAfter - countBefore)); doc.Save(newFileName); Debug.WriteLine("Wrote: " + newFileName); 

    我看到在XmlDocument中添加了342个节点。