Как подключить xml файл c

Обновлено: 07.07.2024

8. Лекция: Отображение XML-документов с использованием связывания данных

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

При связывании данных вы соединяете XML-документ с HTML-страницей, а затем встраиваете стандартные HTML-элементы, такие как SPAN или TABLE, в отдельные XML-элементы. HTML-элементы затем автоматически отображают содержимое XML-элементов, в которые они встроены.

Связывание данных, как и другие методы, о которых вы узнаете в этой лекции, работает только с XML-документом, который симметрично структурирован, например, как базы данных, – а именно, элементы документа могут быть интерпретированы как набор записей и полей. В простейшем случае такой документ состоит из корневого элемента, содержащего множество элементов одинакового типа (записи), каждый из которых имеет одинаковый набор дочерних элементов, все из которых содержат символьные данные (поля). В качестве примера можно привести документ Inventory.xml, который представлен в Листинге 8.1. Элементы BOOK этого документа могут быть интерпретированы как записи, а элементы, вложенные в каждый элемент BOOK (TITLE, AUTHOR и т.д.), могут быть интерпретированы как поля. Далее в этой лекции вы подробнее узнаете о специфических структурах документа, которые подходят для связывания данных. Если структура документа такова, что не допускает связывание данных, можно использовать метод создания сценариев, о котором пойдет речь в лекции 9.

В этой лекции вы прежде всего получите сведения о двух основных шагах при связывании данных. Затем вы узнаете в подробностях, как привязать XML-документ к HTML-странице (первый основной шаг) и как сцеплять элементы HTML с элементами XML (второй основной шаг). Наконец, вы узнаете, как программировать Web-страницу с помощью сценариев, которые используют в качестве базового объекта программирования связанные данные (а именно, Data Source Object, или DSO). Вы можете применять эти сценарии совместно со связыванием данных – либо независимо.

В лекции 9 вы познакомитесь с совершенно иным способом для доступа управления и отображения XML-документа с HTML-страницей. Этот метод вы можете использовать для XML-документов любого типа, независимо от вида его логической структуры.

Основные шаги

Вот два основных этапа при связывании данных:

Установка связи XML-документа с HTML-страницей, на которой вы хотите отобразить данные XML. Этот шаг обычно реализуется включением HTML элемента с именем XML в HTML-страницу. Например, следующий элемент на HTML-странице связывает XML-документ Book.xml со страницей:

Сцепление HTML элементов с XML-элементами. Когда вы сцепляете HTML элементы с XML-элементом, HTML-элемент автоматически отображает содержимое XML-элемента. Например, следующий элемент SPAN на HTML-странице сцеплен с элементом AUTHOR связанного XML-документа:

В результате HTML-элемент SPAN отображает содержимое XML-элемента AUTHOR.

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

Шаг первый: установка связи XML-документа с HTML страницей

Чтобы отобразить XML-документ на HTML странице, вы должны установить его связь со страницей. Самый простой путь сделать это в Microsoft Internet Explorer – включить в страницу HTML-элемент с именем XML, так называемый фрагмент данных. Вы можете использовать одну из двух различных форм записи для фрагмента данных.

В первой форме весь текст XML-документа помещается между начальным и конечным тегами XML. Вот пример фрагмента данных на следующей HTML-странице:

Во второй форме записи HTML-элемент с именем XML остается пустым и содержит только URL XML-документа. Вот пример фрагмента данных на HTML-странице:

В предыдущем примере текст XML-документа должен содержаться в отдельном файле Book.xml:

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

Примечание. Имейте в виду, что элемент с именем XML, используемый для создания фрагмента данных, не является собственно XML-элементом. Это просто HTML-элемент, который содержит XML-элементы. Следовательно, использование синтаксиса XML для пустого элемента, <XML />, недопустимо

Вы должны присвоить атрибуту ID фрагмента данных уникальный идентификатор, который используете для доступа к XML-документу с HTML-страницы. (В предыдущем примере в качестве значения для ID выступает "dsoBook".)

При второй форме записи фрагмента данных вы присваиваете атрибуту SRC URL файла, содержащего данные XML. Вы можете использовать полный URL, как в следующем примере:

Чаще, однако, вы используете частичный URL, который задает местонахождение относительно местонахождения HTML-страницы, содержащей фрагмент данных. Например, атрибут SRC в следующем фрагменте данных указывает, что файл Book.xml находится в той же папке, что и HTML-страница:

Относительные URL более распространены, потому что XML-документ обычно содержится в той же папке, что и HTML-страница, либо в одной из вложенных папок.

Как хранятся данные XML

