Работу с XML в C# условно можно разделить на четыре части, в зависимости от решаемых задач.
- Стандартный разбор (парсинг) и формирование XML при помощи DOM, Xpath и т. п.;
- Сериализация и десериализация объектов, имеющих для этого штатные средства (например, DataTable);
- Сериализация и десериализация произвольных объектов, не относящихся к предыдущей части;
- Валидация структуры XML документов.
В этой статье речь пойдет именно о третьей части.
Создадим простой класс, который будет содержать единственное свойство в виде строки. Так как этот класс мы впоследствии будем сериализовать в XML, то сразу же отметим его атрибутом Serializable и сделаем его открытым (public).
1 2 3 4 5 |
[Serializable] public class ProgData { public string DataString { get; set; } } |
Здесь невольно напрашивается сравнение с подготовкой класса к сериализации (десериализации) в JSON.
Если там требовалось помечать классы и поля соответствующими атрибутами, продумывать структуру будущего JSON объекта, здесь достаточно пометить класс единственным атрибутом и средства XML сериализации .NET Framework самостоятельно определят правильную структуру XML.
Для сериализации на необходимо создать объект XmlSerializer (пространство имён System.Xml.Serialization), передав в его конструктор тип сериализуемого объекта (в нашем случае ProgData).
1 |
XmlSerializer serializer = new XmlSerializer(typeof(ProgData)); |
После этого остаётся только создать поток данных, в который будут помещены выходные и передать его вместе с сериализуемым объектом в метод Serialize объекта XmlSerializer.
Ниже показан пример сериализации экземпляра описанного ранее класса ProgData в XML файл через соответствующий поток.
1 2 3 4 5 6 |
ProgData progData = new ProgData { DataString = "Test1" }; XmlSerializer serializer = new XmlSerializer(typeof(ProgData)); using (FileStream fs = new FileStream("data.xml", FileMode.OpenOrCreate)) { serializer.Serialize(fs, progData); } |
Содержимое созданного XML файла:
1 2 3 4 |
<?xml version="1.0"?> <ProgData xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="https://www.w3.org/2001/XMLSchema"> <DataString>Test1</DataString> </ProgData> |
Как мы видим, оно полностью соответствует структуре исходного объекта.
Теперь мы попытаемся этот объект восстановить.
Для этого, прочитав данные из XML файла в поток, передадим его в метод Deserialize объекта XmlSerialize, как это показано ниже.
1 2 3 4 5 |
XmlSerializer serializer = new XmlSerializer(typeof(ProgData)); using (FileStream fs = new FileStream("data.xml", FileMode.OpenOrCreate)) { ProgData progData = (ProgData)serializer.Deserialize(fs); } |
Единственна неприятная особенность — метод Deserialize возвращает тип object. Поэтому приведение типов обязательно.
С простыми объектами всё достаточно очевидно, но как поступить в более сложных случаях?
1 2 3 4 5 6 7 |
[Serializable] public class AnimalGroup { public int Id { get; set; } public string Title { get; set; } public Animal[] Animals { get; set; } } |
Например, этот класс, помимо всего прочего, содержит целый массив объектов также произвольного класса Animal:
1 2 3 4 5 6 |
[Serializable] public class Animal { public int Id { get; set; } public string Title { get; set; } } |
На самом деле никаких отличий для сложных объектов нет. Они сериализуются в XML и десериализуются из него аналогичным образом.
Единственная оговорка — классы, объекты которых входят в состав сериализуемого класса также должны быть открытыми и помеченными атрибутом Serializable.
Добавить комментарий