在C#中更改元素值的最佳方法

我正在尝试查看更改XML中元素值的最佳方法。

 Value  

在C#中改变“价值”的最简单和/或最好的方法是什么?

我查看了XMLDocument,它将导致整个XML文档加载到内存中。 你能用XMLReader安全地完成吗? 问题在于改变价值并将其发回似乎是一个有趣的难题。

干杯:D

您可以使用System.Xml.Linq命名空间的东西来获得最简单的代码。 这会将整个文件加载到内存中。

 XDocument xdoc = XDocument.Load("file.xml"); var element = xdoc.Elements("MyXmlElement").Single(); element.Value = "foo"; xdoc.Save("file.xml"); 

编辑:没有看到关于XmlDocument的条款。 XmlReader就是这么做的。 您无法使用此类编辑xml文件。

你想要XmlWriter。 但是,如果它仍然有用,这里是XmlDocument的代码。

 private void changeXMLVal(string element, string value) { try { string fileLoc = "PATH_TO_XML_FILE"; XmlDocument doc = new XmlDocument(); doc.Load(fileLoc); XmlNode node = doc.SelectSingleNode("/MyXmlType/" + element); if (node != null) { node.InnerText = value; } else { XmlNode root = doc.DocumentElement; XmlElement elem; elem = doc.CreateElement(element); elem.InnerText = value; root.AppendChild(elem); } doc.Save(fileLoc); doc = null; } catch (Exception) { /* * Possible Exceptions: * System.ArgumentException * System.ArgumentNullException * System.InvalidOperationException * System.IO.DirectoryNotFoundException * System.IO.FileNotFoundException * System.IO.IOException * System.IO.PathTooLongException * System.NotSupportedException * System.Security.SecurityException * System.UnauthorizedAccessException * System.UriFormatException * System.Xml.XmlException * System.Xml.XPath.XPathException */ } } 

您可以使用XmlReader读入一个类,该类通过XmlWriter将数据泵出,并在读/写之间扫描元素,根据需要更改值。

老实说,我有点惊讶你的XML文件是如此巨大,你担心内存消耗……不是说它永远不是问题。 没有更多的信息,我不能说你假设的XML文件不是50GB,但在许多情况下,加载文件似乎很大的内存足够长的时间来操作并不像你想象的那么大。

您是否考虑过将Linq用于XML? (如果您使用的是.Net 3.0+)

 public static XElement ChangeValue(string xmlSnippet, string nodeName, string newValue) { XElement snippet = XElement.Parse(xmlSnippet); if (snippet != null) { snippet.Element(nodeName).Value = newValue; } return snippet; } 

我猜XElement的性能优于XmlDocument(虽然不确定),XElement的基础对象是XObject,是的,它必须加载整个文档。

使用仅向前阅读器肯定会是最有效的方法,在这种情况下,XmlReader派生似乎是合适的,但是它确实比使用一次加载整个文件的DOM方法更有效。

据推测,XmlReader是对源自Java世界的SAX XML解析器API的改进,但它已经成为业界(微软之外)的事实标准。

如果您只是想快速完成工作,那么XmlTextReader就是为此目的而存在的(在.NET中)。

如果你想学习一个稳定的事实标准(并且也可以在许多编程语言中使用),这将迫使你非常有效和优雅地编码,但也非常灵活,那么请研究SAX。 但是,除非您要创建高度深奥的XML解析器,否则不要为SAX本身而烦恼。 有很多解析器在底层使用SAX。

请查看我对SAX的回复,以获取SAX资源列表以及使用XmlTextReader作为其基础的真正有创意的.NET XML解析器理念 : SAX vs XmlTextReader – C#中的SAX

这使用旧文件并创建具有更新值的新文件。 如果找不到元素,它将抛出exception

 { XDocument newSettingFile = new XDocument(settingFile); //Root element var newSetting = newSettingFile.Element("MyXmlType"); //Update childelement with new value newSetting.Element("MyXmlElement").Value = "NewValue"; return newSettingFile; } 

我对一个10.6 K的文档运行了一些测试。解析XmlDocument总是比Linq查询快得多,大约50%。

  var stopwatch2 = Stopwatch.StartNew(); XmlDocument xd = new XmlDocument(); xd.LoadXml(instanceXML); XmlNode node = xd.SelectSingleNode("//figures/figure[@id='" + stepId + "']/properties/property[@name='" + fieldData + "']"); node.InnerXml = ""; stopwatch2.Stop(); var xmlDocTicks = stopwatch2.ElapsedTicks; Stopwatch stopwatch1 = Stopwatch.StartNew(); XDocument doc = XDocument.Parse(instanceXML); XElement prop = (from el in doc.Descendants("figure") where (string)el.Attribute("id") == stepId select el).FirstOrDefault(); prop.Value = valData; stopwatch1.Stop(); var linqTicks = stopwatch1.ElapsedTicks; 

结果如下(xmlDocTicks,linqTicks):

  • RUN1:(1258,1581)
  • RUN2:(2667,3463)
  • RUN3:(1416,2626)
  • run4:(1231,2383)
  • 平均:(1643,2513)
 using System; using System.Xml; using System.Linq; using System.Xml.Linq; namespace ReandAndWriteXML { class MainClass { public static void Main (string[] args) { XDocument xdoc = XDocument.Load(@"file.xml"); var element = xdoc.Root.Elements("MyXmlElement").Single(); element.Value = "This wasn't nearly as hard as the internet tried to make it!"; xdoc.Save(@"file.xml"); } } } 

这很像Ben Robin的例子,除了它有效(虽然他也是这样,现在它已被编辑)。 我甚至给了你使用指令!

加载并保存

 public XDocument XDocument { get; set; } private async Task OpenResWFileAsync() { List dataElements; var reswFile = await StorageHelper.PickSingleFileAsync(".resw"); if (reswFile == null) return; using (Stream fileStream = await reswFile.OpenStreamForReadAsync()) { this.XDocument = XDocument.Load(fileStream); dataElements = this.XDocument.Root.Elements("data").ToList(); this.DataElements = dataElements; } } #region private List GetValues() { if (this.XDocument == null) return new List(); return this.XDocument.Root.Elements("data").Select(e => e.Attribute("name").Value).ToList(); } public void ChangeValue(string resourceKey, string newValue) { if (this.DataElements == null) return; var element = this.DataElements.Where(e => e.Name == resourceKey).Single(); element.Value = newValue; } #endregion