Когда Internet Explorer открывает HTML-страницу, его встроенный XML-процессор синтаксически анализирует XML-документ. Internet Explorer также создает программный объект, который носит название Объект исходных данных (Data Source Object DSO), который хранит данные XML и обеспечивает доступ к этим данным. DSO хранит данные XML как набор записей – т.е. множество записей и их полей. Например, если вы включите документ Inventory.xml (см. Листинг 8.1) в страницу как фрагмент данных, DSO будет хранить каждый элемент BOOK как запись, а каждый дочерний элемент внутри BOOK (TITLE, AUTHOR и т.д.) как поле.

Когда вы сцепляете HTML-элемент с XML-элементом, DSO автоматически предоставляет значение XML-элемента и управляет всеми его свойствами. DSO также позволяет вам напрямую осуществлять доступ и манипулирование имеющимся набором записей посредством ряда методов, свойств и событий. Методы представляют собой функции, которые вы можете вызывать со страницы для доступа или модификации набора записей. (Например, вы можете использовать методы для перемещения между записями.) Свойства представляют собой установленные на данный момент параметры, которые вы можете считывать и в ряде случаев изменять со страницы. (Например, вы можете считать свойство, которое сообщает вам, достигли ли вы последней записи.) События представляют собой определенные смены состояний (например, изменение значений записи), которыми вы можете управлять посредством функции сценария, который вы создаете для страницы.

На странице идентификатор, который вы присваиваете атрибуту ID во фрагменте данных, представляет DSO. (В предыдущем разделе в рассмотренном примере таким идентификатором является dsoBook.)

Проверка на наличие ошибок XML

Чтобы увидеть описание какой-либо ошибки, имеющейся в связанном XML-документе, вы можете протестировать документ с использованием сценариев проверки на корректность и валидность, представленных в разделе "Проверка валидности XML-документа" в лекции 9.

Шаг второй: сцепление HTML-элементов с XML-элементами

Вы можете осуществлять сцепление HTML-элементов с XML-элементами двумя основными способами.

Табличное сцепление , что означает сцепление HTML-элемента TABLE с данными XML, так что в таблице автоматически отображается весь набор записей, принадлежащих XML-документу.

Сцепление по отдельным записям , что означает сцепление не табличных элементов HTML (например, элементов SPAN) с XML-элементами таким образом, что за один раз отображается только одна запись.

Использование табличного сцепления данных

Самый простой способ отобразить XML-документ, который состоит из группы записей (такой как Inventory.xml, представленный в Листинге 8.1), – это сцепить HTML-элемент TABLE с данными XML таким образом, чтобы в таблице автоматически отображались сразу все записи (или одна страница записей за раз, если вы установили режим постраничного отображения). При таком подходе Internet Explorer берет на себя большую часть работы; вам не нужно писать сценарии или вызывать методы (функции). (Одно исключение состоит в том, что если вы выбрали режим пролистывания, вам потребуется включить несколько вызовов простых функций, о чем пойдет речь далее в этой лекции.)

Вы можете использовать одну таблицу HTML для отображения XML-документа, структурированного как набор записей, либо вы можете использовать вложенные HTML-таблицы для отображения XML-документа, содержащего иерархический набор записей (более сложную структуру записей).

Использование одной HTML-таблицы для отображения простого набора записей

Вы можете использовать один HTML-элемент TABLE для отображения XML-документа, в котором данные организованы в виде простого набора записей – т.е. XML-документа, составленного следующим образом:

корневой элемент содержит множество элементов типа запись (record) (в этой лекции подобные элементы иногда называются просто записями);

каждый элемент типа запись содержит одинаковый набор элементов типа поле (field) (в этой лекции подобные элементы иногда называются просто полями);

каждый элемент типа поле содержит только символьные данные. (Если дочерний элемент элемента запись содержит один или несколько своих собственных дочерних элементов, DSO интерпретирует его как вложенную запись, а не как поле. О том, как отображать вложенные поля, вы узнаете в разделе "Использование вложенных таблиц для отображения иерархической структуры записей" далее в этой лекции.)

Примером такого типа XML-документов является документ Inventory.xml, который вы использовали в предыдущих лекциях. Он представлен в Листинге 8.1. В этом документе корневой элемент (INVENTORY) содержит набор из восьми элементов-записей (элементы BOOK), и каждый из элементов-записей имеет одинаковый набор элементов-полей, которые содержат только символьные данные (TITLE, AUTHOR, BINDING, PAGES, PRICE).

Листинг 8.1. Inventory.xml

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

В качестве примера возьмем HTML-страницу из Листинга 8.2, которая содержит таблицу, сцепленную с данными документа Inventory.xml из Листинга 8.1.

Листинг 8.2. Inventory Table.htm

