Загрузка XML из файла

47

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

Загрузка с помощью XDocument.Load()

Зная, как сохранять документы и фрагменты XML, наверняка интересно посмотреть, как их загружать обратно. Это делается с использованием любого из ряда доступных методов. Вот их список:

static XDocument XDocument.Load(string uri);
static XDocument XDocument.Load(TextReader textReader);
static XDocument XDocument.Load(XmlReader reader);
static XDocument XDocument.Load(string uri, LoadOptions options);
static XDocument XDocument.Load(TextReader textReader, LoadOptions options);
static XDocument XDocument.Load(XmlReader reader, LoadOptions options);

Легко заметить, что эти методы симметричны методам XDocument.Save, описанным в предыдущей статье. Однако есть пара отличий, на которые следует обратить внимание. Во-первых, метод Save должен вызываться на объектах типа XDocument или XElement, потому что Save — метод экземпляра. Однако метод Load — статический, поэтому он должен вызываться на самом классе XDocument. Во-вторых, методы Save принимают параметр типа string, в котором должно быть передано имя файла, в то время как методы Load могут принимать в параметре string строку URI.

Вдобавок метод Load допускает при загрузке документа XML указание параметра типа LoadOptions. Значения перечисления LoadOptions описаны ниже:

LoadOptions.None

Применяйте эту опцию, чтобы указать, что никакие опции загрузки не используются.

LoadOptions.PreserveWhitespace

Используйте эту опцию, чтобы сохранить пробелы и пустые строки в исходном XML

LoadOptions.SetLineInfo

Применяйте эту опцию, чтобы иметь возможность получать строку и позицию любого объекта, унаследованного от XObject, посредством интерфейса IXmlLineInfo

LoadOptions.SetBaseUri

Используйте эту опцию, чтобы получать базовый URI любого объекта-наследника XObject

Эти опции можно комбинировать с помощью битовой операции "ИЛИ" (|). Однако некоторые опции не работают в ряде контекстов. Например, при создании элемента или документа передачей строки никакой информации о позициях и номерах строк недоступно, как и недоступен базовый URI. Также нет базового URI при создании документа с помощью XmlReader. Ниже показан пример загрузки XML-документа, созданного в предыдущей статье (документ находится в папке проекта):

XDocument xDoc = XDocument.Load("employees.xml",
                LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);

Console.WriteLine(xDoc);

XElement firstName = xDoc.Descendants("FirstName").First();

Console.WriteLine("firstName Строка {0} - Позиция {1}",
                ((IXmlLineInfo)firstName).LineNumber,
                ((IXmlLineInfo)firstName).LinePosition);

Console.WriteLine("Базовый URI: {0}", firstName.BaseUri);

Понадобится либо добавить директиву using для System.Xml, если ее еще нет, либо указать пространство имен при ссылке на интерфейс IXmlLineInfo в коде. В противном случае компилятор не сможет обнаружить тип IXmlLineInfo.

Этот код загружает файл XML, созданный в предыдущей статье. После загрузки и отображения документа получается ссылка на элемент FirstName и отображается строка и позиция этого элемента в исходном XML-документе. Затем отображается базовый URI элемента. Вот результат:

Загрузка документа методом XDocument.Load

Этот вывод похож на ожидаемый, но с одним возможным исключением. Действительно, XML-документ выглядит хорошо. Виден номер строки и позиции элемента FirstName, но номер строки вызывает недоумение. Показано, что элемент находится в четвертой строке, но в отображенном документе на самом деле элемент FirstName расположен в третьей строке. В чем же дело? Если рассмотреть загруженный ХМL-документ можно заметить, что он начинается с объявления документа, которое в выводе опущено:

<?xml version="1.0" encoding="utf-8"?>

Именно поэтому номер строки, в которой расположен элемент FirstName, отображается как четвертый.

Загрузка с помощью XElement.Load()

Точно так же, как можно сохранять XDocument и XElement, их можно и загружать. Загрузка содержимого элемента почти идентична загрузке документа. Вот доступные для этого методы:

static XElement XElement.Load(string uri);
static XElement XElement.Load(TextReader textReader);
static XElement XElement.Load(XmlReader reader);
static XElement XElement.Load(string uri, LoadOptions options);
static XElement XElement.Load(TextReader textReader, LoadOptions options);
static XElement XElement.Load(XmlReader reader, LoadOptions options);

Эти методы являются статическими, как и методы XDocument.Load(), поэтому должны вызываться на классе XElement напрямую.

Разбор содержимого с помощью методов XDocument.Parse() или XElement.Parse()

Сколько раз вам приходилось передавать в своих программах XML-содержимое в виде строки, лишь иногда нуждаясь в выполнении некоторой серьезной работы, специфичной для XML? Получение данных из переменной типа string в переменную типа XML-документа всегда связано с определенными трудностями. Отныне об этом можно не беспокоиться. В LINQ to XML доступно необходимое средство — метод Parse.

Оба класса — и XDocument, и XElement — имеют статический метод Parse для разбора строк XML. Поняв, как можно выполнять разбор строки с помощью класса XDocument, эти же знания применимы в отношении класса XElement, и наоборот. И поскольку весь API-интерфейс LINQ to XML построен вокруг элементов, на этот раз будет представлен только пример, ориентированный на элементы.

В статье Сохранение XML в разделе "Сохранение с помощью XDocument.Save()" был показан вывод метода Save, когда для его параметра LoadOptions задано значение DisableFormatting. Результат — единая строка XML. В примере ниже эта строка XML (после отмены внутренних кавычек) подвергается разбору в XML-элемент, который затем выводится на экран:

string xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Employees><Employee type=\"Programmer\" language=\"Russian\"><FirstName>Alex</FirstName><LastName>Erohin</LastName></Employee></Employees>";

XElement xElement = XElement.Parse(xml);
Console.WriteLine(xElement);

Результат выглядит следующим образом:

Разбор строки XML в элемент

Здорово, не правда ли? Вспомните старый способ, когда нужно было создавать документ с использованием класса XmlDocument из W3C XML DOM. Благодаря исключению центральной роли документа, строку XML можно превратить в реальное дерево XML простым вызовом метода.

Пройди тесты
Лучший чат для C# программистов