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

时间:2009-02-13 01:06:30

标签: c# .net xml

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

<MyXmlType>
   <MyXmlElement>Value</MyXmlElement>
</MyXmlType>

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

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

干杯:D

9 个答案:

答案 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):

  • RUN1:(1258,1581)
  • RUN2:(2667,3463)
  • RUN3:(1416,2626)
  • run4:(1231,2383)
  • avg:(1643,2513)

答案 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