XML-документ из Листинга 8.1 связан с HTML-страницей из Листинга 8.2 посредством фрагмента данных на этой странице, имеющего ID dsoInventory:

Таблица определена со стандартным заголовком (элемент THEAD) и с одной строкой (элемент TR). Каждая ячейка в этой строке (т.е., каждый элемент TD) состоит из элемента SPAN, который сцеплен с одним из полей XML-документа таким образом, что этот элемент отображает содержимое поля. Например, первая ячейка содержит элемент SPAN, сцепленный с полем TITLE:

Элемент SPAN связывается с полем XML путем присвоения имени поля (в данном примере TITLE) атрибуту DATAFLD элемента.

Вот как работает связывание данных: даже если в элементе TABLE определена только одна строка, когда браузер отображает таблицу, он повторяет строковый элемент для каждой записи в XML-документе. Т.е., в первой строке, следующей за заголовком, отображены поля (TITLE, AUTHOR и т.д.), принадлежащие первой записи (элемент BOOK для книги Adventures of Huckleberry Finn). В следующей строке отображены поля для второй записи (элемент BOOK для книги Leaves of Grass) и т.д. На рисунке 8.1 показано как выглядит документ в Internet Explorer.

У вас может возникнуть вопрос, почему ячейки (элементы TD) не сцеплены непосредственно с полями XML. Ответ заключается в том, что элемент TD не является связываемым HTML-элементом. (Связываемые элементы перечислены в таблице 8.3 в разделе "Другие способы связывания данных".) Следовательно, вы должны включить внутрь каждого элемента TD связываемый элемент (обычно SPAN).

Использование постраничного отображения

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

Установите для атрибута DATAPAGESIZE сцепленного элемента TABLE значение, равное максимальному числу записей, которые вы хотите отобразить за раз. Каждая страница записей будет содержать заданное вами число записей. Например, следующий начальный тег для элемента TABLE присваивает число "5" атрибуту DATAPAGESIZE, в результате чего в таблице будет отображено пять записей за раз:

Присвойте уникальный идентификатор атрибуту ID элемента TABLE, как для следующего начального тега:

Чтобы перемещаться между записями, вызывайте методы элемента TABLE, приведенные в таблице 8.1. Для приведенных в последнем столбце примеров предполагается, что таблица имеет идентификатор InventoryTable.

В этой статье показано, как использовать XmlTextReader класс для чтения XML-данных из файла.

Оригинальная версия продукта: Visual C++
Исходный номер КБ: 815658

Аннотация

В этой статье описывается, как использовать XmlTextReader класс для чтения XML-данных из файла. Класс XmlTextReader обеспечивает прямой анализ и маркеризацию XML-данных. Класс также реализует спецификацию XML 1.0 в дополнение к пространствам имен в спецификации XML, определяемой Всемирным веб-консорциумом XmlTextReader (W3C). В этой статье описывается, как сделать быстрый токенизированный поток доступа к данным XML вместо использования объектной модели, например объектной модели документов XML (DOM).

Требования

В этой статье предполагается, что вы знакомы со следующими разделами:

  • Терминология XML
  • Создание и чтение XML-файла

В следующем списке описаны рекомендуемые пакеты оборудования, программного обеспечения, сетевой инфраструктуры и служб:

Чтение XML-данных из файла

Чтобы прочитать XML-данные из файла, выполните следующие действия:

В меню Файл выберите пункт Создать и затем пункт Проект.

Открывается диалоговое окно Новый проект.

В Project Типы нажмите Visual C++ Projects.

В Visual Studio 2005 г. Visual C++ Projects изменена на Visual C++.

В шаблонах нажмите кнопку CLR Console Application, если вы используете Visual Studio 2005.

В поле Имя введите Q815658 и нажмите кнопку ОК.

Добавьте ссылку System.xml.dll в проект. Дополнительные сведения о добавлении ссылок на управляемый проект Visual C++ см. в справках к управляемому проекту Visual C++

Укажите директиву использования в System::Xml пространстве имен следующим образом:

Это необходимо для того, чтобы позднее в коде не нужно было квалифицировать декларации XmlTextReader классов. Вы должны использовать директиву использования перед любыми другими объявлениями.

Создание экземпляра XmlTextReader объекта. Заполнять XmlTextReader объект файлом .xml.

Обычно класс используется, если вам необходимо получить доступ к необработанных XML-данным без накладных расходов XmlTextReader doM. Таким образом, XmlTextReader класс обеспечивает более быстрый способ чтения XML-данных. Класс XmlTextReader отличается, constructors указывав расположение XML-данных.

Следующий код создает экземпляр класса, а затем XmlTextReader загружает Books.xml файл. Добавьте в функцию следующий _tmain код:

