2016-04-20 6 views
2

В настоящее время я имею дело с этим типом XML: XML FILEдобавление нового узла к нодлисте с использованием цикла Еогеаспа и XmlNodeList C#

со ссылкой на файл 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

Эта ошибка говорит, что _code пытается изменить коллекцию при перечислении через collection_, что недопустимо. попробуйте использовать 'for' вместо' foreach'. –

+0

@Hari Prasad Вы хотите сказать, мне нужно изменить все ** foreach ** петли на ** для ** для всех итераций, которые в коде? Я попытался изменить первый цикл ** ** foreach ** на ** для ** ранее, но ошибка остается прежней! –

+0

Да, по крайней мере, места, где вы видите эти ошибки. –

ответ

1

У вас есть две проблемы здесь:

  1. Вы изменяющие свои XmlNodeList коллекции в то время как итерация через них. Это стандартная практика по Microsoft бросить исключение, если коллекция модифицируются во время итерации, смотрите, например, документацию для IEnumerator.MoveNext:

    Исключение

    InvalidOperationException: Коллекция была изменена после того, как был создан переписчик ,

    Чтобы избежать этого исключения, вы можете использовать for петли и индекс через XmlNodeList вручную или snapshot to a static List<T> and iterate through that.

  2. Вы ищете узлы XML имени <DEFINITION-REF> и <FUNCTION-NAME-VALUE>, но вы также создания узлов с этим именем. Это означает, что узлы, созданные на ранней стадии итерации, можно найти позже на итерации, что приведет к рекурсивному созданию еще большего числа узлов. Я полагаю, вы не хотите этого. Если моя расплата правильно, вы должны снимок всех узлов отвечают вашим критерии поиска, а затем перебирать снимки, например, так:

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

    Тогда, если я count the number of XML nodes до и после:

    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 узла.

+0

Я попытался изменить это в своем коде и вызвал функцию ** AddMissingNodes (doc); ** в кнопке12, хотя на этот раз ошибок нет, я не вижу никаких изменений в файле XML –

+0

@ShreedharHegde - сделал вы не забыли сохранить файл? Используя предоставленный XML-файл, я вижу, что в «XmlDocument» было добавлено 342 узла. – dbc

+0

Я пробовал метод tradtional, используя ** для цикла **, теперь я могу добавить соответствующий узел в соответствующее место. Как мне задать пространство имен для вновь созданных узлов? Я еще не объявил какое-либо пространство имен в моем коде, но у моего XML уже есть пространство имен. Я хочу установить существующее namspace XML для вновь созданного узла. Не могли бы вы помочь мне в этом? Прямо сейчас, когда новый узел добавлен ** ** Я хочу, чтобы это было видимым в моем XML как ** **, но оно должно иметь пространство имен XML по умолчанию –