Базы данных и XML
Работа с XML-данными
Классы пространства имен System.Xml позволяют работать с XML-данными разными способами. Наиболее часто выполняются следующие задачи:
- открытие XML-документа;
- чтение фрагмента XML-данных для извлечения некоторых значений;
- сохранение XML-файла на диск.
Краткое введение в XML
Язык XML (от англ. eXtensible Markup Language – расширяемый язык разметки) предназначен для хранения структурированных данных. Данные, хранящиеся в формате XML, можно передавать между программами. Поскольку данные в XML структурированные, в некоторых случаях использование этого формата может заменить базы данных. Кроме этого, у XML есть еще много других полезных применений.
Язык XML широко распространен, и, скорее всего, вы уже слышали о нем. Этот язык удобно воспринимать как человеку, так и машине. Большая часть программного кода, с которыми работают различные вычислительные системы, обычным людям кажутся китайской грамотой, но XML-документы записываются почти как обычный текст.
Например, можно составить XML-документ для хранения на диске географических данных:
XML весьма похож на другой язык разметки HTML, но в HTML набор тегов фиксирован, и у каждого тега есть свое строго определенное назначение и правила написания. В XML можно определять собственные теги, но при этом все равно нужно соблюдать синтаксические правила языка разметки.
Далее мы обсудим значение двух терминов, без знания которых невозможно дальнейшее изучение языка XML.
Элементы
XML-документ - это запись, состоящая из отдельных элементов. Каждый элемент начинается с открывающего тега, заключенного в треугольные скобки ( <> ) – и заканчивается закрывающим тегом ( </> ).
Имя элемента задается в открывающем теге и повторяется в закрывающем теге, а между открывающим и закрывающим тегами находится его содержание. В содержание тега могут быть вложены другие теги. Теги с одним именем нередко повторяются, даже если они не вложены один в другой.
В приведенном выше XML-документе один из элементов с именем <Континент> имеет значение "Южная Америка". В него вложены два элемента с именем <Страна>, содержательно задающие названия стран этого континента.
Имя элемента в открывающем теге | Значение | Закрывающий тег |
---|---|---|
<Страна> | Бразилия | </Страна> |
<Школьник> | Ваня Курочкин | </Школьник> |
Атрибуты
В открывающем теге можно задавать дополнительные свойства элемента. Для этого используются атрибуты. Каждый атрибут задается парой "имя = "значение"". Например, если для элемента <Страна> надо указать столицу, то можно создать атрибут элемента с именем "столица". А для элемента <Школьник> задать атрибуты "возраст" и "класс". В приведенном ниже примере у элемента "Страна" со значением "Аргентина" атрибут "столица" имеет значение "Буэнос-Айрес".
Открывающий тег | Значение элемента | Закрывающий тег | ||||
---|---|---|---|---|---|---|
Имя элемента | Имя атрибута | Значение атрибута | ||||
<Страна | столица | = | "Буэнос-Айрес" | > | Аргентина | </Страна> |
Читать подобные документы не составляет труда, а поскольку они имеют четкую структуру, то и компьютер можно научить этому без особых проблем. Например, составить такой набор инструкций: "Начать просмотр документа; при нахождении символа " < " — читать имя элемента. При нахождении символа " > " — читать значение элемента..." и так далее.
Некоторые элементы могут иметь только атрибуты и не иметь значения и содержания. Тогда открывающий и закрывающий теги объединяются. Например, элемент <Страна> можно задать следующим образом:
<Страна название = "Аргентина" столица = "Буэнос-Айрес" />
Для описания элемента использовались два атрибута, но не значение элемента.
Пример программы 4.4
Следующая программа считывает данные из XML-файла и отображает их на форме.
В ней используются три класса из пространства имен System.Xml:
- XmlDocument. Объекты этого класса задают Xml-документ. При создании объекта содержимое документа может быть прочитано из файла, получено из других источников или создано в ходе работы программы.
- XmlNodeList. Объекты этого класса могут содержать некоторый список элементов XML-документа, найденный, например, в результате поиска.
- XmlNode. Объект этого класса задает один XML-элемент.
Для поиска нужных фрагментов XML-документа в программе используются так называемые выражения xPath. Они позволяют указать, какие именно элементы необходимо извлечь из XML-документа. Выражение xPath вида "/континент/страна" означает: "найти все элементы с именем "страна", вложенные в элемент с именем "континент"".
using System; using System.Windows.Forms; using System.Drawing; // Пространство имен для работы с XML-данными using System.Xml; //Пространство имен для работы с выражениями xPath using System.Xml.XPath; class XmlRetriever: Form { ComboBox comboBox1; Button button1; ListBox listBox1; RichTextBox richTextBox1; XmlDocument xmlDoc; // Метод-конструктор нашего класса public XmlRetriever() { // Задаем заголовок и размеры окна this.Text = "Работа с XML-документом"; this.Size = new Size(400, 400); // Создаем объект XmlDocument, используя xml-файл xmlDoc = new XmlDocument(); xmlDoc.Load("../../docs/Planets.xml"); // Создаем объект TextBox для вывода данных richTextBox1 = new RichTextBox(); richTextBox1.Dock = DockStyle.Top; richTextBox1.AcceptsTab = true; richTextBox1.Height = 180; richTextBox1.ReadOnly = true; richTextBox1.BackColor = Color.Silver; // Помещаем XML-данные в элемент TextBox richTextBox1.Text = xmlDoc.OuterXml; this.Controls.Add(richTextBox1); // Создаем объект ComboBox // В элементы списка этого объекта записываем //различные выражения XPath, //позволяющие искать нужные элементы XML-документа comboBox1 = new ComboBox(); comboBox1.Location = new Point(0, 200); comboBox1.Width = 300; comboBox1.Items.Add("/Планета"); comboBox1.Items.Add("/Планета/Континент"); comboBox1.Items.Add("/Планета/Континент/Страна"); comboBox1.Items.Add( "/Планета/Континент/Страна[@столица='Рио-де-Жанейро']"); comboBox1.SelectedIndex = 0; this.Controls.Add(comboBox1); // Создаем командную кнопку для поиска и отображения // соответствующих элементов Xml-документа button1 = new Button(); button1.Text = "Получить данные"; button1.Location = new Point(100, 230); button1.Width = 120; button1.Click += new EventHandler(Button1_Click); this.Controls.Add(button1); // Создаем элемент ListBox для отображения элементов listBox1 = new ListBox(); listBox1.Dock = DockStyle.Bottom; listBox1.Location = new Point(10, 10); this.Controls.Add(listBox1); } static void Main() { // Создаем и запускаем новый экземпляр класса Application.Run(new XmlRetriever()); } // Обработчик события, срабатывающий при нажатии кнопки void Button1_Click(object sender, EventArgs e) { XmlNodeList xmlNodes; XmlNode xmlElement; string elementValue; // Используем охраняемый блок try-catch, // что позволит в случае ошибок в выражениях XPath // перехватывать обработку исключений, выдавать сообщение // об ошибке и нормально продолжить работу приложения try { // Выбираем из XML-документа элементы, которые соответствуют // выражению XPath, заданному выбранным элементом ComboBox xmlNodes = xmlDoc.SelectNodes(comboBox1.Text); // Производим циклический перебор найденных элементов, // добавляя каждый элемент в ListBox listBox1.Items.Clear(); for (int i = 0; i < xmlNodes.Count; i++) { xmlElement = xmlNodes[i]; if (xmlElement.HasChildNodes) { elementValue = xmlElement.FirstChild.Value.Trim(); listBox1.Items.Add(elementValue); } } } catch (XPathException ex) { const string errorMessage = "Ошибка в задании выражения XPath!" + "\r\n" + "Соответствующие данные в документе не найдены!" + "\r\n" + "Попробуйте задать другое выражение!"; MessageBox.Show(errorMessage +"\r\n" + ex.Message); } } }Листинг 4.4.
Программа отображает исходный XML-файл в элементе управления RichTextBox. Далее из списка элементов ComboBox можно выбрать одно из выражений xPath и нажать на командную кнопку. В результате в элемент управления ListBox будут выведены элементы Xml-документа, заданные выражением XPath. Вы можете задать собственное выражение XPath в элементе ComboBox. После запуска программы поэкспериментируйте с вводом и выбором выражения xPath, после чего нажмите кнопку "Получить данные".