我正在尝试查看更改XML中元素值的最佳方法。
<MyXmlType>
<MyXmlElement>Value</MyXmlElement>
</MyXmlType>
在C#中更改“值”的最简单和/或最好的方法是什么?
我查看过XMLDocument,它会导致整个XML文档加载到内存中。你能用XMLReader安全地完成吗?问题是改变价值并将其发回似乎是一个有趣的难题。
干杯:D
答案 0 :(得分:32)
您可以使用System.Xml.Linq命名空间内容来获取最简单的代码。这会将整个文件加载到内存中。
XDocument xdoc = XDocument.Load("file.xml");
var element = xdoc.Elements("MyXmlElement").Single();
element.Value = "foo";
xdoc.Save("file.xml");
答案 1 :(得分:5)
编辑:没有看到关于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
*/
}
}
答案 2 :(得分:2)
您可以使用XmlReader读取一个类,该类通过XmlWriter将数据泵出,并在读/写之间扫描元素,并根据需要更改值。
老实说,我有点惊讶你的XML文件是如此巨大,你担心内存消耗......并不是说它永远不是问题。如果没有更多的信息,我不能说你的假设XML文件不是50gb,但在很多情况下,加载文件看起来很长,足以操作的内存并不像你想象的那么大。
答案 3 :(得分:2)
您是否考虑过将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,是的,它必须加载整个文档。
答案 4 :(得分:2)
使用仅向前阅读器肯定会是最有效的方法,在这种情况下,XmlReader派生似乎是合适的,但是,它仍然比使用DOM方法更多的工作,一次加载整个文件。 / p>
XmlReader据说是对源自Java世界的SAX XML解析器API的改进,但它已经成为业界(微软之外)的事实标准。
如果您只是想快速完成工作,那么XmlTextReader就是为此目的而存在的(在.NET中)。
如果你想学习一个稳定的事实标准(并且也可以在许多编程语言中使用),这将迫使你非常有效和优雅地编码,但也非常灵活,那么请研究SAX。 但是,除非您要创建高度深奥的XML解析器,否则不要为SAX本身而烦恼。有很多解析器可以使用SAX。
请查看我对SAX的回复,以获取SAX资源列表以及使用XmlTextReader作为其基础的非常有创意的 .NET XML解析器构思: SAX vs XmlTextReader - SAX in C#
答案 5 :(得分:2)
这使用旧文件并创建一个具有更新值的新文件。如果它找不到元素
,它将抛出异常{
XDocument newSettingFile = new XDocument(settingFile);
//Root element
var newSetting = newSettingFile.Element("MyXmlType");
//Update childelement with new value
newSetting.Element("MyXmlElement").Value = "NewValue";
return newSettingFile;
}
答案 6 :(得分:1)
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");
}
}
}
这很像本·罗宾的例子,除了它有效(尽管他的确如此,现在它已被编辑)。我甚至给了你使用指令!
答案 7 :(得分:1)
我在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;
结果如下(xmlDocTicks,linqTicks):
答案 8 :(得分:0)
加载并保存
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