В Visual C++ 2005 функция _tmain меняется на основную.

Ознакомьтесь с XML-данными.

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

После создания объекта XmlTextReader используйте метод Read для чтения XML-данных.

Метод Read продолжает последовательно перемещаться по .xml до тех пор, пока метод Read не достигнет конца файла. Когда метод Read достигает конца файла, метод Read возвращает ложный.

Для обработки XML-данных каждая запись имеет тип узла, который можно определить из NodeType свойства. Свойство и свойство возвращают следующую информацию для текущего узла или Name Value текущей записи:

  • Имя узла, которое является именем элемента и именем атрибута.
  • Значение узла, которое является текстом узла.

В NodeType этом переумехе определяется тип узла. В следующем примере кода отображается имя элементов и тип документа. В следующем примере кода игнорируются атрибуты элементов:

Типы узлов элементов могут включать список узлов атрибутов, связанных с типами узлов элементов. Метод последовательно перемещается по каждому MovetoNextAttribute атрибуту элемента. Используйте свойство, чтобы проверить, есть ли у узла HasAttributes какие-либо атрибуты. Свойство AttributeCount возвращает количество атрибутов для текущего узла.

Сохраните решение. Построение решения.

Для успешной компиляции предыдущего примера кода необходимо добавить в /clr:oldSyntax Visual C++ 2005 общий параметр компилятор поддержки во время работы с общим языком. Чтобы добавить в Visual C++ 2005 общий параметр компиляторов поддержки во время работы языков, выполните следующие действия:

Щелкните Project и нажмите кнопку <ProjectName> Свойства.

<ProjectName> является местообнамерщиком имени проекта.

Расширь свойства конфигурации и нажмите кнопку General.

Щелкните, чтобы выбрать поддержку общего языкового времени, старый синтаксис (/clr:oldSyntax) в параметре поддержки проектов поддержки общего языкового времени в правой области, щелкните Применить, а затем нажмите кнопку ОК.

Дополнительные сведения о параметре компилятора поддержки во время работы с общим языком см. в материале /clr (Общие языковые компиляциявремени работы).

Эти действия применимы к всей статье.

Просмотр выборки вывода

Устранение неполадок

Неопроверченное исключение типа System.Xml. XmlException произошел в System.xml.dll дополнительные сведения: ошибка системы.

Ссылки

Дополнительные сведения о чтении XML с помощью XmlReader см. в книге Чтение XML с помощью XmlReader.

XML (eXtensible Markup Language) — это универсальный расширяемый язык для разметки информации. Он позволяет структурировать, хранить и передавать информацию в определенном формате. Особенность данного языка заключается в том, что самоопределяемым, что позволяет самостоятельно расширять набор условных меток — тегов. Используя их, можно формировать данные в виде древовидной структуры, когда одни элементы содержат в себе другие.

Пример XML разметки

В качестве примера можно рассмотреть телефонную книгу, в которой хранятся такие данные как имя человека, номер телефона и заметка.

<?xml version="1.0" encoding="UTF-8"?> <!--XML заголовок-->
<catalog> <!--Корневой элемент-->
<phone> <!--Элемент данных-->
<name>Саша</name> <!--Первое значение данных-->
<number>890953317</number> <!--Второе значение-->
<remark>Не бери трубку!</remark> <!--Третье значение-->
</phone> <!--Закрытие элемента данных-->
<phone>
<name>Дима</name>
<number>890512309</number>
<remark>Босс</remark>
</phone>
<phone group="important"> <!--Используем атрибут для дополнительного свойства-->
<name>Рита</name>
<number>890198735</number>
<remark>Невероятная девчонка</remark>
</phone>
</catalog> <!--Завершение всех данных-->

Первым строкой в XML файле должен идти заголовок, который указывает какую версию XML использовать, а также кодировку текста. Затем должен обязательно идти единственных корневой элемент, в который включены все остальные данные. В дальнейшем все данные разбиваются на объекты, включающие другие объекты и так далее, в зависимости от структуры данных. Также у объекта могут быть указаны дополнительные свойства, они называются атрибуты.

Реализуем две основные операции, это чтение Xml данных из файла, и сохранение данных в Xml файл. Рассмотрим основной метод приложения.

Program.cs

static void Main(string[] args)
// Устанавливаем кодировку консоли.
// Нужно только если при использовании англоязычной Windows
// на консоль вместо кириллицы выводятся знаки вопроса (. . . )
Console.OutputEncoding = Encoding.Unicode;

// Читаем Xml файл.
ReadXmlFile("example.xml");

// Ждем ввода пользователя.
Console.ReadLine();

