Опубликован: 21.01.2010 | Доступ: свободный | Студентов: 1071 / 125 | Оценка: 3.88 / 3.81 | Длительность: 11:48:00
Специальности: Программист
Самостоятельная работа 3:

Применение XML при разработке мобильного приложения

< Лекция 7 || Самостоятельная работа 3: 123 || Лекция 8 >

10.1. Иерархическая структура XML-данных

Очень важно хорошо понимать иерархическую структуру XML. Представляйте себе XML-документ в виде дерева объектов, у каждого из которых могут иметься дополнительные дочерние объекты. Для демонстрации этого изменим приведенный выше пример таким образом, чтобы внести в него дополнительную иерархию:

<UserInfo>
    <UserID> 12 </UserID> <Name>
    <FirstName>   Иво </FirstName> <LastName>   Салмре </LastName> </Name> <Address>
<Street>10 НекаяУлица</5сгеег.> <City>Cn3^</City> <State>WA</State> </Address> </UserInfo>

Здесь мы сделали узлы Name и Address подузлами Userlnfо.

Что касается практического использования, то в большинстве случаем XML-данные, участвующие в обмене, попадают в промежуток между двумя крайними категориями: строго структурированными данными и данными свободной формы. Какой уровень строгости следует применять к форматам данных, решают совместно как отправитель, так и получатель данных. Вычислительный узел, генерирующий XML-документы, может придерживаться строго определенной схемы или же просто может выбирать ту форму XML-кодирования, которая является для него наиболее удобной. Аналогичным образом, вычислительный узел, получающий XML-документы, может либо выполнять проверку их содержимого на предмет соответствия предполагаемой схеме, либо предполагать, что данные форматированы корректно, и сразу же пытаться осуществить синтаксический анализ результатов. Поскольку такие операции, как верификация схемы, могут быть трудоемкими в вычислительном отношении, то в тех случаях, когда такая проверка нужна, лучше, чтобы она осуществлялась на сервере до передачи данных устройству.

