Подтвердить что ты не робот

Лучший способ изменить значение элемента в С#

Я пытаюсь найти лучший способ изменить значение элемента в XML.

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

Что является самым простым и/или лучшим способом изменить "Значение" на С#?

Я просмотрел XMLDocument, и это вызовет загрузку всего XML-документа в память. Не могли бы вы сделать это с помощью XMLReader. Проблема заключается в изменении значения, и его испускание кажется интересной загадкой.

Приветствия: D

4b9b3361

Ответ 1

Вы можете использовать пространство имен System.Xml.Linq для простейшего для чтения кода. Это загрузит полный файл в память.

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

Ответ 2

EDIT: не видел вашего предложения о 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
        */
    }
}

Ответ 3

Вы можете использовать XmlReader для чтения в класс, который выводит данные обратно через XmlWriter и просматривает элемент между чтением/записью, изменяя при необходимости значение.

Честно говоря, я немного удивлен, что ваш XML файл настолько огромен, что вы беспокоитесь о потреблении памяти... не говоря, что это никогда не проблема. Без дополнительной информации я не могу сказать, что ваш гипотетический XML файл не 50gb, но во многих случаях загрузка файлов, которые кажутся большими в памяти достаточно долго, чтобы манипулировать, не такая уж большая сделка, как вы думаете.

Ответ 4

Вы думали об использовании 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, и да, ему придется загрузить весь документ.

Ответ 5

Использование читателя с прямым доступом, безусловно, будет самым эффективным подходом, и в этом случае вывод XmlReader кажется уместным, хотя он все же более эффективен, чем при использовании подхода DOM, который загружает весь файл одновременно.

XmlReader предположительно является улучшением по сравнению с API анализатора SAX XML, который возник в мире Java, но который стал стандартом де-факто в отрасли (за пределами Microsoft).

Если вы просто хотите быстро выполнить задание, для этой цели существует XmlTextReader (в .NET).

Если вы хотите изучить стандарт де-факто, который является стабильным (а также доступен на многих языках программирования), и который заставит вас кодировать очень эффективно и элегантно, но который также является чрезвычайно гибким, а затем загляните в SAX. Однако не беспокойтесь о SAX, если вы не собираетесь создавать высокоэзотерические синтаксические анализаторы XML. Есть много парсеров, которые используют SAX под обложками.

Обратите внимание на мой отзыв о SAX здесь для списка ресурсов SAX и действительно творческой идеи синтаксического анализа .NET XML, которая использует XmlTextReader в качестве основы: SAX vs XmlTextReader - SAX на С#

Ответ 6

Это использует старый файл и создает новый с обновленным значением. Он выдает исключение, если он не может найти элемент

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

Ответ 7

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");
        }
    }
}

Это очень похоже на пример Бена Робин, за исключением того, что он работает (хотя его тоже делает, теперь, когда он был отредактирован). И я даже дал вам используемые директивы!

Ответ 8

Я провел несколько тестов в документе, который составлял 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)