gpt4 book ai didi

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

转载 作者:数据小太阳 更新时间:2023-10-29 02:34:06 24 4
gpt4 key购买 nike

目前我正在处理的是 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 的标准做法是在迭代期间修改集合时抛出异常,例如参见 IEnumerator.MoveNext 的文档:

    Exceptions

    InvalidOperationException: The collection was modified after the enumerator was created.

    要避免此异常,您可以使用 for通过 XmlNodeList 循环和索引手动,或 snapshot to a static List<T> and iterate through that .

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

    然后,如果我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 个节点.

关于c# - 使用 foreach 循环和 XmlNodeList C# 将新节点附加到节点列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36740480/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com