在 C# 中更改元素值的最佳方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/544310/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best way to change the value of an element in C#
提问by Spence
I'm trying to look at the best way of changing the value of an element in XML.
我正在尝试查看更改 XML 中元素值的最佳方法。
<MyXmlType>
<MyXmlElement>Value</MyXmlElement>
</MyXmlType>
What is the easiest and/or best way to change "Value" in C#?
在 C# 中更改“值”的最简单和/或最好的方法是什么?
I've looked at XMLDocument and it will cause a load of the whole XML document to memory. Could you do it safely with the XMLReader. The problem is changing the value and emitting it back seems like an interesting conundrum.
我查看了 XMLDocument,它会导致将整个 XML 文档加载到内存中。你能用 XMLReader 安全地做到这一点吗?问题是更改值并将其发回似乎是一个有趣的难题。
Cheers :D
干杯:D
采纳答案by Ben Robbins
You could use the System.Xml.Linq namespace stuff for the easiest to read code. This will load the full file into memory.
您可以使用 System.Xml.Linq 命名空间的东西来获得最容易阅读的代码。这会将完整文件加载到内存中。
XDocument xdoc = XDocument.Load("file.xml");
var element = xdoc.Elements("MyXmlElement").Single();
element.Value = "foo";
xdoc.Save("file.xml");
回答by Rex M
You could use an XmlReader to read into a class that pumps the data back out through an XmlWriter and scan for the element between the read/write, changing the value as necessary.
您可以使用 XmlReader 读入一个类,该类通过 XmlWriter 将数据泵回,并在读/写之间扫描元素,根据需要更改值。
Honestly, I'm a little surprised that your XML file is so huge you are worried about memory consumption... not saying it's never an issue. Without more info, I can't say your hypothetical XML file isn't 50gb, but in many cases loading files that seem large into memory long enough to manipulate isn't quite as big a deal as you might think.
老实说,我有点惊讶你的 XML 文件太大了,你担心内存消耗......并不是说这从来都不是问题。没有更多信息,我不能说您假设的 XML 文件不是 50gb,但在许多情况下,将看起来足够大的文件加载到内存中以进行操作并不像您想象的那么大。
回答by Andrew Ensley
EDIT: didn't see your clause about XmlDocument. XmlReader does just that. You can't edit xml files with this class.
编辑:没有看到您关于 XmlDocument 的条款。XmlReader 就是这样做的。您不能使用此类编辑 xml 文件。
You want XmlWriter. However, in case it's still helpful, here's the code for XmlDocument.
你想要 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
*/
}
}
回答by Vin
Have you thought about using Linq to XML? (if you are using .Net 3.0+)
你有没有想过使用 Linq to 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;
}
I am guessing XElement will perform better than XmlDocument (althought not sure), the base object for XElement is XObject, and yes, it will have to load the whole document.
我猜 XElement 的性能会比 XmlDocument 好(虽然不确定),XElement 的基础对象是 XObject,是的,它必须加载整个文档。
回答by EnocNRoll - AnandaGopal Pardue
Using a forward-only reader is definitely going to be the most efficient approach, in which case a XmlReader derivation seems appropriate, to be sure, though it's still more work than using DOM approach that loads the entire file at once.
使用只进阅读器肯定是最有效的方法,在这种情况下,XmlReader 派生似乎是合适的,当然,尽管它仍然比使用一次加载整个文件的 DOM 方法工作更多。
XmlReader is supposedly an improvement over the SAX XML parser API that originated in the Java world, but which has become a de facto standard in the industry (outside of Microsoft).
XmlReader 据说是对源自 Java 世界的 SAX XML 解析器 API 的改进,但它已成为行业(Microsoft 之外)事实上的标准。
If you just want to get the job done quickly, the XmlTextReader exists for that purpose (in .NET).
如果您只想快速完成工作,XmlTextReader 就是为此目的而存在的(在 .NET 中)。
If you want to learn a de facto standard that is stable (and also available in many programming languages) and which will force you to code very efficiently and elegantly, but which is also extremely flexible, then look into SAX. However, do not bother with SAX itself unless you're going to be creating highly esoteric XML parsers. There are plenty of parsers out there that use SAX under the covers.
如果您想学习一个事实上的标准,它稳定(并且在许多编程语言中都可用)并且会迫使您非常高效和优雅地编码,但它也非常灵活,那么请研究 SAX。 但是,除非您要创建非常深奥的 XML 解析器,否则不要理会 SAX 本身。有很多解析器在幕后使用 SAX。
Please check outmy response about SAX here for a list of SAX resources and a really creative .NET XML parser ideathat uses XmlTextReader as its foundation: SAX vs XmlTextReader - SAX in C#
请在此处查看我对 SAX 的回复,以获取 SAX 资源列表和使用 XmlTextReader 作为其基础的非常有创意的.NET XML 解析器想法: SAX 与 XmlTextReader - C# 中的 SAX
回答by Dekker
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");
}
}
}
This is much like Ben Robin's example, except it works (although his does too, now that it has been edited). And I even gave you the using directives!
这很像 Ben Robin 的例子,除了它可以工作(尽管他的也是如此,现在它已经被编辑了)。我什至给了你 using 指令!
回答by Haze
This uses an old file and creates a new one with updated value. It will throw an exception if it can't find the element
这将使用旧文件并创建一个具有更新值的新文件。如果找不到元素会抛出异常
{
XDocument newSettingFile = new XDocument(settingFile);
//Root element
var newSetting = newSettingFile.Element("MyXmlType");
//Update childelement with new value
newSetting.Element("MyXmlElement").Value = "NewValue";
return newSettingFile;
}
回答by ItsAllABadJoke
I ran some tests on a document that was 10.6 K. The parsing the XmlDocument always comes out faster than the Linq query, by about 50%.
我对一个 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 = "<![CDATA[ " + valData + " ]]>";
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;
The results are as follows (xmlDocTicks,linqTicks):
结果如下(xmlDocTicks,linqTicks):
- run1:(1258,1581)
- run2:(2667,3463)
- run3:(1416,2626)
- run4:(1231,2383)
- avg: (1643,2513)
- 运行 1:(1258,1581)
- 运行2:(2667,3463)
- 运行 3:(1416,2626)
- 运行4:(1231,2383)
- 平均:(1643,2513)
回答by Minute V
Load and Save
加载和保存
public XDocument XDocument { get; set; }
private async Task OpenResWFileAsync()
{
List<XElement> 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<string> GetValues()
{
if (this.XDocument == null) return new List<string>();
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