// Пишем в файл.
WriteXmlFile("result.xml", catalog);

// Сообщаем пользователю о завершении.
Console.WriteLine("ОК");
Console.ReadLine();
>

Возьмем в качестве исходного файла пример указанный выше, для простоты удалив комментарии.

Program.cs

/// <summary>
/// Прочитать Xml файл.
/// </summary>
/// <param name="filename"> Путь к Xml файлу. </param>
private static void ReadXmlFile(string filename)
// Создаем экземпляр Xml документа.
var doc = new XmlDocument();

// Загружаем данные из файла.
doc.Load(filename);

// Получаем корневой элемент документа.
var root = doc.DocumentElement;

// Используем метод для рекурсивного обхода документа.
PrintItem(root);
>

// Если у элемента есть атрибуты,
// то выводим их поочередно, каждый в квадратных скобках.
foreach(XmlAttribute attr in item.Attributes)
Console.Write($"[]");
>

if(child is XmlText text)
// Если зависимый элемент текст,
// то выводим его через тире.
Console.Write($"- ");
>
>
>

В результате получим следующий вывод на консоль

Для начала нам нужно определить классы модели данных, то есть указать свойства, которые хотим хранить в файле.

Phone.cs

namespace XML
/// <summary>
/// Телефонный контакт.
/// </summary>
public class Phone
/// <summary>
/// Имя.
/// </summary>
public string Name

/// <summary>
/// Телефонный номер.
/// </summary>
public int Number

/// <summary>
/// Заметка.
/// </summary>
public string Remark

/// <summary>
/// Важный контакт.
/// </summary>
public bool Important

/// <summary>
/// Приведение объекта к строке.
/// </summary>
/// <returns> Имя. </returns>
public override string ToString()
return Name;
>
>
>

Catalog.cs

namespace XML
/// <summary>
/// Каталог телефонных номеров.
/// </summary>
public class Catalog
/// <summary>
/// Список телефонных номеров.
/// </summary>
public List<Phone> Phones < get; set; >= new List<Phone>();
>
>

Теперь реализуем метод формирования Xml файла на основе имеющихся данных.

Program.cs

/// <summary>
/// Сохранить данные в Xml файл.
/// </summary>
/// <param name="filename"> Путь к сохраняемому файлу. </param>
/// <param name="catalog"> Сохраняемые данные. </param>
private static void WriteXmlFile(string filename, Catalog catalog)
// Создаем новый Xml документ.
var doc = new XmlDocument();

// Создаем Xml заголовок.
var xmlDeclaration = doc.CreateXmlDeclaration("1.0", "UTF-8", null);

// Добавляем заголовок перед корневым элементом.
doc.AppendChild(xmlDeclaration);

// Создаем Корневой элемент
var root = doc.CreateElement("catalog");

// Получаем все записи телефонной книги.
foreach(var phone in catalog.Phones)
// Создаем элемент записи телефонной книги.
var phoneNode = doc.CreateElement("phone");

if (phone.Important)
// Если установлен атрибут Важный в true,
// то создаем и добавляем атрибут к элементу записи телефонной книги.

// Создаем атрибут и нужным именем.
var attribute = doc.CreateAttribute("group");

// Устанавливаем содержимое атрибута.
attribute.InnerText = "important";

// Добавляем атрибут к элементу.
phoneNode.Attributes.Append(attribute);
>

// Создаем зависимые элементы.
AddChildNode("name", phone.Name, phoneNode, doc);
AddChildNode("number", phone.Number.ToString(), phoneNode, doc);
AddChildNode("remark", phone.Remark, phoneNode, doc);

// Добавляем запись телефонной книги в каталог.
root.AppendChild(phoneNode);
>

// Добавляем новый корневой элемент в документ.
doc.AppendChild(root);

// Сохраняем документ.
doc.Save(filename);
>

/// <summary>
/// Добавить зависимый элемент с текстом.
/// </summary>
/// <param name="childName"> Имя дочернего элемента. </param>
/// <param name="childText"> Текст, который будет внутри дочернего элемента. </param>
/// <param name="parentNode"> Родительский элемент. </param>
/// <param name="doc"> Xml документ. </param>
private static void AddChildNode(string childName, string childText, XmlElement parentNode, XmlDocument doc)
var child = doc.CreateElement(childName);
child.InnerText = childText;
parentNode.AppendChild(child);
>

В результате, после выполнения программы, мы получим файл Xml с идентичной структурой и данными.

Приветствую всех! Сегодня посмотрим классы и методы работы с файлами XML.

XML-eXtensible Markup Language-Текстовый формат, предназначенный для хранения структурированных данных для обмена информацией между программами, а
также для создания на его основе более специализированных языков разметки.