При работе с XML-данными вы можете использовать один из трех основных подходов:

  1. Создать собственный "оптимизированный" анализатор с нуля. При наличии ранее разработанных и протестированных методик это почти никогда не стоит делать. Причина, по которой применять такой подход категорически не рекомендуется, заключается в том, что получаемые при этом преимущества лишь в редких случаях окупают усилия, затрачиваемые на разработку и последующее сопровождение соответствующих программ.
  2. Использовать высокоуровневые универсальные методы синтаксического анализа с произвольным, доступом, основанные на модели XML DOM. DOM (Document Object Model- объектная модель документов) обеспечивает возможность работы с XML-данными, хранящимися в памяти в виде иерархического дерева объектов. В результате использования высокоуровневого API-интерфейса для работы с XML вы получаете в высшей степени надежный код, удобный в сопровождении. Такой подход является оптимальным для небольших XML-документов, а также документов, при работе с которыми требуется постоянный произвольный доступ ко всем частям дерева XML-документа, или документов, которые должны быть заново целиком сохранены в файле на диске.
  3. Использовать низкоуровневый API-интерфейс XML, обеспечивающий выполнение лишь одштаправленпых операций чтения-записи данных. Применение низкоуровневых API-интерфейсов позволяет максимально повысить производительность, но возлагает дополнительную нагрузку на программистов. Эти API-интерфейсы поддерживают выполнение операций чтения-записи данных только в прямом направлении и позволяют считывать или записывать данные XML-дерева в виде потока XML-элементов без сохранения всего документа в памяти. В случае мобильных устройств, для которых память всегда является дефицитным ресурсом, и особенно при работе с большими объемами данных или данными, предназначенными только для чтения, только такой подход и обеспечивает достижение приемлемой производительности. Он представляет собой хорошую основу, являющуюся промежуточной между использованием высокоуровневых АР1-интер(рейсов и развертыванием собственной методики. Такой путь является разумным, если привлечение высокоуровневых API-интерфейсов для удовлетворения ваших нужд требует интенсивных дополнительных вычислений и приводит к чрезмерному расходу памяти.

Более подробно рассмотрим второй и третий варианты работы с XML - данными

XML DOM

DOM (от англ. Document Object Model - "объектная модель документа") - это независящий от платформы и языка программный интерфейс, позволяющий программам и скриптам получить доступ к содержимому документов, а также изменять содержимое, структуру и оформление документов.

Модель DOM не накладывает ограничений на структуру документа. Любой документ известной структуры с помощью DOM может быть представлен в виде дерева узлов, каждый узел которого представляет собой элемент, атрибут, текстовый, графический или любой другой объект. Узлы связаны между собой отношениями родительский-дочерний.

Изначально различные браузеры имели собственные модели документов (DOM), не совместимые с остальными. Для того, чтобы обеспечить взаимную и обратную совместимость, специалисты международного консорциума W3C классифицировали эту модель по уровням, для каждого из которых была создана своя спецификация. Все эти спецификации объединены в общую группу, носящую название W3C DOM.

Объектная модель XML-документа, или DOM (Document Object Model) состоит из группы программных объектов, представляющих различные компоненты XML-документа. Свойства и методы этих объектов позволяют использовать сценарии для отображения XML-документа с HTML-страницы. DOM хранит данные в древообразной структуре, отражающей иерархическую структуру XML-документа, и предоставляет доступ к любым компонентам XML-документа, включая элементы, атрибуты, инструкции по обработке, комментарии и объявления нотаций и примитивов.

Чтобы получить доступ к XML-документу с использованием DOM, вы должны связать XML-документ с HTML-страницей. На HTML-странице это можно сделать через так называемый фрагмент данных:

<XML ID="dsoDoc" SRC="Sample.xml"></XML>

Идентификатор ID, который вы назначаете фрагменту данных, указывает на DSO (Data Source Object) документа. Свойство объекта DSO "XMLDocument" содержит корневой объект DOM, называемый также "узел документа". Вы можете использовать это свойство для доступа к DOM в сценариях:

xmlDOM_Document = dsoDoc.XMLDocument;

Полный перечень свойств, методов и событий объекта DSO документа вы можете получить в MSDN, воспользовавшись, например, поиском по словосочетанию "xml Object". Если вы хотите иметь доступ к нескольким XML-документам с HTML-страницы, вы можете поместить фрагмент данных для каждого из них. Кроме того, вы можете включить несколько фрагментов данных для одного XML-документа. Последний приём может оказаться полезным для поддержки нескольких различных версий данных XML, если ваша страница модифицирует эти данные.

XML DOM работает с представлением данных в виде дерева объектов в памяти. Каждый XML-элемент представляется хранящимся в памяти объектом. Можно считать, что подход XML DOM в значительной степени основан на концепции состояния в том смысле, что все данные, необходимые для воссоздания XML-документа после его считывания, загружаются как состояние. XML-деревья могут создаваться в памяти, а затем сериализовываться в файлы или через сетевые потоки. Аналогичным образом, любое XML-содержимое или XML-документ, полученный с использованием любого потока данных, могут быть использованы для заполнения дерева XML DOM в памяти.

Создание дерева объектов в памяти является удобным способом работы с данными среднего объема, которые требуется всего лишь последовательно обновлять. XML-файл размером 20 Кбайт можно довольно быстро загрузить в память и после работы с ним в памяти как с деревом объектов вновь сохранить в файловой системе. Коль скоро объемы интересующих нас данных невелики, модель XML DOM предоставляет отличные возможности для создания XML-документов, обработки их в памяти и вывода XML-данных в файл или сетевой поток.

Применимость DOM-подхода ограничивается как объемом памяти, доступной для размещения сгенерированного анализатором дерева объектов, так и наличием резер вов вычислительной мощности, необходимых для разбора всего дерева XML-данных. Недостатком подхода, основанного на XML DOM, является его монолитность; прежде чем вы сможете получить доступ к XML-данным, вы должны выполнить синтаксический анализ документа и разместить в памяти все содержимое файла или потока. Если вам необходимо работать лишь с небольшим объемом данных, содержащихся в файле большого размера, то доступ к этим данным будет сопряжен с большими накладными расходами.

using System;
//	
//Демонстрирует сохранение и загрузку файлов с
//использованием объектной модели документов ХМЪ
//	
public class SaveAndLoadXML_UseDOM {
//XML-дескрипторы, которые мы будем использовать в нашем документе
const string XML_R00T_TAG = "AllMyData";
const string XML_USERINFO_TAG = "Userlnfo";
const string XML_USERID_TAG = "UserlD";
const string XML_NAMEINF0_TAG = "Name";
const string XML_FIRSTNAME_TAG = "FirstName";
const string XML_LASTNAME_TAG = "LastName";
//	
//Загружает пользовательское состояние //
// [in] fileName:     Имя файла, используемого для сохранения данных
// [out] userld:       Загруженный идентификатор пользователя
// [out] firstName: Загруженное имя пользователя
// [out] lastName:   Загруженная фамилия пользователя
//	
public static void XML_LoadUserInfo(string fileName,
out int userld, out string firstName, out string lastName)
{
//Начинаем с нулевых значений userld = 0; firstName = ""; lastName = ,,n;
//Предполагаем, что данные еще не загружены bool gotUserlnfoData = 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_R00T_TAG) {
throw new Exception("Тип корневого узла не совпадает с ожидаемым!");
}
//	
//Простой конечный автомат для итеративного обхода всех узлов
//	
foreach(System.Xml.XmlElement childOf_RootNode in rootElement.ChildNodes)
{
//Если это узел Userlnfo, то мы хотим просмотреть его содержимое
if(childOf_RootNode.Name = XML_USERINFO_TAG)
I
gotUserlnfoData   = true; //Пользовательские данные найдены
//	
//Загрузить каждый из подэлементов
//	
foreach(System.Xml.XmlElement child_UserDataNode in childOf_RootNode.ChildNodes)
{
//Идентификатор пользователя (UserlD)
if(child_UserDataNode.Name = XML_USERID_TAG)
{
userld = System.Convert.ToInt32( child_UserDataNode.InnerText);
}
//ФИО пользователя (UserName) else if(child UserDataNode.Name == XML NAMEINFO TAG)
foreach(System.Xml.XmlElement child_Name in childJJserDataNode.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 }
//Конец цикла разбора Userlnfo ) Конец оператора if, осуществляющего проверку Userlnfo }
//Конец цикла разбора корневого узла
if (gotUserlnfoData == false) 
{
throw new Exception("Данные пользователя в XML-документе не найдены!");
}

//	
//Сохраняет пользовательское состояние //
// [in] fileName:   Имя файла, используемого для сохранения данных
// [in] userld:       Идентификатор пользователя, который мы хотим сохранить
// [in] firstName: Имя пользователя, которое мы хотим сохранить
// [in] lastName:   Фамилия пользователя, которую мы хотим сохранить
//	
public static void XML_SaveUserInfo(string fileName, int userld, string firstName, string lastName)
{
System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
//	
//Добавить элемент документа высшего уровня
//	
System.Xml.XmlElement rootNodeForDocument; rootNodeForDocument = xmlDocument.CreateElement(
XML_R00T_TAG); xmlDocumen t.Appen dCh i1d(гооtNode For Document);
//	
//Добавить данные в элемент Userlnfo
//	
System.Xml.XmlElement topNodeForUserData; topNodeForUserData = xmlDocument.CreateElement(
XML_USERINFO_TAG); rootNodeForDocument.AppendChild(topNodeForUserData);
//	
//Добавить значение UserlD в наш документ
//	

//Создать подузел для информации о пространстве имен System.Xml.XmlElement subNodeForUserlD; subNodeForUserlD =
xmlDocument.CreateElement(XML_USERID_TAG); subNodeForUserlD.InnerText =
System.Convert.ToString(userld);
//Присоединить подузел UserlD к узлу высшего уровня topNodeForUserData.AppendChild(subNodeForUserlD);
//	
//Добавить все значения Namelnfo в наш документ
//	

//Создать подузел для информации о пространстве имен System.Xml.XmlElement subNodeForNamelnfо; 
subNodeForNamelnfo = xmlDocument.CreateElement( XML_NAMEINFO_TAG);
//Имя (FirstName)
System.Xml.XmlElement subNodeFirstName; subNodeFirstName = xmlDocument.CreateElement(
XML_FIRS TNAME_TAG); subNodeFirstName.InnerText = firstName;
//Фамилия (LastName)
System.Xml.XmlElement subNodeLastName; subNodeLastName = xmlDocument.CreateElement(
XML_LASTNAME_TAG); subNodeLastName.InnerText = lastName;
//Присоединить подузлы имени и фамилии к родительскому //узлу Namelnfo
subNodeForNamelnfo.AppendChild(subNodeFirstName); subNodeForNamelnfo.AppendChild(subNodeLastName);
//Присоединить подузел Namelnfo (вместе с его дочерними узлами) //к узлу высшего уровня
topNodeForUserData.AppendChild(subNodeForNamelnfo);
//	
//Сохранить документ
//	
try
{
xmlDocument.Save(fileName);
)
catch (System.Exception ex) {
System.Windows.Forms.MessageBox.Show(
"Ошибка при сохранении XML-документа - " + ex.Message);
}
} //Конец функции } //Конец класса
private void buttonl_Click(object sender, System.EventArgs e) 
{
const string FILENAME = "TestFileName.XML"; 
//Сохранить, используя XML DOM
SaveAndLoadXML_UseDOM.XML_SaveUserInfо(FILENAME, 14, "Ivo","Salmre");
//Сохранить, используя объект однонаправленной записи XMLWriter
//SaveAndLoadXML_UseReaderWriter.XML_SaveUserInfо(FILENAME,
//	18, "Ivo", "Salmre");
int userlD; string firstName; string lastName;
//Загрузить, используя XML DOM
SaveAndLoadXML_UseDOM.XML_LoadUserInfo(FILENAME, out userlD,
out firstName, out lastName);
//Загрузить, используя объект однонаправленного чтения XMLReader
//SaveAndLoadXML_UseReaderWriter.XML_LoadUserInfо(FILENAME,
//	out userlD, out firstName, out lastName);
System.Windows.Forms.MessageBox.Show("Готово! " +userlD.ToString() + ", 
" + lastName + ", " + firstName);
< Лекция 7 || Самостоятельная работа 3: 123 || Лекция 8 >