3

現在、私が扱っているのは 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 ループを最初に実行した後、このエラーが発生しました。このエラーを解決するにはどうすればよいですか?

4

1 に答える 1

2

ここには 2 つの問題があります。

  1. XmlNodeListコレクションを繰り返しながらコレクションを変更しています。反復中にコレクションが変更されたときに例外をスローすることは、Microsoft による標準的な方法です。たとえば、次のドキュメントを参照してくださいIEnumerator.MoveNext

    例外

    InvalidOperationException: 列挙子の作成後にコレクションが変更されました。

    この例外を回避するには、手動でforループとインデックスを使用するか、スナップショットを静的に使用してそれを反復処理します。XmlNodeListList<T>

  2. <DEFINITION-REF>およびという名前の XML ノードを検索していますが、この名前のノード<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);
        }
    }
    

    次に、前後の 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);
    

    に 342 個のノードが追加されていることがわかりますXmlDocument

于 2016-04-20T18:51:10.270 に答える