Давайте рассмотрим на практике использование популярного формата структурирования информации XML в языке программирования C#. Мы реализуем как чтение уже имеющихся данных, так и сохранение их в XML C#.
Что такое XML?
XML (eXtensible Markup Language) — это универсальный расширяемый язык для разметки информации. Он позволяет структурировать, хранить и передавать информацию в определенном формате. Особенность данного языка заключается в том, что самоопределяемым, что позволяет самостоятельно расширять набор условных меток — тегов. Используя их, можно формировать данные в виде древовидной структуры, когда одни элементы содержат в себе другие.
Подпишись на группу Вконтакте и Телеграм-канал. Там еще больше полезного контента для программистов.
А на YouTube-канале ты найдешь обучающие видео по программированию. Подписывайся!
Пример XML разметки
В качестве примера можно рассмотреть телефонную книгу, в которой хранятся такие данные как имя человека, номер телефона и заметка.
<?xml version="1.0" encoding="UTF-8"?> <!--XML заголовок--> <catalog> <!--Корневой элемент--> <phone> <!--Элемент данных--> <name>Саша</name> <!--Первое значение данных--> <number>890953317</number> <!--Второе значение--> <remark>Не бери трубку!</remark> <!--Третье значение--> </phone> <!--Закрытие элемента данных--> <phone> <name>Дима</name> <number>890512309</number> <remark>Босс</remark> </phone> <phone group="important"> <!--Используем атрибут для дополнительного свойства--> <name>Рита</name> <number>890198735</number> <remark>Невероятная девчонка</remark> </phone> </catalog> <!--Завершение всех данных-->
Первым строкой в файле должен идти заголовок, который указывает какую версию использовать, а также кодировку текста. Затем должен обязательно идти единственных корневой элемент, в который включены все остальные данные. В дальнейшем все данные разбиваются на объекты, включающие другие объекты и так далее, в зависимости от структуры данных. Также у объекта могут быть указаны дополнительные свойства, они называются атрибуты.
Работа с XML на языке C#
Для взаимодействия с файлом в языке программирования C# имеется несколько отличных библиотек, но для начала мы рассмотрим одну из самых простых реализаций, расположенную в пространстве имен System.XML. Данная библиотека позволяет как читать, так и сохранять данные в файлы.
Реализуем две основные операции, это чтение данных из файла, и сохранение данных в файл. Рассмотрим основной метод приложения.
Program.cs
static void Main(string[] args) { // Устанавливаем кодировку консоли. // Нужно только если при использовании англоязычной Windows // на консоль вместо кириллицы выводятся знаки вопроса (??? ????? ??????) Console.OutputEncoding = Encoding.Unicode; // Читаем Xml файл. ReadXmlFile("example.xml"); // Ждем ввода пользователя. Console.ReadLine(); // Создаем структуру данных. var catalog = new Catalog() // Корневой элемент { Phones = new List<Phone>() // Коллекция номеров телефонов. { new Phone() {Name = "Саша", Number = 890953317, Remark = "Не бери трубку!", Important = false}, // Запись номера телефона. new Phone() {Name = "Дима", Number = 890512309, Remark = "Босс", Important = false}, new Phone() {Name = "Рита", Number = 890198735, Remark = "Невероятная девчонка", Important = true} } }; // Пишем в файл. WriteXmlFile("result.xml", catalog); // Сообщаем пользователю о завершении. Console.WriteLine("ОК"); Console.ReadLine(); }
Чтение XML файла на языке C#
Возьмем в качестве исходного файла пример указанный выше, для простоты удалив комментарии.
Program.cs
/// <summary> /// Прочитать Xml файл. /// </summary> /// <param name="filename"> Путь к Xml файлу. </param> private static void ReadXmlFile(string filename) { // Создаем экземпляр Xml документа. var doc = new XmlDocument(); // Загружаем данные из файла. doc.Load(filename); // Получаем корневой элемент документа. var root = doc.DocumentElement; // Используем метод для рекурсивного обхода документа. PrintItem(root); } /// <summary> /// Метод для отображения содержимого xml элемента. /// </summary> /// <remarks> /// Получает элемент xml, отображает его имя, затем все атрибуты /// после этого переходит к зависимым элементам. /// Отображает зависимые элементы со смещением вправо от начала строки. /// </remarks> /// <param name="item"> Элемент Xml. </param> /// <param name="indent"> Количество отступов от начала строки. </param> private static void PrintItem(XmlElement item, int indent = 0) { // Выводим имя самого элемента. // new string('\t', indent) - создает строку состоящую из indent табов. // Это нужно для смещения вправо. // Пробел справа нужен чтобы атрибуты не прилипали к имени. Console.Write($"{new string('\t', indent)}{item.LocalName} "); // Если у элемента есть атрибуты, // то выводим их поочередно, каждый в квадратных скобках. foreach(XmlAttribute attr in item.Attributes) { Console.Write($"[{attr.InnerText}]"); } // Если у элемента есть зависимые элементы, то выводим. foreach(var child in item.ChildNodes) { if (child is XmlElement node) { // Если зависимый элемент тоже элемент, // то переходим на новую строку // и рекурсивно вызываем метод. // Следующий элемент будет смещен на один отступ вправо. Console.WriteLine(); PrintItem(node, indent + 1); } if(child is XmlText text) { // Если зависимый элемент текст, // то выводим его через тире. Console.Write($"- {text.InnerText}"); } } }
В результате получим следующий вывод на консоль

Создание XML файла на языке C#
Для начала нам нужно определить классы модели данных, то есть указать свойства, которые хотим хранить в файле.
Phone.cs
namespace XML { /// <summary> /// Телефонный контакт. /// </summary> public class Phone { /// <summary> /// Имя. /// </summary> public string Name { get; set; } /// <summary> /// Телефонный номер. /// </summary> public int Number { get; set; } /// <summary> /// Заметка. /// </summary> public string Remark { get; set; } /// <summary> /// Важный контакт. /// </summary> public bool Important { get; set; } /// <summary> /// Приведение объекта к строке. /// </summary> /// <returns> Имя. </returns> public override string ToString() { return Name; } } }
Catalog.cs
using System.Collections.Generic; namespace XML { /// <summary> /// Каталог телефонных номеров. /// </summary> public class Catalog { /// <summary> /// Список телефонных номеров. /// </summary> public List<Phone> Phones { get; set; } = new List<Phone>(); } }
Теперь реализуем метод формирования файла на основе имеющихся данных.
Program.cs
/// <summary> /// Сохранить данные в Xml файл. /// </summary> /// <param name="filename"> Путь к сохраняемому файлу. </param> /// <param name="catalog"> Сохраняемые данные. </param> private static void WriteXmlFile(string filename, Catalog catalog) { // Создаем новый Xml документ. var doc = new XmlDocument(); // Создаем Xml заголовок. var xmlDeclaration = doc.CreateXmlDeclaration("1.0", "UTF-8", null); // Добавляем заголовок перед корневым элементом. doc.AppendChild(xmlDeclaration); // Создаем Корневой элемент var root = doc.CreateElement("catalog"); // Получаем все записи телефонной книги. foreach(var phone in catalog.Phones) { // Создаем элемент записи телефонной книги. var phoneNode = doc.CreateElement("phone"); if (phone.Important) { // Если установлен атрибут Важный в true, // то создаем и добавляем атрибут к элементу записи телефонной книги. // Создаем атрибут и нужным именем. var attribute = doc.CreateAttribute("group"); // Устанавливаем содержимое атрибута. attribute.InnerText = "important"; // Добавляем атрибут к элементу. phoneNode.Attributes.Append(attribute); } // Создаем зависимые элементы. AddChildNode("name", phone.Name, phoneNode, doc); AddChildNode("number", phone.Number.ToString(), phoneNode, doc); AddChildNode("remark", phone.Remark, phoneNode, doc); // Добавляем запись телефонной книги в каталог. root.AppendChild(phoneNode); } // Добавляем новый корневой элемент в документ. doc.AppendChild(root); // Сохраняем документ. doc.Save(filename); } /// <summary> /// Добавить зависимый элемент с текстом. /// </summary> /// <param name="childName"> Имя дочернего элемента. </param> /// <param name="childText"> Текст, который будет внутри дочернего элемента. </param> /// <param name="parentNode"> Родительский элемент. </param> /// <param name="doc"> Xml документ. </param> private static void AddChildNode(string childName, string childText, XmlElement parentNode, XmlDocument doc) { var child = doc.CreateElement(childName); child.InnerText = childText; parentNode.AppendChild(child); }
В результате, после выполнения программы, мы получим файл с идентичной структурой и данными.
Заключение
Здесь рассмотрено элементарное взаимодействие с файлами. В дальнейшем мы обязательно вернемся к данной теме. Исходный код доступен в репозитории https://github.com/shwanoff/XML.
Также советую изучить статью Новинки C# 7.2. Span<T> и Memory<T>. А еще подписывайтесь на группу ВКонтакте, Telegram и YouTube-канал. Там еще больше полезного и интересного для программистов.