Книга: Программирование мобильных устройств на платформе .NET Compact Framework
Листинг 10.3. Использование однонаправленного чтения-записи XML-данных для загрузки XML-документа из файла и его сохранения
Листинг 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);
//Записать содержимое документа!
//<Root>
xmlTextWriter.WriteStartElement(XML_ROOT_TAG);
//<Root>
xmlTextWriter.WriteStartElement(XML_USERINFO_TAG);
//<Root><UserID>
//<Root><UserInfo>
xmlTextWriter.WriteStartElement(XML_NAMEINFO_TAG);
//<Root><UserInfo><Name>
xmlTextWriter.WriteStartElement(XML_FIRSTNAME_TAG);
//<Root><UserInfo><Name><FirstName>
xmlTextWriter.WriteString(firstName); //Запись значения
xmlTextWriter.WriteEndElement(); //Закрыть дескриптор имени
//<Root><UserInfo><Name>
xmlTextWriter.WriteStartElement(XML_LASTNAME_TAG);
//<Root><UserInfo><Name><LastName>
xmlTextWriter.WriteString(lastName); //Запись значения
xmlTextWriter.WriteEndElement(); //Закрыть дескриптор фамилии
//<Root><UserInfo><Name>
xmlTextWriter.WriteEndElement(); //Закрыть дескриптор ФИО
//<Root><UserInfo>
//<Root><UserInfo>
xmlTextWriter.WriteStartElement(XML_USERID_TAG);
//<Root><UserInfo><UserID>
//Запись значения
xmlTextWriter.WriteString(userId.ToString());
xmlTextWriter.WriteEndElement();
//Закрыть дескриптор UserID
//<Root><Userlnfo>
xmlTextWriter.WriteEndElement(); //Закрыть дескриптор UserInfo
//<Root>
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) {
//Если мы находимся в узле AllMyData, то переход возможен
//в узлы, которые указаны ниже
case (ReadLocation.inAllMyData): {
if (nodeName == XMI_USERINFO_TAG) {
currentReadLocation = ReadLocation.inUserInfo;
}
break;
}
//Если мы находимся в узле UserInfo, то переход возможен
//в узлы, которые указаны ниже
case (ReadLocation.inUserInfo): {
if (nodeName == XML_USERID_TAG) {
currentReadLocation = ReadLocation.inUserID;
} else if (nodeName == XML_NAMEINFO_TAG) {
currentReadLocation = ReadLocation.inName;
}
break;
}
//Если мы находимся в узле Name, то переход возможен
//в узлы, которые указаны ниже
case (ReadLocation.inName): {
if (nodeName == XML_FIRSTNAME_TAG) {
currentReadLocation = ReadLocation.inFirstName;
} else if (nodeName == XML_LASTNAME_TAG) {
currentReadLocation = ReadLocation.inLastName;
}
break;
}
}
} //Конец функции
} //Конец класса
- Чем XMLReader и XMLWriter отличаются от SAX?
- Соображения, побуждающие к использованию однонаправленной обработки XML-данных
- Соображения, побуждающие избегать использования однонаправленной обработки XML-данных
- Листинг 10.3. Использование однонаправленного чтения-записи XML-данных для загрузки XML-документа из файла и его сохранения
- Примеры к главе 10 (производительность и XML)
- Резервное копирование базы данных InterBase
- Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ
- Резервное копирование многофайловых баз данных
- Листинг 10.1. (simpleid.c) Отображение идентификаторов пользователя и группы
- Восстановление с использованием инструмента gbak
- Восстановление из резервных копий многофайловых баз данных
- Владелец базы данных
- ЧАСТЬ IV. База данных и ее объекты.
- Ничего, кроме правды: поведение потребителей
- Перевод базы данных InterBase 6.x на 3-й диалект
- Типы данных для работы с датой и временем