![]() Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Технология LINQ to XML
Технология LINQ to XML предоставляет программный интерфейс для работы с XML-документами, описываемыми в виде дерева объектов. Этот программный интерфейс обеспечивает создание, редактирование и трансформацию XML, при этом возможно применение LINQ-подобного синтаксиса. LINQ to XML содержит набор классов, сосредоточенных в пространстве имён System.Xml.Linq (рис. 6): 1. Абстрактные классы XObject, XNode и XContainer служат основой для иерархии классов, соответствующих различным объектам XML. 2. Классы XElement и XDocument представляют XML-элемент и XML-документ соответственно. 3. Класс XAttribute служит для описания XML-атрибута. 4. Класс XText представляет текст в XML-элементе. 5. Класс XName представляет имя атрибута или элемента. 6. Классы XDeclaration, XDocumentType, XProcessingInstruction, XComment описывают соответствующие части XML-документа. 7. Статический класс Extensions содержит методы расширения для выполнения запросов к XML-данным. Рис. 6. Основные классы LINQ to XML. Центральную роль в работе с XML-данными играют классы XElement, XDocument и XAttribute. Для создания отдельного XML-элемента обычно используется один из конструкторов класса XElement: public XElement(XElement other); public XElement(XName name); public XElement(XStreamingElement other); public XElement(XName name, object content); public XElement(XName name, params object[] content); Первая версия конструктора XElement является копирующим конструктором, а вторая – создаёт пустой элемент. Обсудим использование четвёртой версии, которая позволяет указать имя элемента и его содержимое. Заметим, что существует неявное преобразование строки в XName. Интерпретация аргумента content производится по табл. 14. Таблица 14 Интерпретация аргумента content конструктора класса XElement
Ниже приведены различные варианты вызова конструктора XElement: var e1 = new XElement(" name", " Earth"); // < name> Earth< /name>
var e2 = new XElement(" planet", e1); // < planet> // < name> Earth< /name> // < /planet>
var e3 = new XElement(" period", new XAttribute(" units", " days")); // < period units=" days" />
var e4 = new XElement(" comment", new XComment(" the comment")); // < comment> // <! --the comment--> // < /comment>
var e5 = new XElement(" list", new List< object> {" text", new XElement(" name", " Mars")}); // < list> // text< name> Mars< /name> // < /list>
var e6 = new XElement(" moon", null); // < moon />
var e7 = new XElement(" date", DateTime.Now); // < date> 2010-01-19T11: 04: 54.625+02: 00< /date> Пятая версия конструктора XElement подобна четвёртой, но позволяет предоставить множество объектов для содержимого: var p = new XElement(" planets", new XElement(" planet", new XElement(" name", " Mercury")), new XElement(" planet", new XElement(" name", " Venus")), new XElement(" planet", new XElement(" name", " Earth"), new XElement(" moon", new XElement(" name", " Moon"), new XElement(" period", 27.321582, new XAttribute(" units", " days"))))); Console.WriteLine(p); // выводим первые три планеты в виде XML Использование конструктора XAttribute для создания XML-атрибута очевидно из приведённых выше примеров. Конструкторы класса XDocument позволяют указать декларацию XML-документа и набор объектов содержимого. В этот набор могут входить комментарии, инструкции по обработке и не более одного XML-элемента: var d = new XDeclaration(" 1.0", " utf-8", " yes"); // используем элемент p из предыдущего примера var doc = new XDocument(d, new XComment(" первые три планеты"), p); Console.WriteLine(doc.Declaration); // печатаем декларацию Console.WriteLine(doc); // печатаем документ Кроме применения конструкторов, объекты XML можно создать из строкового представления при помощи статических методов XElement.Parse() и XDocument.Parse(): var planet = XElement.Parse(" < name> Earth< /name> "); Для сохранения элемента или XML-документа используется метод Save(), имеющийся у XElement и XDocument. Данный метод перегружен и позволяет выполнить запись в текстовый файл или с применением адаптеров TextWriter и XmlWriter. Кроме этого, можно указать опции сохранения (например, отключить автоматическое формирование отступов элементов). doc.Save(" planets.xml", SaveOptions.None); Загрузка элемента или XML-документа выполняется статическими методами XElement.Load() или XDocument.Load(). Метод Load() перегружен и позволяет выполнить загрузку из файла, произвольного URI, а также с применением адаптеров TextReader и XmlReader. Можно задать опции загрузки (например, связать с элементами XML номер строки в исходном тексте). var d1 = XDocument.Load(" planets.xml", LoadOptions.SetLineInfo); var d2 = XElement.Load(" https://habrahabr.ru/rss/"); Рассмотрим набор методов и свойств, используемых в LINQ to XML при выборке данных. Класс XObject имеет свойство NodeType для типа XML-узла и свойство Parent, указывающее, какому элементу принадлежит узел. Методы классов XNode и XContainer позволяют получить у элемента наборы предков и дочерних узлов (элементов). При этом возможно указание фильтра – имени элемента. Большинство методов возвращают коллекции, реализующие IEnumerable[14]. // методы выборки у XNode public IEnumerable< XElement> Ancestors(); // + XName name public IEnumerable< XElement> ElementsAfterSelf(); // + XName name public IEnumerable< XElement> ElementsBeforeSelf(); // + XName name public bool IsAfter(XNode node); public bool IsBefore(XNode node); public IEnumerable< XNode> NodesAfterSelf(); public IEnumerable< XNode> NodesBeforeSelf();
// методы выборки у XContainer public IEnumerable< XNode> DescendantNodes(); public IEnumerable< XElement> Descendants(); // + XName name public XElement Element(XName name); public IEnumerable< XElement> Elements(); // + XName name Класс XDocument позволяет получить корневой элемент при помощи свойства Root. В классе XElement есть методы для запроса элементов-предков и элементов-потомков, а также методы для запроса атрибутов. // методы выборки у XElement public IEnumerable< XElement> AncestorsAndSelf(); // + XName name public XAttribute Attribute(XName name); public IEnumerable< XAttribute> Attributes(); // + XName name public IEnumerable< XNode> DescendantNodesAndSelf(); public IEnumerable< XElement> DescendantsAndSelf(); // + XName name Статический класс Extensions определяет несколько методов расширения, работающих с коллекциями элементов или узлов XML: IEnumerable< XElement> Ancestors< T> (...) where T: XNode; IEnumerable< XElement> AncestorsAndSelf(...); IEnumerable< XAttribute> Attributes(...); IEnumerable< XNode> DescendantNodes< T> (...) where T: XContainer; IEnumerable< XNode> DescendantNodesAndSelf(...); IEnumerable< XElement> Descendants< T> (...) where T: XContainer; IEnumerable< XElement> DescendantsAndSelf(...); IEnumerable< XElement> Elements< T> (...) where T: XContainer; IEnumerable< T> InDocumentOrder< T> (...) where T: XNode; IEnumerable< XNode> Nodes< T> (...) where T: XContainer; void Remove(this IEnumerable< XAttribute> source); void Remove< T> (this IEnumerable< T> source) where T: XNode; Продемонстрируем примеры запросов, используя файл planets.xml с описанием четырёх планет. Загрузим файл и выведем имена планет: var xml = XDocument.Load(" planets.xml"); var query = xml.Root.Elements(" planet") .Select(planet => planet.Element(" name").Value); foreach (string name in query) { Console.WriteLine(name); } Выберем все элементы с именем " moon", которые являются потомками корневого элемента. У каждого из полученных элементов возьмём ребёнка с именем " name": var moons = xml.Descendants(" moon").Select(p => p.Element(" name")); Найдём элемент, содержащий указанный текст: var phobos = xml.DescendantNodes().OfType< XText> () .Where(text => text.Value == " Phobos") .Select(text => text.Parent); Модификация XML-информации в памяти выполняется при помощи следующих методов классов XNode, XContainer, XElement[15]: // методы модификации у XNode public void AddAfterSelf(object content); // + params public void AddBeforeSelf(object content); // + params public void Remove(); public void ReplaceWith(object content); // + params
// методы модификации у XContainer public void Add(object content); // + params public void AddFirst(object content); // + params public void RemoveNodes(); public void ReplaceNodes(object content); // + params
// методы модификации у XElement public void RemoveAll(); public void RemoveAttributes(); public void ReplaceAll(object content); // + params public void ReplaceAttributes(object content); // + params public void SetAttributeValue(XName name, object value); public void SetElementValue(XName name, object value); Рассмотрим несколько примеров модификации XML. Начнём с удаления заданных узлов. Для этого используем метод расширения Remove< T> (): var xml = XDocument.Load(" planets.xml"); xml.Element(" planets").Elements(" planet").Elements(" moon").Remove(); Продемонстрируем добавление и замену элементов: var p = XDocument.Load(" planets.xml").Root; p.Add(new XElement(" planet", new XElement(" name", " Jupiter"))); var moon = p.Descendants(" moon").First(); moon.ReplaceWith(new XElement(" DeathStar")); Покажем добавление атрибута к элементу: XElement sun = xml.Element(" planets"); sun.Add(new XAttribute(" MassOfTheSun", " 332.946 Earths")); Функциональные конструкторы и поддержка методами выборки коллекций открывают богатые возможности трансформации наборов объектов в XML. В следующем примере показано создание XML-документа на основе коллекции студентов gr (коллекция описана в параграфе, посвящённом LINQ to objects): var xml = new XElement(" students", from student in gr select new XElement(" student", new XAttribute(" name", student.Name), new XAttribute(" age", student.Age), from mark in student.Marks select new XElement(" mark", mark))); Хотя предыдущий пример использует отложенный оператор Select(), полная итерация по набору выполняется конструктором класса XElement. Если необходимо отложенное конструирование XML-элементов, следует воспользоваться классом XStreamingElement. string[] names = {" John", " Paul", " George", " Pete" }; var xml = new XStreamingElement(" Beatles", from n in names select new XStreamingElement(" name", n)); names[3] = " Ringo"; // это присваивание изменит объект xml Для описания пространства имён XML в LINQ to XML используется класс XNamespace. У этого класса нет открытого конструктора, но определено неявное приведение строки к XNamespace: XNamespace ns = " https://astronomy.com/planet"; Чтобы указать на принадлежность имени к определённому пространству имён, следует использовать перегруженную версию оператора +, объединяющую объект XNamespace и строку в результирующий объект XName: XElement jupiter = new XElement(ns + " name", " Jupiter"); // < name xmlns=" https://astronomy.com/planet" > Jupiter< /name> Префикс пространства имён устанавливается путём добавления в элемент атрибута специального вида. Если префикс задан, им заменяется любое указание пространства имён у дочернего элемента: XElement planet = new XElement(ns + " planet", new XAttribute(XNamespace.Xmlns + " p", ns)); planet.Add(new XElement(ns + " name", " Jupiter")); Console.WriteLine(planet); // < p: planet xmlns: p=" https://astronomy.com/planet" > // < p: name> Jupiter< /p: name> // < /p: planet>
|