Текст книги "Программирование мобильных устройств на платформе .NET Compact Framework"
Автор книги: Иво Салмре
Жанр:
Программирование
сообщить о нарушении
Текущая страница: 30 (всего у книги 69 страниц)
Простой пример, иллюстрирующий применение модели XML DOM и однонаправленного чтения-записи XML-документов
Ниже мы сравниваем использование высокоуровневой модели DOM и подхода, основанного на использовании однонаправленных операций чтения-записи XML– данных, на примере работы с простыми XML-документами. В обоих случаях генерируется и используется один и тот же XML-документ. Важно подчеркнуть что, ввиду крайней малости объема используемых XML-данных, приемлемую производительность обеспечивают оба подхода. Реальные различия в производительности скажутся лишь при увеличении объема данных. Чтобы представить мысленную картину того, как это могло бы выглядеть, вообразите, что узел данных UserInfo повторен сотни или тысячи раз. При желании вы можете создать файл данных, соответствующий такой ситуации, и использовать его для тестирования своих алгоритмов с целью сравнения результативности обоих подходов.
Пример: содержимое XML-файла
Обращаю ваше внимание на тот факт, что в качестве узла наивысшего уровня я решил использовать не узел UserInfo, а размещенный над ним дополнительный узел. Такая практика поощряется, поскольку XML допускает существование на самом верхнем уровне только одного узла, который называется "корневым" ("root node"). Оставив в качестве корневого узел UserInfo, мы значительно ограничили бы свои возможности в отношении сохранения другой информации наивысшего уровня в файле без пересмотра проекта.
Использование типового узла наивысшего уровня позволяет свободно добавлять другие узлы нижележащего уровня по мере расширения потребностей. Так, для сохранения важной информации, не зависящей от пользователя, мы могли бы теперь в дополнение к узлу UserInfo ввести узлы ServerInfo и ApplicationInfo. Кроме того, пользователей может быть несколько, и для каждого из них требуется ввести свой узел UserInfo. Описанная выше структура поддерживает включение нескольких разделов UserInfo, следующих один за другим, что было бы невозможным, если бы узел UserInfo был корневым
XML DOMXML DOM работает с представлением данных в виде дерева объектов в памяти. Каждый XML-элемент представляется хранящимся в памяти объектом. Можно считать, что подход XML DOM в значительной степени основан на концепции состояния в том смысле, что все данные, необходимые для воссоздания XML-документа после его считывания, загружаются как состояние. XML-деревья могут создаваться в памяти, а затем сериализоваться в файлы или через сетевые потоки. Аналогичным образом, любое XML-содержимое или XML-документ, полученный с использованием любого потока данных, могут быть использованы для заполнения дерева XML DOM в памяти.
Создание дерева объектов в памяти является удобным способом работы с данными среднего объема, которые требуется всего лишь последовательно обновлять. XML-файл размером 20 Кбайт можно довольно быстро загрузить в память и после работы с ним в памяти как с деревом объектов вновь сохранить в файловой системе. Коль скоро объемы интересующих нас данных невелики, модель XML DOM предоставляет отличные возможности для создания XML-документов, обработки их в памяти и вывода XML-данных в файл или сетевой поток.
Применимость DOM-подхода ограничивается как объемом памяти, доступной для размещения сгенерированного анализатором дерева объектов, так и наличием резервов вычислительной мощности, необходимых для разбора всего дерева XML-данных. Недостатком подхода, основанного на XML DOM, является его монолитность; прежде чем вы сможете получить доступ к XML-данным, вы должны выполнить синтаксический анализ документа и разместить в памяти все содержимое файла или потока. Если вам необходимо работать лишь с небольшим объемом данных, содержащихся в файле большого размера, то доступ к этим данным будет сопряжен с большими накладными расходами.
Соображения, побуждающие к использованию подхода, основанного на модели XML DOM
■ XML DOM – простая и вместе с тем предлагающая богатые возможности программная модель. Представление XML-документа деревом объектов, хранящимся в памяти, упрощает работу с данными, к которым требуется произвольный доступ.
■ XML DOM отлично подходит для работы с данными небольшого или среднего объема. Коль скоро файл данных имеет достаточно небольшие размеры, его содержимое не займет слишком много места в памяти.
■ XML DOM – наилучший выбор, если необходимо работать (имея возможность вносить изменения) сразу со всеми находящимися в памяти XML-данными. XML DOM является чрезвычайно мощным инструментом, если вашему приложению необходимо работать с данными в режиме произвольного доступа, а данные после их обработки должны быть заново сохранены в файле на диске или потоке.
Соображения, побуждающие избегать использования подхода, основанного на модели XML DOM
■ Модель программирования XML DOM вынуждает вас выполнять синтаксический анализ и загрузку XML-данных в дерево объектов, хранящееся в памяти, прежде чем вы сможете получить к ним доступ. Слишком расточительно создавать в памяти крупное по размерам дерево всего документа, если вашему приложению требуется доступ лишь к небольшой части входящих в него XML-данных.
■ Использование модели XML DOM приведет к постепенному снижению производительности по мере роста размеров XML-документов. Поскольку в случае крупных файлов многие объекты будут создаваться в условиях ограниченных ресурсов памяти устройства, это иногда может стать причиной нехватки памяти. Кроме того, все созданные объекты впоследствии должны быть удалены из памяти сборщиком мусора, что обременит ваше приложение дополнительными накладными расходами.
■ Не стоит останавливать свой выбор на XML DOM, если данные будут использоваться только в режиме чтения. DOM привносит дополнительные накладные расходы, но упрощает обратную запись данных из памяти на носитель. Если данные будут использоваться только в режиме чтения или вы планируете записывать их в другом формате, то потеряете в производительности, ничего не получая взамен.
В листинге 10.1 содержится пример кода, предназначенного для чтения и записи представленных выше XML-данных с использованием модели XML DOM.
Листинг 10.1. Использование XML DOM для сохранения данных в файле и их загрузки
using System;
//–
//Демонстрирует сохранение и загрузку файлов с
//использованием объектной модели документов XML
//–
public class SaveAndLoadXML_UseDOM {
//XML-дескрипторы, которые мы будем использовать в нашем документе
const string XML_ROOT_TAG = "AllMyData";
const string XML_USERINFO_TAG = "UserInfo";
const string XML_USERID_TAG = "UserID";
const string XML_NAMEINFO_TAG = "Name";
const string XML_FIRSTNAME_TAG = "FirstName";
const string XML_LASTNAME_TAG = "LastName";
//–
//Загружает пользовательское состояние
//
// [in] fileName: Имя файла, используемого для сохранения данных
// [out] userId: Загруженный идентификатор пользователя
// [out] firstName: Загруженное имя пользователя
// [out] lastName: Загруженная фамилия пользователя
//–
public static void XML_LoadUserInfo(string fileName, out int userId, out string firstName, out string lastName) {
//Начинаем с нулевых значений
userId = 0;
firstName = "";
lastName = "";
//Предполагаем, что данные еще не загружены
bool gotUserInfoData = false;
System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
xmlDocument.Load(fileName);
//Получить корневой узел
System.Xml.XmlElement rootElement;
rootElement = (System.Xml.XmlElement)xmlDocument.ChildNodes[0];
//Убедиться в том, что корневой узел согласуется с ожидаемым текстом,
//ибо противное означает, что мы имеем дело с каким-то другим XML-файлом
if (rootElement.Name != XML_ROOT_TAG) {
throw new Exception("Тип корневого узла не совпадает с ожидаемым!");
}
//–
//Простой конечный автомат для итеративного обхода всех узлов
//–
foreach(System.Xml.XmlElement childOf_RootNode in rootElement.ChildNodes) {
//Если это узел UserInfo, то мы хотим просмотреть его содержимое
if (childOf_RootNode.Name == XML_USERINFO_TAG) {
gotUserInfoData = true; //Пользовательские данные найдены
//–
//Загрузить каждый из подэлементов
//–
foreach(System.Xml.XmlElement child_UserDataNode in childOf_RootNode.ChildNodes) {
//Идентификатор пользователя (UserID)
if (child_UserDataNode.Name == XML_USERID_TAG) {
userId = System.Convert.ToInt32(child_UserDataNode.InnerText);
}
//ФИО пользователя (UserName)
else if (child_UserDataNode.Name == XML_NAMEINFO_TAG) {
foreach(System.Xml.XmlElement child_Name in child_UserDataNode.ChildNodes) {
//Имя (FirstName)
if (child_Name.Name == XML_FIRSTNAME_TAG) {
firstName = child_Name.InnerText;
}
//Фамилия (LastName)
else if (child_Name.Name == XML_LASTNAME_TAG) {
lastName = child_Name.InnerText;
}
}//Конец цикла разбора UserName
}//Конец оператора if, осуществляющего проверку UserName
}//Конец цикла разбора UserInfo
}// Конец оператора if, осуществляющего проверку UserInfo
}//Конец цикла разбора корневого узла
if (gotUserInfoData == false) {
throw new Exception ("Данные пользователя в XML-документе не найдены!");
}
}
//–
//Сохраняет пользовательское состояние
//
// [in] fileName: Имя файла, используемого для сохранения данных
// [in] userId:Идентификатор пользователя, которыймы хотим сохранить
// [in] firstName: Имя пользователя, которое мы хотим сохранить
// [in] lastName: Фамилия пользователя, которую мы хотим сохранить
//–
public static void XML_SaveUserInfo(string fileName, int userId, string firstName, string lastName) {
System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
//–
//Добавить элемент документа высшего уровня
//–
System.Xml.XmlElement rootNodeForDocument;
rootNodeForDocument = xmlDocument.CreateElement(XML_ROOT_TAG);
xmlDocument.AppendChild(rootNodeForDocument);
//–
//Добавить данные в элемент UserInfo
//–
System.Xml.XmlElement topNodeForUserData;
topNodeForUserData = xmlDocument.CreateElement(XML_USERINFO_TAG);
rootNodeForDocument.AppendChild(topNodeForUserData);
//–
//Добавить значение UserID в наш документ
//–
//Создать подузел для информации о пространстве имен
System.Xml.XmlElement subNodeForUserID;
subNodeForUserID = xmlDocument.CreateElement(XML_USERID_TAG);
subNodeForUserID.InnerText = System.Convert.ToString(userId);
//Присоединить подузел UserID к узлу высшего уровня
topNodeForUserData.AppendChild(subNodeForUserID);
//–
//Добавить все значения NameInfo в наш документ
//–
//Создать подузел для информации о пространстве имен
System.Xml.XmlElement subNodeForNameInfo;
subNodeForNameInfo = xmlDocument.CreateElement(XML_NAMEINFO_TAG);
//Имя (FirstName)
System.Xml.XmlElement subNodeFirstName;
subNodeFirstName = xmlDocument.CreateElement(XML_FIRSTNAME_TAG);
subNodeFirstName.InnerText = firstName;
//Фамилия (LastName)
System.Xml.XmlElement subNodeLastName;
subNodeLastName = xmlDocument.CreateElement(XML_LASTNAME_TAG);
subNodeLastName.InnerText = lastName;
//Присоединить подузлы имени и фамилии к родительскому
//узлу NameInfo
subNodeForNameInfo.AppendChild(subNodeFirstName);
subNodeForNameInfo.AppendChild(subNodeLastName);
//Присоединить подузел NameInfo (вместе с его дочерними узлами)
//к узлу высшего уровня
topNodeForUserData.AppendChild(subNodeForNameInfo);
//–
//Сохранить документ
//–
try {
xmlDocument.Save(fileName);
}
catch (System.Exception ex) {
System.Windows.Forms.MessageBox.Show("Ошибка при сохранении XML-документа – " + ex.Message);
}
} //Конец функции
} //Конец класса
Листинг 10.2. Вызов кода, предназначенного для сохранения и загрузки XML-документа
private void button1_Click{object sender, System.EventArgs e) {
const string FILENAME = "TestFileName.XML";
//Сохранить, используя XML DOM
SaveAndLoadXML UseDOM.XML_SaveUserInfo(FILENAME, 14, "Ivo", "Salmre");
//Сохранить, используя объект однонаправленной записи XMLWriter
//SaveAndLoadXML_UseReaderWriter.XML SaveUserInfo(FILENAME,
// 18, "Ivo", "Salmre");
int userID;
string firstName;
string lastName;
//Загрузить, используя XML DOM
SaveAndLoadXML_UseDOM.XML_LoadUserInfo(FILENAME, out userID, out firstName, out lastName);
//Загрузить, используя объект однонаправленного чтения XMLReader
//SaveAndLoadXML_UseReaderWriter.XMILoadUserInfo(FILENAME,
// out userID, out firstName, out lastName);
System.Windows.Forms.MessageBox.Show('Готово!" + userID.ToString() + ", " + lastName + ", " + firstName);
}
В отличие от подхода XML DOM, обеспечивающего произвольный доступ к XML-данным и интенсивно использующего информацию о состоянии, объекты XMLReader и XMLWriter обеспечивают лишь возможности однонаправленного доступа. Они поддерживают минимальный объем информации о состоянии, которого достаточно для чтения и записи XML-данных, и не пытаются создавать в памяти дерево XML-данных или работать с ним. В этом случае говорят о моделях однонаправленного доступа, поскольку они поддерживают программный курсор, указывающий на текущую позицию в XML-файле, и позволяют работать только с находящимися в этом месте данными; курсор может перемещаться только в прямом направлении, но не в обратном. Объект XMLReader предлагает много возможностей, но в приложениях используется в основном для прохождения узлов XML-документа. При чтении XML-документа XMLReader каждый раз считывает только один узел и связанные с ним атрибуты; это напоминает чтение обычного файла по одной строке за один раз. Когда разработчик заканчивает просмотр узла и его атрибутов, он отдает объекту XMLReader команду перейти к следующему элементу, в результате чего XMLReader сбрасывает содержащуюся в нем информацию, которая относится к содержимому текущего узла. Однонаправленность доступа является необходимой платой за достижение наилучшей производительности и снижение накладных расходов.
Следует отметить, что XML DOM строится поверх классов XMLReader и XMLWriter. XML DOM использует XMLReader для синтаксического анализа XML-документа и создает в памяти дерево на основе считанных данных. При записи XML-документа DOM итеративно проходит узлы находящегося в памяти дерева и выводит их через XMLWriter в поток или файл. Как следствие, все, что можно сделать с использованием XML DOM, можно сделать, используя XMLReader и XMLWriter. XML DOM делает все возможное для того, чтобы с наибольшей эффективностью выполнять функции универсального XML-анализатора с произвольным доступом, максимально использующего информацию о состоянии.
Преимущества использования объектов XMLReader и XMLWriter вместо XML DOM коренятся в оптимизации, которая становится возможной либо благодаря тому, что вашему приложению не требуется универсальный синтаксический анализатор, либо благодаря тому, что работу можно выполнить, храня в памяти меньший объем информации о состояния, поскольку вам может не требоваться запись в файл всего XML-дерева, в которое были считаны XML-данные. Если нет нужды в использовании всех богатых функциональных возможностей XML DOM, то XMLReader и XMLWriter позволят добиться лучшей производительности, работая на более низком уровне абстракции.
Чем XMLReader и XMLWriter отличаются от SAX?
В .NET Framework и .NET Compact Framework реализован подход, основанный на использовании программного курсора, при котором алгоритмы конечного разработчика отдают объекту XMLReader команды относительно перемещения курсора в прямом направлении и синтаксического анализа очередных элементов XML-данных, однако это не единственный из подходов, в которых используется однонаправленная обработка XML– данных. Другим популярным подходом аналогичного рода является модель SAX (Simple API for XML Model – простой API-интерфейс для работы с XML). В то время как при работе с XMLReader используется подход на основе программного курсора, предоставляющий программисту возможность выбирать, как и когда перемещаться курсору в прямом направлении, SAX представляет собой модель, основанную на событиях, в которой механизм синтаксического анализа выполняет проход по всему XML-документу (также только в прямом направлении) и генерирует события, которые код конечного разработчика может обрабатывать для исследования содержимого XML-документа в ходе его анализа. Модель XMLReader основана на "извлечении" данных, то есть код приложения извлекает очередную порцию XML-данных, которые необходимо обработать. Модель SAX основана на "выталкивании" данных, то есть порции XML-данных передаются событиям, которые обрабатываются кодом приложения. Обе модели преследуют одну и ту же цель, а именно – облегчить быстрое выполнение синтаксического анализа XML-документов при низких накладных расходах. Выбор между моделями SAX и XMLReader/XMLWriter определяется личными предпочтениями и доступностью соответствующих средств на платформе, с которой вы работаете. Приведенные в данном разделе рекомендации в равной степени справедливы для обеих моделей.
Соображения, побуждающие к использованию однонаправленной обработки XML-данных
■ Такие модели однонаправленного чтения данных, как XMLReader, обеспечивают наиболее быстрые и надежные способы чтения XML-данных даже в случае гигантских файлов. Минимальным требованием является поддержка каркасом информации о состоянии в процессе выполнения синтаксического анализа XML-документа. Объем этой информации не растет с увеличением размера анализируемого XML-документа, и поэтому ограничения на размеры XML-документов, которые вы хотите просматривать для извлечения необходимых данных, практически отсутствуют. Единственным долговременным генерируемым состоянием являются объекты, которые создаются вашим приложением, исходя из нужд анализа.
■ Такие модели однонаправленной записи данных, как модель XMLWriter, обеспечивают наиболее быстрые и простые способы записи корректно сформированных XML-документов. Коды для записи XML-данных при помощи объекта XMLWriter работают быстро и отличаются простотой. Даже в случае сложных XML-документов ваш код, реализующий навигацию между вашими собственными внутренними структурами данных, скорее всего, окажется более сложным, чем код, с помощью которого осуществляется запись XML-данных из памяти. Использовать для вывода XML-дескрипторов объект XMLWriter для гораздо проще, чем самостоятельно написать предназначенный для этого пользовательский код. Существует довольно мало причин, если таковые вообще находятся, по которым следовало бы поступать иначе.
■ Модели однонаправленной обработки прекрасно подходят для извлечения определенных данных или записи коротких потоков XML-данных. Если вас интересует извлечение из XML-документа только определенных данных и вам известно, где именно в иерархии данных файла они находятся, то использование объекта XMLReader и собственного конечного автомата для перехода к нужным данным не вызывает особых затруднений. Аналогичным образом, если вам заранее известно, каким должен быть формат XML-данных, выводимых для записи, работа с объектом XMLWriter не будет для вас сложной.
Соображения, побуждающие избегать использования однонаправленной обработки XML-данных
■ Модели однонаправленной обработки данных не поддерживают произвольный доступ к элементам документа. Вам дается только один "выстрел", чтобы успеть сделать что-либо с данными по мере их чтения. Если ваш алгоритм нуждается в динамическом перекрестном использовании данных или внесении взаимосвязанных изменений в данные, относящиеся к различным частям XML-документа, то для этого вам придется самостоятельно написать довольно сложный код, интенсивно использующий информацию о состоянии. Поскольку модель XML DOM поддерживает хранящееся в памяти дерево документа, она позволяет легко совершать обход этого дерева для поиска нужных узлов и внесения необходимых изменений.
■ Модели однонаправленной обработки данных требуют выполнения значительного объема работы для реконструкции всей структуры дерева. Если вы хотите вывести для записи тот же самый документ, который был считан, то вам придется продублировать значительную часть той функциональности XML DOM, при помощи которой это можно было бы сделать. Объекты XMLReader отлично приспособлены для извлечения определенных порций данных. Объекты XMLWriter отлично приспособлены для быстрого вывода вашим приложением определенных элементов XML-данных. Если же вам необходимо считать XML-документ и внести в него значительные изменения перед тем, как записать его обратно, то ваш друг – DOM.
■ Модели однонаправленной обработки требуют использования более сложных программных моделей, реализующих навигацию и операции поиска в сложных документах. Написание кода универсального синтаксического анализатора, который работал бы с произвольными иерархиями XML, может вызывать большие трудности. Чтобы найти искомую информацию, вам придется использовать очень сложное состояние, позволяющее определять, в каком узле дерева документа вы находитесь. Так, если вы осуществляете поиск дескриптора
Ниже приведен простой код, предназначенный для чтения и записи представленных ранее данных с использованием модели однонаправленной обработки XML– документов с помощью объектов XMLReader и XMLWriter. Особый интерес для вас может представлять конечный автомат, используемый в объекте XMLReader для отслеживания текущего места в документе; заметьте, что даже для столь простого XML-документа, как наш, этот код вовсе не тривиален. В противоположность этому код, предназначенный для вывода XML-документов при помощи объекта XMLWriter, отличается простотой.
Листинг 10.3. Использование однонаправленного чтения-записи XML-данных для загрузки XML-документа из файла и его сохранения
using System;
public class SaveAndLoadXML UseReaderWriter {
//XML-дескрипторы, которые мы будем использовать в своем документе
const string XML_ROOT_TAG = "AllMyData";
const string XML_USERINFO_TAG = "UserInfo";
const string XMI_USERID_TAG = "UserID";
const string XML_NAMEINFO_TAG = "Name";
const string XML_FIRSTNAME_TAG = "FirstName";
const string XML_LASTNAME TAG = "LastName";
//Набор состояний, отслеживаемых по мере чтения данных
private enum ReadLocation {
inAllMyData,
inUserInfo,
inUserID,
inName,
inFirstName,
inLastName,
}
//–
//Сохраняет пользовательское состояние
//
// [in] fileName: Имя файла, используемого для сохранения данных
// [in] userId: Идентификатор пользователя, который мы хотим сохранить
// [in] firstName: Имя пользователя, которое мы хотим сохранить
// [in] lastName: Фамилия пользователя, которую мы хотим сохранить
//–
public static void XML_SaveUserInfo(string fileName, int userId,string firstName, string lastName) {
System.Xml.XmlTextWriter xmlTextWriter;
xmlTextWriter =new System.Xml.XmlTextWriter(fileName, System.Text.Encoding.Default);
//Записать содержимое документа!
//
xmlTextWriter.WriteStartElement(XML_ROOT_TAG);
//
xmlTextWriter.WriteStartElement(XML_USERINFO_TAG);
//
//
xmlTextWriter.WriteStartElement(XML_NAMEINFO_TAG);
//
xmlTextWriter.WriteStartElement(XML_FIRSTNAME_TAG);
//
xmlTextWriter.WriteString(firstName); //Запись значения
xmlTextWriter.WriteEndElement(); //Закрыть дескриптор имени
//
xmlTextWriter.WriteStartElement(XML_LASTNAME_TAG);
//
xmlTextWriter.WriteString(lastName); //Запись значения
xmlTextWriter.WriteEndElement(); //Закрыть дескриптор фамилии
//
xmlTextWriter.WriteEndElement(); //Закрыть дескриптор ФИО
//
//
xmlTextWriter.WriteStartElement(XML_USERID_TAG);
//
//Запись значения
xmlTextWriter.WriteString(userId.ToString());
xmlTextWriter.WriteEndElement();
//Закрыть дескриптор UserID
//
xmlTextWriter.WriteEndElement(); //Закрыть дескриптор UserInfo
//
xmlTextWriter.WriteEndElement(); //Закрыть дескриптор документа
//
xmlTextWriter.Close();
}
//–
//Загружает пользовательское состояние
//
// [in] fileName: Имя файла, используемого для сохранения данных
// [out] userId: Загруженный идентификатор пользователя
// [out] firstName: Загруженное имя пользователя
// [out] lastName: Загруженная фамилия пользователя
//–
public static void XML_LoadUserInfo(string fileName, out int userId, out string firstName,out string lastName) {
ReadLocation currentReadLocation;
//Начинаем с нулевых значений
userId = 0;
firstName = "";
lastName = "";
System.Xml.XmlTextReader xmlReader = new System.Xml.XmlTextReader(fileName);
xmlReader.WhitespaceHandling = System.Xml.WhitespaceHandling.None;
bool readSuccess;
readSuccess = xmlReader.Read();
if (readSuccess == false) {
throw new System.Exception("Отсутствуют XML-данные для чтения!");
}
//Убедиться в том, что мы распознали корневой дескриптор
if (xmlReader.Name != XML_ROOT_TAG) {
throw new System.Exception("Корневой дескриптор отличается от ожидаемого!");
}
//Отметить текущее местоположение в документе
currentReadLocation = ReadLocation.inAllMyData;
//–
//Цикл прохождения документа и чтение необходимых данных
//–
while (readSuccess) {
switch (xmlReader.NodeType) {
//Вызывается при входе в новый элемент
case System.Xml.XmlNodeType.Element: {
string nodeName = xmlReader.Name;
LoadHelper_NewElementEncountered(nodeName, ref currentReadLocation);
break;
}
//–
//Здесь мы можем извлечь некоторый фактический текст и
//получить данные, которые пытаемся загрузить
//–
case System.Xml.XmlNodeType.Text: {
switch (currentReadLocation) {
case ReadLocation.inFirstName: {
firstName = xmlReader.Value;
break;
}
case ReadLocation.inLastName: {
lastName = xmlReader.Value;
break;
}
case ReadLocation.inUserID: {
userId = System.Convert.ToInt32(xmlReader.Value);
break;
}
}
break;
}
//–
//Вызывается, когда встречается конец
//элемента
//
//Мы можем захотеть переключить состояние в зависимости от вида
//покидаемого узла, чтобы указать на то, что собираемся
//вернуться назад к его предку
//–
case System.Xml.XmlNodeType.EndElement: {
bool continueParsing;
continueParsing = LoadHelper_EndElementEncountered(ref currentReadLocation);
if (continueParsing ==false) {
goto finished_reading_wanted_data;
}
break;
}
default: {
//He страшно, если имеются XML-узлы других типов, но
//в нашем примере работы с XML-документом мы должны
//оповестить об этом факте...
System.Windows.Forms.MessageBox.Show("Встретился непредвиденный XML-тип " + xmlReader.Name);
break;
}
} //Конец оператора Case, используемого для определения текущего
//типа XML-элeмeнтa, oбpaбaтывaeмoгo анализатором
//Перейти к следующему узлу
readSuccess = xmlReader.Read();
}
//Если мы оказались в этом месте программы, не покинув
//XML-дескриптора UserInfo, то с XML-данными, которые
//мы считываем, что-то не так
throw new Exception("He найден элемент UserInfo в XML-документе!");
finished_reading_wanted_data:
//Закрыть файл, поскольку работа с ним закончена!
xmlReader.Close();
}
//–
//Вспомогательный код, ответственный за принятие решения
//относительно того, в какое состояние необходимо перейти,
//когда встречается закрывающий дескриптор
//–
private static bool LoadHelper_EndElementEncountered(ref ReadLocation currentReadLocation) {
switch (currentReadLocation) {
//Если мы покидаем узел Name, то должны вернуться
//обратно в узел UserInfo
case ReadLocation.inName: {
currentReadLocation = ReadLocation.inUserInfo;
break;
}
//Если мы покидаем узел FirstName, то должны вернуться
//обратно в узел Name
case ReadLocation.inFirstName: {
currentReadLocation = ReadLocation.inName;
break;
}
//Если мы покидаем узел LastName, то должны вернуться
//обратно в узел Name
case ReadLocation.inLastName: {
currentReadLocation = ReadLocation.inName;
break;
}
//Если мы покидаем узел UserID, то должны вернуться
//обратно в узел UserInfo
case ReadLocation.inUserID: {
currentReadLocation = ReadLocation.inUserInfo;
break;
}
//Если мы покидаем узел UserInfo, то мы только что
//закончили чтение данных в узлах UserID, FirstName
//и LastName.
//
//Можно выйти из цикла, поскольку у нас уже есть вся
//информация, которую мы хотели получить!
case ReadLocation.inUserInfo: {
return false; //Анализ должен быть прекращен
}
}
return true; //Продолжить анализ
}
private static void LoadHelper_NewElementEncountered(string nodeName,ref ReadLocation currentReadLocation) {
//–
//Мы вошли в новый элемент!
//
//B какое состояние переход возможен, зависит от того, в
//каком состоянии мы находимся в данный момент
//–
switch (currentReadLocation) {







