目前我正在处理的是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循环的第一次执行之后,我得到了这个错误,我应该如何克服这个错误?
这里有两个问题:
-
您正在修改
XmlNodeList
集合,同时对它们进行迭代。Microsoft的标准做法是在迭代过程中修改集合时抛出异常,例如参见IEnumerator.MoveNext
:的文档异常
InvalidOperationException
:在创建枚举器后修改了集合。为了避免此异常,您可以手动使用
for
循环并索引XmlNodeList
,或者快照到静态List<T>
并迭代。 -
您正在搜索名为
<DEFINITION-REF>
和<FUNCTION-NAME-VALUE>
的XML节点,但也在创建具有此名称的节点。这意味着在迭代早期创建的节点可能会在迭代后期找到,从而导致递归创建更多的节点。我想你不想要这个。如果我的计算是正确的,你应该快照所有符合搜索条件的节点,然后迭代快照,如下所示: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:TempQuestion36740480autosar_ecucvalues_Fx4_L.xml"; var newFileName = @"D:TempQuestion36740480autosar_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
中。