Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Базовые технологии платформы .NET.pdf
Скачиваний:
65
Добавлен:
11.05.2015
Размер:
1.81 Mб
Скачать

Для описания пространства имён XML в LINQ to XML используется класс XNamespace. У этого класса нет открытого конструктора, но определено неявное приведение строки к XNamespace:

XNamespace ns = "http://astronomy.com/planet";

Чтобы указать на принадлежность имени к определённому пространству имён, следует использовать перегруженную версию оператора +, объединяющую объект XNamespace и строку в результирующий объект XName:

XElement jupiter = new XElement(ns + "name", "Jupiter"); // <name xmlns="http://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="http://astronomy.com/planet">

//<p:name>Jupiter</p:name>

//</p:planet>

20. Дополнительные возможности обработки XML

В дополнение к LINQ to XML, платформа .NET содержит несколько программных интерфейсов для работы с XML. Для этого обычно используются классы из пространств имён вида System.Xml.* (сборка System.Xml.dll).

Классы XmlReader и XmlWriter – это основа механизма последовательного чтения, обработки и записи XML-документов. Такой подход выгодно использовать, когда документ слишком велик, чтобы читать его в память целиком, или содержит ошибки в структуре.

Для чтения XML-документов применяется класс XmlReader и его наследники XmlTextReader (чтение на основе текстового потока), XmlNodeReader (разбор XML из объектов XmlNode) и XmlValidatingReader (чтение с проверкой схемы XML-документа). Класс XmlReader содержит статический метод Create(), создающий объект для чтения на основе Stream, TextReader или строки URI (частный случай URI – имя файла):

XmlReader reader = XmlReader.Create("planets.xml");

Метод Create() принимает в качестве дополнительного аргумента объект класса XmlReaderSettings, который задаёт различные опции чтения данных:

// игнорируем при чтении комментарии и пробельные символы var settings = new XmlReaderSettings();

83

settings.IgnoreComments = true; settings.IgnoreWhitespace = true;

XmlReader reader = XmlReader.Create("planets.xml", settings);

Объект XmlReader извлекает XML-конструкции из документа при помощи метода Read()1. Тип текущей конструкции можно узнать, используя свойство NodeType, значениями которого являются элементы перечисления XmlNodeType. В табл. 15 приведены основные элементы этого перечисления. С конструкцией работают, применяя свойства Name (имя элемента), Value (данные элемента) и некоторые другие.

Таблица 15

Основные элементы перечисления XmlNodeType

Значение

Пример

CDATA

<![CDATA[ This is CDATA info ]]>

Comment

<!-- первые четыре планеты -->

Document

<planets> (корневой элемент)

Element

<planet>

EndElement

</planet>

ProcessingInstruction

<?perl lower-to-upper-case ?>

Text

Mercury

Whitespace

\r \t \n (перевод строки, табуляция)

XmlDeclaration

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

Следующий пример демонстрирует разбор XML-файла и печать разобранных конструкций:

using (var r = XmlReader.Create("planets.xml"))

{

while (r.Read())

{

Console.Write("{0}\t", r.Depth); switch (r.NodeType)

{

case XmlNodeType.Element: case XmlNodeType.EndElement:

Console.WriteLine(r.Name); break;

case XmlNodeType.Text: case XmlNodeType.Comment:

case XmlNodeType.XmlDeclaration: Console.WriteLine(r.Value); break;

}

}

}

1 У класса XmlReader имеются также специфичные методы чтения конкретного содержимого

XML-документа (например, ReadContentAsInt(), ReadAttributeValue()).

84

Для чтения атрибутов текущего элемента можно использовать индексатор XmlReader, указав имя или позицию атрибута (если атрибута не существует, индексатор вернёт значение null):

// переписанный фрагмент оператора switch из предыдущего примера switch (r.NodeType)

{

case XmlNodeType.Element: Console.WriteLine(r.Name); string attribute = r["units"];

Console.WriteLine(attribute ?? string.Empty); break;

. . .

}

Набор методов класса XmlReader, начинающихся с префикса MoveTo (MoveToElement() и т. п.), может использоваться для перехода к следующей XML-конструкции в потоке. Вернуться к просмотренным конструкциям нельзя.

Класс XmlWriter – это абстрактный класс для создания XML-данных. Подчеркнём, что XML-данные всегда могут быть сформированы в виде простой строки и затем записаны в любой поток. Однако такой подход не лишён недостатков – возрастает вероятность неправильного формирования структуры XML из-за элементарных ошибок. Класс XmlWriter и его наследники (например, XmlTextWriter) предоставляют более «помехоустойчивый» способ генерации XML-документа.

Приведём пример работы с классом XmlWriter.

// опция для формирования отступов в документе

var settings = new XmlWriterSettings {Indent = true };

using (var writer = XmlWriter.Create("customers.xml", settings))

{

//начинаем с XML-декларации writer.WriteStartDocument();

//открывающий тег с двумя атрибутами writer.WriteStartElement("customer"); writer.WriteAttributeString("id", "1"); writer.WriteAttributeString("status", "archived");

//вложенный элемент со строковым содержимым writer.WriteElementString("name", "Alex");

//так пишутся элементы с не строковым содержимым

//для этого используется метод WriteValue() writer.WriteStartElement("birthdate"); writer.WriteValue(new DateTime(1975, 8, 4)); writer.WriteEndElement();

85

// закрывающие теги (принцип стека) writer.WriteEndElement(); writer.WriteEndDocument();

}

Этот пример формирует следующий XML-документ:

<?xml version="1.0" encoding="utf-8"?> <customer id="1" status="archived">

<name>Alex</name> <birthdate>1975-08-04T00:00:00</birthdate>

</customer>

Классы XmlNode, XmlAttribute, XmlElement, XmlDocument служат для пред-

ставления XML-документа в виде дерева объектов. Программный интерфейс, основанный на использовании данных классов, являлся предшественником LINQ to XML. В связи с этим ограничимся только простым примером, демонстрирующим работу с указанными классами:

public static void OutputNode(XmlNode node)

{

Console.WriteLine("Type= {0} \t Name= {1} \t Value= {2}", node.NodeType, node.Name, node.Value);

if (node.Attributes != null)

{

foreach (XmlAttribute attr in node.Attributes)

{

Console.WriteLine("Type={0} \t Name={1} \t Value={2}", attr.NodeType, attr.Name, attr.Value);

}

}

// если есть дочерние элементы, рекурсивно обрабатываем их if (node.HasChildNodes)

{

foreach (XmlNode child in node.ChildNodes)

{

OutputNode(child);

}

}

}

// пример использования метода OutputNode() var doc = new XmlDocument(); doc.Load("planets.xml"); OutputNode(doc.DocumentElement);

86