之前操作XML文档基本上用的是XmlDocument对象,对一些小文件的操作使用还挺顺手,今天偶尔用来操作一个4M的XML文件,发现查询指定的节点并删除时执行时间很长。在Web项目下和控制台程序中都出现很长时间程序无响应,并且CPU占用很高。不知道是我写的代码有问题还是本身这个对象不适合操作打文件呢?我的代码如下:
1 XmlDocument xmlDocument = new XmlDocument(); 2 xmlDocument.Load(ConfigFilePath); 3 XmlNodeList nodeList = xmlDocument.SelectNodes("/System/add"); 4 foreach (XmlNode node in nodeList) 5 { 6 if (node.Attributes["key"] != null) 7 { 8 if (node.Attributes["key"].Value.Equals(key, StringComparison.CurrentCultureIgnoreCase)) 9 { 10 node.RemoveAll(); 11 12 } 13 } 14 }
就是查询根节点System下add子节点,如果该节点的key属性和指定的属性相等,则删除此节点。经过运行发现,我的一个4M大的文件大概1万个节点,执行起来一直无响应。希望高手能给个解答。
后来考虑到是操作XML文件,于是想起用LINQ TO XML来实现,同样的功能我实现如下:
XElement rootNodes = XDocument.Load(ConfigFilePath).Root; rootNodes.Elements("add").Where(el => el.Attribute("key").Value.Equals(key)).Remove();
经测试,该方法指定时间仅仅在200毫秒左右,简直不是一个数量级别的。
同样的一个园友用以下方法实现删除功能:
1 private static void DeleteXmlNodeInformation(string xmlPath) 2 { 3 try 4 { 5 //定义并从xml文件中加载节点(根节点) 6 XElement rootNode = XElement.Load(xmlPath); 7 //查询语句: 获取ID属性值等于"999999"的所有User节点 8 IEnumerable<XElement> targetNodes = from target in rootNode.Descendants("User") 9 where target.Attribute("ID").Value.Equals("999999") 10 select target; 11 12 //将获得的节点集合中的每一个节点依次从它相应的父节点中删除 13 targetNodes.Remove(); 14 //保存对xml的更改操作 15 rootNode.Save(xmlPath); 16 } 17 catch (Exception ex) 18 { 19 Console.WriteLine(ex.ToString()); 20 } 21 }
未通过调试,一直提示没有父节点,不知道是怎么回事。下面给出详细代码:
1 //xml文件路径 2 string ConfigFilePath = AppDomain.CurrentDomain.BaseDirectory + "Profile.config"; 3 //初始化XElement对象 4 XElement rootNodes = XDocument.Load(ConfigFilePath).Root; 5 6 rootNodes 7 .Elements("add") //查询根节点下所有add子节点 8 .Where( 9 el => 10 el.Attribute("value").Value //Where方法中用于筛选复核条件的节点 11 .Equals("d")) 12 .First() //可以实现只删第一条 13 .Remove();//删除节点 14 15 //实现删除查询结果中指定索引的一个节点可以如下实现: 16 rootNodes 17 .Elements("add") //查询根节点下所有add子节点 18 .Where( 19 el => 20 el.Attribute("value").Value //Where方法中用于筛选复核条件的节点 21 .Equals("d")) 22 .Skip(10) //跳过指定的条数,这里可以实现删除指定的某一个节点 23 .First() //跳过指定条数后获取剩余的第一个节点 24 .Remove(); //删除节点 25 26 rootNodes.Save(ConfigFilePath);//保存到文件