XML — это описанная в текстовом формате иерархическая структура, предназначенная для хранения любых структурированных данных. Визуально структура может быть представлена как дерево элементов. Элементы XML описываются тегами. Основан на принципах иерархии.

< firstElement attribute = "значения 1" attribute = "значение 2" > < ! -- Иерархия элемента второго уровня , подчиненная предыдущему -- >

XML-классы в пространстве имен System.Xml образуют полнофункциональный интегрированный набор классов, позволяющий работать с XML-документами и данными. XML-классы поддерживают синтаксический анализ и запись XML-кода, изменение XML-данных в памяти, проверку данных и преобразование XSLT.

XmlAttribute : атрибут элемента.

XmlDeclaration: описание документа.

XmlDocument : документ XML.

XmlElement : элемент XML.

XmlNode: узел, может быть как весь документ, так и отдельные элемент.

Основным классом для работы с XML является XmlNode

Attributes -колекция атрибутов узла.

ChildNodes -коллекция дочерних узлов.

Value-получить значение

Классы для работы с XML

XmlDocument основные методы и свойство:

Load()-загрузает документ из внешнего источника.

LoadXml()-создает документ из строки с XML.

Greate()-создает соответствующий объект.

DocumentElement-корневой элемент документа.

XmlElement основные методы и свойство:

XmlElement-представляет собой элемент, может иметь атрибуты, а также может иметь дочерние элементы.

GetAttribute()-возвращает значения атрибута по его имени.

Name-имя текущего элемента.

Remove-удаляет соответствующий объект.

SetAttribute()-добавляет в элемент новый атрибут с именем и значением.

XML Path Language

XPath (XML Path Language) — язык запросов к элементам XML-документа.
Разработан для организации доступа к частям документа XML в файлах трансформации XSLT и является стандартом консорциума W3C. XPath призван реализовать навигацию по DOM в XML.

Пространство имен XPath

Пространство имен, позволяющее использовать возможности языка XPath (XML Path Language).
Содержит класс XPathDocument, позволяющий создавать экземпляры XPathNavigator.
XPathNavigator – предоставляет курсор-ориентированную модель для просмотра и редактирования XML данных.

Пространство имен System.Xml.XPath содержит классы, определяющие модель курсора для переходов и изменения элементов сведений XML и предназначено для обеспечения высокой скорости работы.
XPathDocument – представляет собой быстрое, доступное только для чтения, хранимое в памяти представление XML-документа с помощью модели данных XPath. Его единственной задачей является создание навигаторов XPathNavigator. Создавать класс XPathDocument можно несколькими способами. Можно передать его конструктору
экземпляр XmlReader, имя файла XML-документа или объект, основанный на Stream. Это обеспечивает значительную гибкость, например, можно сначала применить
XmlValidatingReader для проверки правильности XML-документа и затем воспользоваться этим же объектом для создания XPathDocument.

C++: метаданные своими руками

Чтение/запись простых Xml-файлов из программы на классическом С++

Проблема

Имеется структура данных, содержащая подструктуры любой степени вложенности, а также массивы. И поля структур, и элементы массивов имеют типы-значения, т.е. среди них нет ни указателей, ни ссылок. Задача состоит в том, чтобы обеспечить универсальный алгоритм чтения/записи такой структуры в виде xml-файла. Изменение структуры данных не должно приводить к перепрограммированию алгоритма чтения. Чтение должно быть основано на неких данных, которыми предварительно снабжены (размечены) все типы, участвующие в считываемой/записываемой структуре.

Короче, при таком подходе программист не должен для каждого типа сохраняемых данных писать процедуру обхода XMLDOM-дерева. Он лишь декларирует (описывает, размечает) структуру данных специальным образом, чтобы потом использовать универсальный алгоритм чтения/записи. Ровно то, что называется декларативным подходом в программировании.

ПРИМЕЧАНИЕ

Решение

Предлагаю для начала, не вдаваясь в подробности устройства библиотеки, посмотреть на то, как она применяется, и что это даёт. Начнём с простейшего. Правило первое – чтобы записать структуру в xml-файл, её необходимо разметить, т.е. сопоставить полям структуры имена xml-тегов, и задать значения полей по умолчанию (если при чтении файла полю разрешено отсутствовать). Ниже приведён пример создания простейшего xml-файла.

Как вы видите, в тело класса добавлен вложенный тип LayoutDefault, унаследованный от шаблонного класса Layout<Clr>. В конструкторе класса LayoutDefault с помощью специального метода Simple происходит разметка структуры. Этот метод принимает в качестве входных параметров имя тега, указатель на поле и указатель на значение поля по умолчанию (может быть NULL, если нет значения по умолчанию).

