Чтение онлайн

ЖАНРЫ

C# для профессионалов. Том II

Ватсон Карли

Шрифт:

listBox1.Items.Add(tr.ReadElementString);

 } else

//иначе двигаться дальше

tr.Read;

 }

}

В цикле

while
используется метод
MoveToContent
для поиска каждого узла типа
XmlNodeType.Element
с именем
title
. Если это условие не выполняется, то предложение
else
вызывает метод
Read
для перехода к следующему узлу. Если будет найден узел, соответствующий критерию, то результат работы метода
ReadElementString
добавляется в
listbox
. Таким образом мы получим
заглавия книг в
listbox
. Отметим, что после успешного применения
ReadElementString
метод
Read
не вызывается. Это связано с тем, что метод
ReadElementString
обрабатывает весь
Element
и перемещается к следующему узлу.

Если удалить

&& tr.Name=="title"
из предложения
if
, то придется отслеживать исключение
XmlException
, когда оно будет порождаться. При просмотре файла данных можно заметить, что первым элементом, который найдет метод MoveToContent, является элемент
<bookstore>
. Как элемент он будет проходить проверку в операторе
if
. Но так как он не содержит простой текстовый тип, он вынуждает метод
ReadElementString
порождать исключение
XmlException
. Одним из способов обхода этой проблемы является размещение вызова
ReadElementString
в своей собственной функции. Назовем ее
LoadList
.
XmlTextReader
передается в нее в качестве параметра. Теперь, если вызов
ReadElementString
отказывает внутри этой функции, мы можем иметь дело с ошибкой и вернуться назад в вызывающую функцию. Вот как выглядит пример с этими изменениями (код можно найти в папке
XmlReaderSample3
):

protected void button1_Click(object sender, System.EventArgs e) {

 // использовать файловый поток для получения данных

 FileStream fs = new FileStream("..\\..\\..\\books.xml", FileMode.Open);

 XmlTextReader tr = new XmlTextReader(fs);

 while(!tr.EOF) {

// если встретился тип элемента, проверить и загрузить его в окно списка

if (tr.MoveToContent == XmlNodeType.Element) {

LoadList(tr);

} else

// иначе двигаться дальше

tr.Read;

 }

}

private void LoadList(XmlReader reader) {

 try {

listBox1.Items.Add(reader.ReadElementString);

 }

 //если инициировано исключение XmlException, игнорировать его.

 catch(XmlException er){}

}

Вот что должно появиться, когда код будет выполнен:

Это тот же результат, который был раньше. Мы видим, что существует более одного способа достичь одной и той же цели. При этом становится очевидной гибкость пространства имен

System.Xml
.

По мере чтения узлов можно заметить отсутствие каких-либо атрибутов. Это связано с тем, что атрибуты не считаются частью структуры документа. При нахождении в узле элемента мы можем проверить наличие атрибутов и получить значения атрибутов. Метод

HasAttributes
возвращает
true
, если существуют какие-либо атрибуты, иначе возвращается
false
. Свойство
AttributeCount
сообщит, сколько имеется атрибутов. Метод
GetAttribute
получает атрибут по имени или по индексу. Если желательно просмотреть все атрибуты по очереди, можно использовать методы
MoveToFirstAttribute
(перейти к первому атрибуту) и
MoveToNextAttribute
(перейти к следующему атрибуту). Вот пример просмотра атрибутов из
XmlReaderSample4
:

protected void button1_Click(object sender, System.EventArgs e) {

 //
задаем путь доступа в соответствии со структурой путей доступа

 // к данным

 string fileName = "..\\..\\..\\books.xml";

 // Создать новый объект TextReader

 XmlTextReader tr = new XmlTextReader(filename);

 // Прочитать узел за раз

 while (tr.Read) {

// проверить, что это элемент NodeType

if (tr.NodeType = XmlNodeType.Element) {

// если это — элемент, то посмотрим атрибуты

for(int i=0; i<tr.AttributeCount; i++) {

listBox1.Items.Add(tr.GetAttribute(i));

}

}

 }

}

На этот раз мы ищем узлы элементов. Когда такой узел найден, в цикле просматриваются все атрибуты и с помощью метода

GetAttribute
значение атрибута загружается в
listbox
.

Проверка

Если нужно проверить документ XML, используйте класс

XmlValidatingReader
. Он обладает всей функциональностью класса
XmlTextReader
(оба реализуют
XmlReader
, но
XmlValidatingReader
добавляет свойство
ValidationType
, свойство
Schemes
и свойство
SchemaType
). Свойство
ValidationType
задается как тип проверки, которую желательно выполнить. Допустимые значения этого свойства следующие:

Значение свойства Описание
Auto
Если в
<!DOCTYPE...>
объявлен DTD, он и будет загружаться и обрабатываться. Атрибуты по умолчанию и общие сущности, определенные в DTD, станут доступными. Если найден атрибут XSD
schemalocation
, то загружается и обрабатывается XSD, при этом все атрибуты по умолчанию, определенные в схеме, будут возвращены. Если найдено пространство имен с префиксом MSXML
x-schema:
, загрузится и обработается схема XDR, все атрибуты, определенные по умолчанию, возвратятся.
DTD
Проверка согласно правилам DTD.
Schema
Проверка согласно правилам XSD.
XDR
Проверка согласно правилам XDR.
None
Проверка не выполняется.

Если свойство задано, то должен быть назначен обработчик событий

ValidationEventHandler
. Событие инициируется, когда случается ошибка проверки. На ошибку можно отреагировать любым подходящим образом. Рассмотрим пример. Добавим пространство имен схемы XDR (XML Data Reduced — приведенные данные XML) к файлу
books.xml
и назовем этот файл
booksVal.xml
. Теперь он выглядит так:

<?xml version='1.0'?>

<!-- Этот файл представляет фрагмент базы данных учета запасов книжного склада -->

<bookstore xmlns="x-schema:books.xdr">

 <book genre="autobiography" publicationdate="1981" ISBN="1-861003-11-0">

<title>The Autobiography of Benjamin Franklin</title>

<author>

<first-name>Benjamin</first-name>

<last-name>Franklin</last-name>

</author>

<price>8.99</price>

Поделиться с друзьями: