2016-04-20 4 views
2

はXMLの一種です:XMLファイルを参照してXML FILEは現在、私はこれで取り扱っておりますforeachループを使用してノードリストに新しいノードを追加しているXmlNodeList C#

場合、私は、ノードをチェックしますノードが見つからない場合、ノードをファイルに追加する必要があります。私は、次のコードを試してみました:

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回実行された後、このエラーが発生します。このエラーをどのように解決すればよいですか?

+1

このエラーは、_codeがコレクション_を列挙している間にコレクションを変更しようとしていると示していますが、これは許可されていません。 'foreach'の代わりに' for'を使ってみてください。 –

+0

@Hari Prasadあなたは、コード内のすべての反復に対して、すべての** foreach **ループを** **に**変更する必要があると言っていますか? 以前の** foreach **ループを**に変更しようとしましたが、エラーは同じです! –

+0

はい、少なくとも、これらのエラーが表示される場所。 –

答えて

1

あなたはここでは2つの問題があります。それらを反復しながら、あなたはあなたのXmlNodeListコレクションを変更している

  1. を。

    例外

    InvalidOperationException:列挙子を作成した後、コレクションが変更されたそれは、コレクションを反復処理中に変更されたときに例外をスローするためにマイクロソフトによって標準的な方法である、例えばIEnumerator.MoveNextのドキュメントを参照してください。

    この例外を回避するには、手動でXmlNodeList、またはsnapshot to a static List<T> and iterate through thatを通じてforループとインデックスを使用することができます。

  2. あなたは<DEFINITION-REF><FUNCTION-NAME-VALUE>という名前のXMLノードを探しているが、あなたは、この名前を持つノードを作成するもです。これは、反復の初期段階で作成したノードが反復処理の後半で見つかる可能性があり、ノードを再帰的に作成することを意味します。私はあなたがこれを望んでいないと思う。私の審判が正しい場合は、検索基準を満たすすべてのノードのスナップショットを作成する必要があり、そのようにように、スナップショットを反復処理:I count the number of XML nodes前と後の場合は、次に

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

    私が見る
    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); 
    

    その342ノードがXmlDocumentに追加されました。

+0

私はこれを私のコードで変更しようとしましたが、この時点ではエラーはありませんが、button12では** AddMissingNodes(doc)という**関数を呼び出しました。私のXMLファイルには何も変更が見られません –

+0

@ShreedharHegde - didファイルを保存するのを忘れないでください。提供したXMLファイルを使用して、私は342ノードが 'XmlDocument'に追加されたことを確認します。 – dbc

+0

** for **ループを使用してtradtionalメソッドを試しましたが、今度はそれぞれのノードをそれぞれの場所に追加することができます。新しく作成されたノードの名前空間はどのように設定する必要がありますか?私はまだコード内に名前空間を宣言していませんが、XMLにはすでに名前空間があります。私は、XMLの既存の名前空間を新しく作成したノードに設定したいと考えています。これで私を助けてくれますか? これは新しいノードの追加方法です。** ** XMLで** **のように表示されますが、 –

関連する問題