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>
Поделиться с друзьями: