Чтение и запись XML в файл

Материал сайта coderlife.ru

Сейчас наиболее популярным форматом передачи данных является XML, по этому, я думаю, не стоит говорить об актуальности рассматриваемой проблемы. Рано или поздно вам придется столкнуться с этим форматом.

Сегодня мы поговорим о том как читать/писать из/в XML фаил посредством классов входящих в .Net Framework. Скажу сразу, классов для работы с XML несколько, поэтому выбирать между ними все-таки придется .

Почему существует несколько классов для работы с одним и тем же? На этот вопрос, на мой взгляд, есть два ответа: «на вкус и цвет все фломастеры разные» и «в зависимости от предоставляемой функциональности один класс может оказаться удобнее в той или иной ситуации». Немного покопавшись в интернете и MSDN я нашел золотую парочку (для чтения и записи), о которой я вам сегодня и поведаю.

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

    1. Практически нулевой риск создать неправильный XML документ;

    2. Можно задать форматирование (отступы и д.р.) XML документа (очень сильно улучшает читаемость).

Итак, для начала надо решить, что вам надо сделать:

    1. Сформировать XML-документ одним проходом и не возвращаться к нему больше

    2. Прочитать/изменить уже существующий XML-документ

Зачем определяться? Скажем так, впоследствии это сэкономит ваше время при написании кода.

Наиболее подходящим для первого случая является класс XmlWriter. Плюсы данного класса:

    1. Форматирование результирующего XML документа;

    2. Создание открывающего и закрывающего тега в одну команду,причем для создания закрывающего тега не требуется знать имя открывающего (сомнительный плюс, но все же).

Для форматирования выводимого XML документа в XmlWriter используется класс XmlWriterSettings.

using System.Xml; ... XmlWriterSettings settings = new XmlWriterSettings(); // включаем отступ для элементов XML документа// (позволяет наглядно изобразить иерархию XML документа) settings.Indent = true; settings.IndentChars = " "; // задаем отступ, здесь у меня 4 пробела // задаем переход на новую строку settings.NewLineChars = "\n"; // Нужно ли опустить строку декларации формата XML документа// речь идет о строке вида "<?xml version="1.0" encoding="utf-8"?>" settings.OmitXmlDeclaration = true;

Это не все параметры, остальные свойства класса XmlWiterSettings вы сможете найти в MSDN.

Так выглядит простейшее использование класса XmlWriter.

// FileName - имя файла, куда будет сохранен XML-документ// settings - настройки форматирования (и не только) вывода// (рассмотрен выше)using (XmlWriter output = XmlWriter.Create(FileName, settings)){ ... // Создали открывающийся тег output.WriteStartElement("filialBD"); // Добавляем атрибут для filialBD output.WriteAttributeString("deliver_id","10"); // Создаем элемент <dname>sanchos</dname> output.WriteElementString("dname", "sanchos"); ... // Закрываем filialBD output.WriteEndElement(); ... // Сбрасываем буфферизированные данные output.Flush(); // Закрываем фаил, с которым связан output output.Close();}

Вот что получится, если выполнить пример выше:

<?xml version="1.0" encoding="utf-8" ?><filialBD deliver_id="10"> <dname>sanchos</dname></filialBD>

UPD. Используя функцию WriteElementString, вы не только открываете тег, записываете данные, но и ЗАКРЫВАЕТЕ его, поэтому добавить атрибут к такому элементу НЕЛЬЗЯ! Для решения данной проблемы используйте WriteStartElement, WriteAttributeString, WriteEndElement.

Перейдем ко второму варианту развития событий – отредактировать/прочитать уже существующий XML-документ.

Для чтения XML-документа предусмотрен класс XMLReader, но он крайне не удобен, т.к осуществляет последовательное считывание и не позволяет «прыгать через»/обращаться сразу к нужному элементу.

Чтение и редактирование удобно производить через класс XmlDocument.

Давайте, для начала вспомним из чего состоит XML-документ:

    1. Строка вида <?xml … ?>

    2. Родительский элемент (он единственный и не повторимый )

Дальше, внутри родительского элемента располагаются элементы-потомки (child’ы) и т.д. по иерархии.

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

// Создаем экземпляр класса XmlDocument xmlDoc = new XmlDocument(); // Загружаем XML-документ из файла xmlDoc.Load(FileName); // Загружаем XML-документ из строки// xmlDoc.LoadXML(s1); // Получаем всех детей корневого элемента// xmlDoc.DocumentElement - корневой элементforeach (XmlNode table in xmlDoc.DocumentElement.ChildNodes){ // перебираем все атрибуты элемента foreach (XmlAttribute attr in table.Attributes) { // attr.Name - имя текущего атрибута // attr.Value - значение текущего атрибута string s = attr.Name + ":" + attr.Value; } // перебираем всех детей текущего узла foreach (XmlNode ch in table.ChildNodes) { ... } // Получаем текст хранящийся в текущем узле MessageBox.Show(table.InnerText);}

Теперь давайте рассмотрим как изменять уже имеющийся XML-документ.

Для вставки элемента в иерархию XML-документа необходимо создать элемент типаXmlNode и задать его родителя, делается это следующим образом:

// Создаем node// book - имя узла XmlNode node = xmlDoc.CreateElement("book"); // Добавляем его в качестве ребенка parentNode.AppendChild(node);

Удаление узла производится следующим образом:

// Удаление узла parentNode.RemoveChild(node);

Примеры операции с атрибутами рассмотрены ниже:

// Создаем новый атрибут// genre - имя атрибута XmlAttribute newAttr = doc.CreateAttribute("genre"); newAttr.Value = "novel"; // Задаем его значение// Добавляем атрибут в коллекцию атрибутов элемента node.SetNamedItem(newAttr); // Удаляем атрибут node.Attributes.RemoveNamedItem("genre"); // Изменяем значение атрибута XmlAttributeCollection Attribs = node.Attributes; XmlAttribute attr = (XmlAttribute)Attribs.GetNamedItem("genre"); attr.Value = "fiction";

На первый взгляд, мне показалось крайне не логичным то, что для того чтобы создать node необходимо обращаться к методу CreateElement класса XmlDocument. Однако, мне кажется, что это сделано намерено - в таком случае от экземпляра класса XmlDocument передаются все необходимые параметры (версия xml, кодировка и т.д.), которые необходимы при сохранении или экспорте XML-документа.

Итак, я дал вам пищу для ума и фантазии, это далеко не все, что можно сказать про XML-документ в контексте работы с ним в C#, однако это ступенька при помощи, которой вы сможете начать двигаться вперед .

Удачи!