Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Технология 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

Тип или значение content Способ обработки
string Преобразуется в дочерний объект типа XText и добавляется как текстовое содержимое элемента
XText Добавляет как дочерний объект – текстовое содержимое элемента
XElement Добавляется как дочерний элемент
XAttribute Добавляется как атрибут элемента
XProcessingInstruction, XComment Добавляется как дочернее содержимое. При добавлении объектов типа XAttribute или унаследованных от XNode выполняется клонирование, если эти объекты уже имеют родителя в дереве объектов XML.
IEnumerable Объект перечисляется и обрабатывается рекурсивно. Коллекция строк добавляется в виде единого текста
Null Этот объект игнорируется
Любой прочий тип Вызывается метод ToString(), и результат трактуется как string

Ниже приведены различные варианты вызова конструктора 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>






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.