Лучший способ изменить значение элемента в С#
Я пытаюсь найти лучший способ изменить значение элемента в XML.
<MyXmlType>
<MyXmlElement>Value</MyXmlElement>
</MyXmlType>
Что является самым простым и/или лучшим способом изменить "Значение" на С#?
Я просмотрел XMLDocument, и это вызовет загрузку всего XML-документа в память. Не могли бы вы сделать это с помощью XMLReader. Проблема заключается в изменении значения, и его испускание кажется интересной загадкой.
Приветствия: D
Ответы
Ответ 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)