Как анализировать и обновлять XML-файл с помощью xmltextreader или xmlreader

Привет, у меня есть следующий код для чтения файла xml и изменения значения определенного узла, но я хочу сделать то же самое, используя xmltextreader или xmlreader, я пытаюсь избежать оператора doc.Save(System.Web.HttpContext.Current.Server.MapPath("Data/Example.xml"));, который имеет прямую ссылку на мой физический файл.

XmlDocument doc = new XmlDocument();
                   string xmlFile = System.Web.HttpContext.Current.Server.MapPath("Data/Example.xml");
                   doc.Load(xmlFile);
                   XmlNodeList xmlnode = doc.GetElementsByTagName("value");
                   xmlnode[0].ChildNodes[0].Value = 23;
 doc.Save(System.Web.HttpContext.Current.Server.MapPath("Data/Example.xml"));

person mahesh    schedule 15.09.2011    source источник
comment
+1 но вопрос все равно выглядит непродуманным, невозможно сохранить что-либо с помощью reader, это напоминает мне о моем плохом знании английского языка.   -  person Artur Mustafin    schedule 15.09.2011


Ответы (2)


Что ж, что-то должно иметь ссылку на файл. Однако вы можете легко изменить свой код, чтобы просто принять Stream (который должен быть доступен для чтения, записи и поиска):

private static void ChangeDocument(Stream stream)
{
    XmlDocument doc = new XmlDocument();
    doc.Load(stream);
    XmlNodeList xmlnode = doc.GetElementsByTagName("value");
    xmlnode[0].ChildNodes[0].Value = 23;
    stream.Position = 0;
    doc.Save(stream);
    stream.SetLength(stream.Position); // Truncate the file if it was longer
}

Как-то некрасиво, согласитесь...

Конечно, вы всегда можете передать само имя файла - ваш вызов MapPath все равно будет в методе более высокого уровня, и это может быть все, чего вы пытаетесь достичь:

private static void ChangeDocument(string filename)
{
    XmlDocument doc = new XmlDocument();
    doc.Load(filename);
    XmlNodeList xmlnode = doc.GetElementsByTagName("value");
    xmlnode[0].ChildNodes[0].Value = 23;
    doc.Save(filename);
}

Последнее замечание: если вы используете .NET 3.5 или более позднюю версию, я настоятельно рекомендую использовать LINQ to XML как более удобный XML API.

person Jon Skeet    schedule 15.09.2011
comment
Хитрый способ скрыть doc.Save(...)? - person Artur Mustafin; 15.09.2011
comment
Тогда полный путь к файлу будет в другом коде, где вы объявляете объект Stream, в любом случае, это просто неизбежно при использовании файлового подхода. - person Artur Mustafin; 15.09.2011
comment
@Artur: Да, если вы хотите получить доступ к файлу, вам нужно, чтобы имя было известно где-то. Я предположил, что OP не хочет, чтобы он вычислялся здесь, что вполне может быть разумным. (Например, этот код можно поместить в библиотеки классов, используемые в нескольких приложениях, где Server.MapPath вполне может быть неуместным.) - person Jon Skeet; 15.09.2011
comment
Действительно ли необходимо иметь doc.Save, могу ли я обновить свой xml-файл любым другим хорошим подходом? - person mahesh; 15.09.2011
comment
@mahesh: Ну, что-то должно знать, как писать обратно в файл. Вы можете передать Func<XmlWriter> или, если вам удобно писать в другой файл, вы можете передать XmlWriter для начала. Было бы полезно, если бы вы сказали точно чего вы пытаетесь избежать. Почему вам не нравится doc.Save? - person Jon Skeet; 15.09.2011
comment
Нет, я просто хотел изменить свой код, чтобы реализовать следующий подход: byte[] bytes = Encoding.ASCII.GetBytes(dataXml); dataStream = новый MemoryStream (байты); //Создаем Xmlreader из потока памяти XmlReader reader = XmlReader.Create(dataStream); Данные XElement = XElement.Load(читатель); - person mahesh; 15.09.2011
comment
@mahesh: Но почему ты хотел это сделать? Использование XmlReader намного сложнее, и вам потребуется какой-то способ отражения изменений. Вы также не должны предполагать, что файл XML находится в ASCII - вы даже не должны предполагать, что он в UTF-16. По общему признанию, в этом случае вы можете это знать, но это все равно делает код более хрупким. - person Jon Skeet; 15.09.2011
comment
Спасибо за полезный ответ, я полностью с вами согласен, в указанном вами примере кода, не могли бы вы показать, как создать поток и передать его в функцию ChangeDocument (поток потока) - person mahesh; 15.09.2011
comment
@mahesh: Просто используйте File.Open(path, FileMode.Open). - person Jon Skeet; 15.09.2011
comment
Я планирую использовать Linq to xml - person mahesh; 15.09.2011
comment
Не могли бы вы предложить мне хорошую статью о linq to xml для функций, которые я пытаюсь реализовать? - person mahesh; 15.09.2011
comment
@mahesh: я бы просто нашел несколько руководств по LINQ to XML - их загрузки по всему Интернету. - person Jon Skeet; 15.09.2011

Вы не можете записывать или обновлять XML-данные с помощью ансекторов XmlTextReader или XmlReader, использовать предков XmlTextWriter или XmlWriter или < strong>XmlSerializer.Serialize(..) в качестве альтернативы.

Нельзя избежать утверждения и тому подобное,

doc.Save(System.Web.HttpContext.Current.Server.MapPath("Data/Example.xml"));

который имеет прямую ссылку на ваш физический файл, потому что вам нужно снова записать измененные узлы обратно в исходный файл, иначе вам придется переключить вашу систему с использования файлового подхода (веб-сайт ASP.NET, использующий файловое хранилище данных ) к подходу, управляемому базой данных (веб-сайт ASP.NET с использованием сервера базы данных).

В качестве альтернативы используйте свои собственные XML-данные на сервере SQL, а затем загружайте и обновляйте их с помощью EF или ORM.

person Artur Mustafin    schedule 15.09.2011