Такая разметка структуры позволяет нам использовать метод Xml::Save для сохранения структуры в виде xml-файла. Xml::Save – этот тот самый универсальный метод сохранения данных, о котором говорилось при постановке задачи. Имеется аналогичный метод для чтения данных из Xml-файла – Xml::Load.

Результатом будет следующий файл:

В данном случае для сопоставления тегов и полей структуры использовался метод Simple. Если же нужно, чтобы значения компонентов цвета сохранялись не как элементы, а как атрибуты, придется разметить структуру немного по-другому и использовать метод Attribute:

Результат получается соответствующий:

Просто, не правда ли? А если структура данных будет более сложной? Если будут присутствовать вложенные структуры, массивы? OK, давайте рассмотрим ещё один пример:

Думаю, если привести результирующий файл, то объяснения будут излишни.

Итак, общее представление о возможностях библиотеки вы, надеюсь, получили. Осталось только рассказать, как работать с таким важным типом данных, как перечисления. Это тоже совсем не сложно:

После этих действий перечисление можно использовать при разметке структур, в которые оно входит в качестве поля (как Simple или как Attribute).

Соответствующий xml-файл будет таким:

Вот, собственно, и все главные возможности библиотеки. Если они вас не заинтересовали, то на этом чтение статьи можно закончить. Если же сказанное выше представляет для вас интерес, то я продолжу.

Подробности

СОВЕТ

Читать дальнейшее лучше всего, изучая на экране монитора демонстрационный проект, загруженный в среду Visual Studio.

«Деревянное» хранилище

В самом начале разработки библиотеки было принято решение не ограничиваться работой только с XML-файлами. Ведь на свете есть много иерархически устроенных хранилищ данных, и работу с ними можно организовать единообразно. Ниже приведён интерфейс, который был принят для описания хранилища данных в виде дерева, «деревянного» хранилища:

Используя XMLDOM, эти интерфейсы реализовать легко, тем более что названия операторов специально сделаны похожими на названия операторов Msxml2.DOM. Не стоит тратить здесь время на реализацию этих интерфейсов, так как она довольно проста.

Подчеркну, что эти интерфейсы можно реализовать для хранения данных как, к примеру, в Registry, так и в других «деревянных» хранилищах. Среди прилагающихся исходных текстов вы найдёте реализацию этих интерфейсов для двух хранилищ (XML-файл и Registry).

Registry

Попробуем для примера сохранить уже знакомую нам структуру Pnt в реестре. Это можно сделать следующим образом:

Вот примерно как будет выглядеть результат (см. рисунок 1):



Рисунок 1. Результат сохранения структуры данных в реестре.

К сожалению, реестр не поддерживает массивы узлов (ключей), поэтому приходится эмулировать массивы при помощи специального вида имён узлов.

ПРЕДУПРЕЖДЕНИЕ

При работе с реестром не забывайте о том, что, в отличие от XML, регистр имён элементов (ключей) и атрибутов (величин) здесь не имеет значения. Это надо учитывать при разметке данных и не допускать имён, отличающихся только регистром.

Метаклассы

Как уже упоминалось, данный вариант библиотеки накладывает определённые ограничения на структуру данных, предназначенных для чтения/записи в xml-файл. Принята следующая модель данных: данные могут быть или примитивными типами, или структурами (наборами полей разных типов), или массивами (последовательностями однотипных элементов). Поля и элементы массивов могут быть данными примитивных типов или же структурами и массивами. Короче, данные – это примитивы, структуры и массивы, состоящие из примитивов, структур и массивов, которые в свою очередь состоят из примитивов, структур и массивов и т.д.

Теперь вам будет легко понять, что такое метакласс. Метакласс – это тип класса (класс класса, тип типа), то есть метакласс – это сущность, которая показывает, к какому семейству структур данных принадлежит данная структура. Это примитив? Это структура (в узком смысле)? Или это массив?

Попробуем выразить эту мысль на языке C++. Метакласс превращается в шаблонный тип (параметр шаблона – сам класс), реализующий следующий интерфейс.

Естественно, что типы, принадлежащие разным метаклассам, сохраняются и читаются из "деревянного" хранилища по-разному. Этот факт выражается в том, что имеется три реализации интерфейса MetaClass.

Первый потомок – это примитивный метакласс:

Реализация примитивного метакласса и сама по себе примитивна. Этот класс читает текст узла дерева и разбирает его с помощью некоторого «приспособления» – шаблонного класса Primitive. О классе Primitive речь будет идти ниже.

Второй метакласс – векторный.

