Как стать автором
Обновить
1301.79
OTUS
Цифровые навыки от ведущих экспертов

Работа с XML в C#

Уровень сложностиСредний
Время на прочтение6 мин
Количество просмотров7K

Привет, Хабр!

Обработка XML-данных остаётся актуальной задачей несмотря на появление более крутых технологий для работы с данными. XML — это все еще гибкий и мощный инструмент для структурирования данных, который используется в самых разнообразных приложениях.

В статье рассмотрим как работать с XML в C#.

Работа с XML в C#

Начнем с базы.

XmlDocument — это класс, который позволяет работать с XML в доменной модели. Можно загружать, изменять и сохранять XML-документы. Читать XML можно через методыLoad и LoadXml, которые считывают данные из файлов или строк. Создание новых узлов и атрибутов происходит с помощью методов CreateElement и CreateAttribute, после чего элементы добавляются в документ с помощью AppendChild.

Cоздадим XML-документ, добавим в него элементы и атрибуты, а затем сохраним его:

using System;
using System.Xml;

class Program
{
    static void Main()
    {
        // новый XML-документ
        XmlDocument doc = new XmlDocument();

        // корневой элемент
        XmlElement root = doc.CreateElement("users");
        doc.AppendChild(root);

        // новый элемент
        XmlElement user = doc.CreateElement("user");
        root.AppendChild(user);

        // атрибут для элемента user
        XmlAttribute attr = doc.CreateAttribute("id");
        attr.Value = "1";
        user.Attributes.Append(attr);

        // вложенные элементы в элемент user
        XmlElement firstName = doc.CreateElement("firstName");
        firstName.InnerText = "John";
        user.AppendChild(firstName);

        XmlElement lastName = doc.CreateElement("lastName");
        lastName.InnerText = "Doe";
        user.AppendChild(lastName);

        // сейвим XML-документ в файл
        doc.Save("users.xml");
    }
}

Но есть способы получше.

XmlReader и XmlWriter

XmlReader и XmlWriter предоставляют более производительные альтернативы для чтения и записи XML по сравнению с DOM, т.к они работают в потоковом режиме. XmlReader читает XML поэлементно.

Пример XmlReader:

using System;
using System.Xml;

class Program
{
    static void Main()
    {
        // создаем XmlReader для чтения файла
        using (XmlReader reader = XmlReader.Create("example.xml"))
        {
            while (reader.Read()) // чтение некст элемента
            {
                if (reader.NodeType == XmlNodeType.Element && reader.Name == "name")
                {
                    Console.WriteLine(reader.ReadElementContentAsString()); // читаем содержимое элемента <name>
                }
            }
        }
    }
}

Здесь юзаем XmlReader для поэлементного чтения XML-файла. Фильтруем элементы по типу узла XmlNodeType.Element и имени name, чтобы извлечь информацию только из тех элементов, которые нас интересуют.

Пример XmlWriter:

using System;
using System.Xml;

class Program
{
    static void Main()
    {
        // создаем XmlWriter
        using (XmlWriter writer = XmlWriter.Create("output.xml"))
        {
            writer.WriteStartDocument(); // начало документа
            writer.WriteStartElement("users"); // начало корневого элемента <users>

            writer.WriteStartElement("user"); // начало элемента <user>
            writer.WriteElementString("name", "Ivan"); //добавление <name>
            writer.WriteEndElement(); // закрытие элемента <user>

            writer.WriteEndElement(); // закрытие корневого элемента <users>
            writer.WriteEndDocument(); // закрытие документа
        }
    }
}

Используем XmlWriter для создания нового XML-файла с простой структурой. Стартуем с создания корневого элемента <users>, добавляем в него дочерний элемент <user> с вложенным элементом <name>, и последовательно закрываем все открытые элементы и документ.

XDocument

Также существует XDocument и связанные с ним классы XElement, XAttribute.

XElement — это отдельный элемент в XML-документе и он позволяет управлять содержимым элемента, включая его вложенные элементы, текст и атрибуты.

XAttribute служит для работы с атрибутами XML-элементов. Атрибуты представляют собой пары имя-значение, которые прикрепляются к элементам.

Cоздадим простой XML-документ, который содержит инфу о нескольких юзерах, каждый из которых имеет уникальный идентификатор и имя:

using System;
using System.Xml.Linq;

class Program
{
    static void Main()
    {
        // новый XML-документа
        XDocument xmlDoc = new XDocument(
            new XDeclaration("1.0", "utf-8", null),
            new XElement("users", // корневой элемент
                new XElement("user", // дочерний элемент
                    new XAttribute("id", "1"), // атрибут элемента user
                    new XElement("name", "Ivan")
                ),
                new XElement("user",
                    new XAttribute("id", "2"),
                    new XElement("name", "Kolya")
                )
            )
        );

        Console.WriteLine(xmlDoc.ToString());

        // сохранение XML-документа в файл
        xmlDoc.Save("users.xml");
    }
}

XDocument создаёт новый XML-документ.

XElement используется для создания элементов users и user. Элемент users служит корневым элементом, а user — дочерним элементом, представляющим пользователя.

