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

C# 更改C中元素值的最佳方法#,c#,.net,xml,C#,.net,Xml,我试图寻找在XML中更改元素值的最佳方法 <MyXmlType> <MyXmlElement>Value</MyXmlElement> </MyXmlType> 价值 更改C#中“值”的最简单和/或最佳方法是什么 我已经看过了XMLDocument,它会导致整个XML文档加载到内存中。您能安全地使用XMLReader吗。问题是更改值并将其发回似乎是一个有趣的难题 干杯:D您可以使用XmlReader读入一个类,该类通过XmlWriter

我试图寻找在XML中更改元素值的最佳方法

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

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

我已经看过了XMLDocument,它会导致整个XML文档加载到内存中。您能安全地使用XMLReader吗。问题是更改值并将其发回似乎是一个有趣的难题


干杯:D

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


老实说,我有点惊讶,您的XML文件如此之大,以至于您担心内存消耗。。。不是说这从来都不是问题。如果没有更多的信息,我不能说您假设的XML文件不是50gb,但在许多情况下,将似乎足够长的文件加载到内存中进行操作并不像您想象的那么重要。

编辑:没有看到您关于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
        */
    }
}

您可以使用System.Xml.Linq名称空间来获得最容易阅读的代码。这将把完整的文件加载到内存中

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

您考虑过使用Linq转换XML吗?(如果您使用的是.Net 3.0+)


我猜XElement的性能会比XmlDocument好(尽管不确定),XElement的基本对象是XObject,是的,它必须加载整个文档。

使用仅向前读卡器肯定是最有效的方法,在这种情况下,XmlReader派生似乎是合适的,尽管这仍然比使用DOM方法一次加载整个文件要复杂得多

XmlReader被认为是对SAXXML解析器API的改进,SAXXML解析器API起源于Java世界,但已成为业界(微软以外)事实上的标准

如果您只是想快速完成工作,XmlTextReader就是为了这个目的而存在的(在.NET中)

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

请查看我对SAX的回复,这里有一个SAX资源列表和一个非常有创意的使用XmlTextReader作为基础的.NET XML解析器想法


这与本·罗宾的例子非常相似,只是它很有效(虽然他的例子也有效,但现在已经编辑好了)。我甚至给了你使用指令

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

{
    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.6K的文档上运行了一些测试。解析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;
var stopwatch2=Stopwatch.StartNew();
XmlDocument xd=新的XmlDocument();
LoadXml(instanceXML);
XmlNode node=xd.SelectSingleNode(//figures/figures[@id=''+stepId+']]/properties/properties[@name='+fieldData+']);
node.InnerXml=“”;
秒表2.Stop();
var xmlDocTicks=stopwatch2.ElapsedTicks;
秒表秒表1=Stopwatch.StartNew();
XDocument doc=XDocument.Parse(instanceXML);
希莱蒙道具=
(来源于文件子体中的el(“图”)
其中(字符串)el.Attribute(“id”)==stepId
选择el).FirstOrDefault();
属性值=valData;
秒表1.Stop();
var linqTicks=秒表1.ElapsedTicks;
结果如下(xmlDocTicks,linqTicks):

  • run1:(12581581)
  • run2:(26673463)
  • run3:(14162626)
  • run4:(12383)
  • 平均值:(16432513)
加载并保存

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
public XDocument XDocument{get;set;}
专用异步任务OpenResWFileAsync()
{
列出数据元素;
var reswFile=await-StorageHelper.PickSingleFileAsync(“.resw”);
if(reswFile==null)返回;
使用(Stream fileStream=wait reswFile.OpenStreamForReadAsync())
{
this.XDocument=XDocument.Load(fileStream);
dataElements=this.XDocument.Root.Elements(“数据”).ToList();
this.DataElements=数据元素;
}
}
#区域
私有列表GetValues()
{
如果(this.XDocument==null)返回新列表();
返回此.XDocument.Root.Elements(“数据”).Select(e=>e.Attribute(“name”).Value).ToList();
}
public void ChangeValue(字符串resourceKey、字符串newValue)
{
if(this.DataElements==null)返回;
var element=this.DataElements.Where(e=>e.Name==resourceKey).Single();
element.Value=newValue;
}
#端区

他特别询问了如何在不使用XMLDocument的情况下完成这项工作。这与问题的标题相符,并帮助我解决了问题+1XML名称空间给了我悲伤,但它让我到达了我需要的地方。谢谢,加上linqy的东西很好:)。基于我提供的xml,您的示例已经运行了。如果xml文件不是太大,这很好。问题是xml文件超过100MB,我必须经常这样做。因此,如果我可以避免使用XDocument类,那么在我更改文档时,文档可以流式输入和输出,而不需要完全加载到内存中。。。我只是自己在学这些东西。当我最初从谷歌来到这里时,我只是被一个不起作用的例子所困扰,所以我觉得有必要在这里发表一篇文章,这是一个有效的版本。你找到有效的解决方案了吗
       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;
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