Загрузка XML из файла
47LINQ --- LINQ to XML --- Загрузка XML из файла
Создание и сохранение 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 элемента. Вот результат:
Этот вывод похож на ожидаемый, но с одним возможным исключением. Действительно, 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);
Результат выглядит следующим образом:
Здорово, не правда ли? Вспомните старый способ, когда нужно было создавать документ с использованием класса XmlDocument из W3C XML DOM. Благодаря исключению центральной роли документа, строку XML можно превратить в реальное дерево XML простым вызовом метода.