XAttribute применяется для добавления атрибутов к элементу user, в данном случае это идентификатор пользователя.

LINQ

Можно интегрировать LINQ с XML и сделать код более читабельным.

Например, так можно сделать чтение и запрос данных:

using System;
using System.Linq;
using System.Xml.Linq;

class Program
{
    static void Main()
    {
        XDocument doc = XDocument.Load("books.xml");

        var books = from book in doc.Descendants("book")
                    where (int)book.Attribute("id") == 1
                    select new
                    {
                        Title = book.Element("title").Value,
                        Author = book.Element("author").Value
                    };

        foreach (var book in books)
        {
            Console.WriteLine($"Title: {book.Title}, Author: {book.Author}");
        }
    }
}

А так сделать агрегацию данных из XML:

using System;
using System.Xml.Linq;
using System.Linq;

class Program
{
    static void Main()
    {
        XDocument doc = XDocument.Load("books.xml");

        var bookCount = doc.Descendants("book").Count(); // cчитаем количество книг
        var maxId = doc.Descendants("book").Max(book => (int)book.Attribute("id")); // Находим максимальный id

        Console.WriteLine($"Total books: {bookCount}, Max ID: {maxId}");
    }
}

Десериализация XML и обработка исключений

Для начала десериализации нужно создать класс, структура которого соответствует структуре XML документа. Этот класс должен содержать поля или свойства, соответствующие элементам XML.

Создаем экземпляр XmlSerializer, указав тип объекта, который нужно десериализовать:

XmlSerializer serializer = new XmlSerializer(typeof(MyClass));

Также используемXmlSerializer для чтения XML из файла или потока и его преобразования в объект. Чаще всего используется StreamReader или StringReader:

using (StreamReader reader = new StreamReader("path_to_file.xml"))
{
    MyClass myObject = (MyClass)serializer.Deserialize(reader);
}

При десериализации могут возникать различные исключения, например, InvalidOperationException при несоответствии XML схемы ожидаемому классу или XmlException при синтаксических ошибках в XML. Обрабатывать эти исключения можно с помощью блоков try-catch:

try
{
    using (StreamReader reader = new StreamReader("path_to_file.xml"))
    {
        MyClass myObject = (MyClass)serializer.Deserialize(reader);
    }
}
catch (InvalidOperationException ex)
{
    Console.WriteLine($"Invalid XML format: {ex.Message}");
}
catch (XmlException ex)
{
    Console.WriteLine($"XML Parsing Error at line {ex.LineNumber}: {ex.Message}");
}
catch (Exception ex)
{
    Console.WriteLine($"General error: {ex.Message}");
}

Рассмотрим класс Person и XML файл, который содержит данные о человеке:

<Person>
    <Name>Ivan</Name>
    <Age>30</Age>
</Person>

Соответствующий класс Person в C# будет выглядеть так:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

Десериализация этого XML в объект Person с XmlSerializer выглядит так:

string xmlData = @"<Person><Name>John Doe</Name><Age>30</Age></Person>";
using (StringReader stringReader = new StringReader(xmlData))
{
    XmlSerializer serializer = new XmlSerializer(typeof(Person));
    Person person = (Person)serializer.Deserialize(stringReader);
    Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");
}

XML схемы и валидация в C#

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

XML схема обычно определяет элементы и атрибуты, которые могут появляться в документе, их типы данных, и другие ограничения. Например, схема для описания книг в библиотеке может выглядеть так:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="library">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="book" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="title" type="xs:string"/>
                            <xs:element name="author" type="xs:string"/>
                            <xs:element name="isbn" type="xs:string"/>
                            <xs:element name="price" type="xs:decimal"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

Для валидации XML документа в соответствии с XSD схемой, можно использовать классы XmlReader и XmlReaderSettings из пространства имен System.Xml.Schema. Например:

using System;
using System.Xml;
using System.Xml.Schema;

class Program
{
    static void Main()
    {
        XmlReaderSettings settings = new XmlReaderSettings();
        settings.Schemas.Add(null, "library.xsd");
        settings.ValidationType = ValidationType.Schema;

        XmlReader reader = XmlReader.Create("library.xml", settings);
        XmlDocument document = new XmlDocument();
        document.Load(reader);
        ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler);
        document.Validate(eventHandler);
    }

    static void ValidationEventHandler(object sender, ValidationEventArgs e)
    {
        if (e.Severity == XmlSeverityType.Error)
        {
            Console.WriteLine("Error: {0}", e.Message);
        }
        else if (e.Severity == XmlSeverityType.Warning)
        {
            Console.WriteLine("Warning: {0}", e.Message);
        }
    }
}

Таким образом можно обеспечить, что XML документы точно соответствуют определенным структурам и правилам.


Современные приложения иногда потребляют очень много памяти. Приглашаем вас на бесплатный урок, на котором будут рассмотрены основные приемы эффективной работы и экономии памяти в современных .net приложениях, и как помогают в этом ArrayPool, Span.

Теги:
Хабы:
Всего голосов 5: ↑5 и ↓0+9
Комментарии17

Публикации

Информация

Сайт
otus.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия
Представитель
OTUS