Как видите, векторный метакласс для своей работы нуждается в метаклассе своих элементов и в именах тегов своих элементов. Этого ему достаточно, чтобы записать/считать себя в/из xml-файла.

Третий, самый интересный метакласс - структурный.

Напомню, что структура состоит из полей разного типа, расположенных в произвольном порядке. Поэтому для своей работы структурный мета-класс требует полного описания всех типов полей их положения внутри структуры. Вся эта информация хранится в экземпляре шаблонного класса Layout.

Разметка структуры

Layout – это просто набор (массив) данных о каждом поле.

Главную роль в разметке играют шаблонные классы FieldAttribute:

Необходимо пояснить назначение методов ReadField и WriteField. Эти методы читают и пишут не всю структуру, переданную им как параметр (как это делают методы метаклассов), а только одно её поле - то, за которое отвечает данный экземпляр FieldAttribute.

Как вы, наверное, уже догадались, есть три реализации интерфейса FieldAttribute – это поле-примитив, поле-структура, и поле-массив. Приведу реализацию только одного из них – StructFieldAttribute.

Приведённый ниже листинг необходимо прочесть внимательно. Это важно для понимания принципов работы библиотеки.

Обратите внимание на поле m_offset – это указатель на поле в структуре. Он определяет положение (смещение) поля относительно начала структуры. С его помощью производится чтение/запись поля.

Аналогично устроены данные о полях примитива и полях массивах.

Разбор (парсинг) примитивов

Осталось рассказать про примитивы. На самом деле примитивы – это самые важные классы. Всё происходит именно ради них. В конечном счете все цепочки вызовов кончаются чтением или записью строк в тела элементов или в значения атрибутов "деревянного" хранилища.

Примитив (в данном контексте) – это структура данных, сохраняемая непосредственно в тексте, поэтому для её поддержки используется вот такой простейший интерфейс:

Для каждого примитивного типа нужно обеспечить специализацию этого шаблона. Например, вот как это сделано для типа char:

У других примитивов реализация такая же простая.

Метаданные своими руками

А где же метаданные создаются? – спросите вы. Где и когда создаются экземпляры тех объектов, о которых шла речь? Помните, мы размечали структуру Pnt? Мы создали класс-наследник Layout<Pnt> и в его конструкторе определяли разметку структуры с помощью методов Simple, Attribute, Array, Complex? Ниже приведён текст одного из этих методов:

Как видите, метод всего лишь создаёт атрибут одного поля и вставляет его в разметку. Но откуда же он берёт разметку самого поля? Она передаётся в качестве последнего параметра метода, а он, в свою очередь, имеет значение по умолчанию DefaultLayout(). Посмотрим на текст этого метода.

Вот где затаились сами метаданные! Они представлены как статические переменные процедуры DefaultLayout(). Применён распространённый способ: статические переменные, не инициализирующиеся до тех пор, пока не потребуются, – это намного удобнее и эффективнее открытых глобальных статических переменных. Метаклассы создаются так же, как и разметка – по требованию. Для этого есть метод DefaultMetaClass().

Важное замечание: и DefaultLayout(), и DefaultMetaClass() – это всего лишь значения по умолчанию параметров вызовов Complex и Array. Если вас не устраивает разметка по умолчанию, или же её просто нет (класс чужой), то вы можете определить свои варианты разметки и метакласса.

Вот как можно обеспечить альтернативный способ сохранения знакомого нам класса Clr:

Теперь мы можем сохранять Clr ещё одним способом:

Давайте еще раз поподробнее проследим путь (жизненный цикл) метаданных. Как только мы добавляем разметку одного поля в структуре, компилятор генерирует код процедур, генерирующих метаданные, код метаклассов, атрибутов полей и примитивов. Если при исполнении программы код сериализации не исполняется, то метаданные создаваться не будут. Но стоит один раз исполнить код сериализации, как будут проинициализированы все необходимые метаданные (проинициализируются статические переменные-разметки и переменные-метаклассы, о которых говорилось, отработают все их конструкторы, в теле которых были написаны разметку структур, заполнятся карты имён перечислений и т.д.). При последующих вызовах Xm::Load и Xm::Save эта титаническая работа производиться уже не будет – метаданные строятся один раз за время исполнения программы.

Создаётся и размечается структура, соответствующая тегу add:

Создаётся и размечается структура, соответствующая всему конфигурационному файлу в целом (точнее его разделу appSettings):

И, наконец, нужно позаботиться об удобстве и эффективности обращения к конфигурационным данным:

Единожды проделав эти простые шаги, можно повсеместно использовать этот код для чтения config-файлов:

Заключение

Кажется, идея оказалась плодотворной. Давайте подумаем, что ещё можно сделать?

Читайте также: