Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Базовые технологии платформы .NET.docx
Скачиваний:
13
Добавлен:
03.11.2018
Размер:
614.46 Кб
Скачать

Запросы, модификация и трансформация xml

Рассмотрим набор методов и свойств, используемых в LINQ to XML при выборке данных. Класс XObject имеет свойство NodeType для типа XML-узла и свойство Parent, указывающее, какому элементу принадлежит узел.

Методы классов XNode и XContainer позволяют получить у элемента наборы предков и дочерних узлов (элементов). При этом возможно указание фильтра – имени элемента. Большинство методов возвращают коллекции, реализующие IEnumerable1.

// методы выборки у 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(p =>

p.Element("name").Value);

foreach (var x in query) Console.WriteLine(x);

Выберем все элементы с именем moon, которые являются потомками корневого элемента. У каждого из полученных элементов возьмём первого ребёнка с именем name:

var moons = xml.Descendants("moon").Select(p => p.Element("name"));

Найдём элемент, содержащий указанный текст:

var phobos = xml.DescendantNodes().OfType<XText>()

.Where(t => t.Value == "Phobos")

.Select(t => t.Parent);

Модификация XML-информации в памяти выполняется при помощи следующих методов классов XNode, XContainer, XElement:1

// методы модификации у 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("MassOfSun", "332.946 Earths"));

Функциональные конструкторы и поддержка методами выборки коллекций открывают богатые возможности трансформации наборов объектов в XML. В следующем примере показано создание XML-документа на основе коллекции студентов gr (см. параграф 2.14):

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";

Console.WriteLine(xml); // Ринго заменил Пита Беста