17323

Создание XML-документов в .NET

Лекция

Информатика, кибернетика и программирование

Лекция 9. Создание XMLдокументов в .NET План 1. Использование класса XmlWriter запись потоков данных Xml 2. Использование DOM в .Net 2.1. Чтение XMLдокумента с помощью XmlNodeList 2.2. Вставка элементов узлов в XML документ 3. Обработка атрибутов 3.1. Извлечение атрибутов с помощью XmlRead...

Украинкский

2013-06-30

123.45 KB

10 чел.

Лекция 9. Создание XML-документов в .NET

План

1. Использование класса XmlWriter - запись потоков данных Xml

2. Использование DOM в .Net

2.1. Чтение XML-документа с помощью XmlNodeList

2.2. Вставка элементов (узлов)  в XML- документ

3. Обработка атрибутов

3.1. Извлечение атрибутов с помощью XmlReader

3.2. Вставка атрибутов  в документ с помощью XmlWriter

1. Использование класса XmlWriter - запись потоков данных Xml

Таблица 1. Основные классы чтения и записи данных XML

XmlReader

Абстрактный класс, выполняющий чтение и обеспечивающий быструю доставку некешированных данных XML. Класс представляет собой однонаправленный синтаксический анализатор

XmlWriter

Абстрактный класс, выполняющий запись данных в виде потока или файла

XmlTextReader

Реализация  класса XmlReader. Обеспечивает однонаправленный потоковый доступ к данным XML

XmlTextWtiter

Реализация  класса Xml.Writer. Обеспечивает быструю однонаправленную генерацию потоков XML

Для работы с данными каждый из классов предоставляет необходимые методы.

Класс XmlWriter позволяет записывать Xml-код в поток данных, файл, в класс StringBuilder, TextWriter  и другие объекты XmlWriter.

Класс легко конфигурируется, что позволяет определить потребность во вспомогательных установках, таких как отступы, кавычки, пространства имен и другое. Такое конфигурирование выполняется с использованием объекта XmlWriterSettings.

Создадим обработчик кнопки WriteXml  примера предыдущей лекции.

При нажатии кнопки WriteXml выполняется создание элементов XML-документа и запись его в новый файл  "booknew.xml");

      private void btmWriteXml_Click(object sender, EventArgs e)

       {

          // запись в файл

           XmlWriterSettings setting = new XmlWriterSettings();

           setting.Indent = true;

           XmlWriter writer = XmlWriter.Create("booknew.xml", setting);

           writer.WriteStartDocument();

           //начало создания єлементов

           writer.WriteStartElement("Catalog");

           writer.WriteStartElement("book");

           writer.WriteElementString("title", "Основы инженерии качества программных систем");

           writer.WriteStartElement("author");

           writer.WriteElementString("name", "Коротун Т.М.");

           writer.WriteElementString("name", "Коваль Г.И.");

           writer.WriteEndElement();

           writer.WriteElementString("price", "120.00");

           writer.WriteEndElement();

           writer.WriteEndElement();

           writer.WriteEndDocument();

           //Очистка потока

           writer.Flush();

           writer.Close();

       }

В этом примере создается новый XML-файл booknew.xml, в который записываются данные о новой книге. Класс XmlWriter перезаписывает существующее содержимое файла новым содержимым.  Для вставки новых элементов используются методы класса XmlWriter.  Для создания объекта XmlWriter используется статический метод Create(). В примере строка, представляющая имя файла, передается как параметр вместе с экземпляром класса XmlWriterSettings.

Класс XmlWriterSettings имеет свойства, управляющие способом создания Xml-докуметов. Например, свойство Indent – булевское значение, которое определяет, должны ли элементы выводиться с отступом.  Свойство IndentChars содержит  строку символов, используемую для отступа.  По умолчанию это строка из двух символов. Свойство NewLine служит для определения символа новой строки.  

Основные методы класса XmlWriter

WriteStartDocument()

добавляет объявление документа. После этого можно добавлять данные.

WriteEndDocument()

определяет конец документа (вставляет тег конца)

WriteStartElement()

добавляет новый элемент

WriteElementString

вставляет строку, указывающую имя и содержимое элемента

WriteEndElement

определяет конец элемента (вставляет тег конца)

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

В результате в папке приложения будет создан такой файл:

<?xml version="1.0" encoding="utf-8"?>

<Catalog>

 <book>

   <title>Основы инженерии качества программных систем</title>

   <author>

     <name>Коротун Т.М.</name>

     <name>Коваль Г.И.</name>

   </author>

   <price>120.00</price>

 </book>

</Catalog>

Этот файл содержит XML-документ, описывающий одну книгу.  Такой метод подходит для создания новых документов. А что делать, если необходимо добавить элемент в существующий XML-документ? Например добавить новую книгу в каталог. Для этого нужно воспользоваться классами  DOM.

2. Использование DOM в .Net

Реализация объектной модели документа (DOM, Document Object Model) в .NET поддерживает спецификации W3C DOM Level 1 и Core DOM Level 2. DOM реализуется с помощью класса XmlNode. XmlNode является абстрактным классом, который представляет узел документа XML. XmlNodeList является упорядоченным списком узлов. Это активный список узлов, и любые изменения в любом узле немедленно отражаются в списке. XmlNodeList поддерживает индексный доступ или итеративный доступ. Эти два класса составляют основу реализации DOM на платформе .NET.

Основные классы, которые основываются на XmlNode

Имя класса

Описание

XmlLinkedNode

Расширяет XmlNode. Возвращает узел непосредственно перед или после текущего узла. Добавляет свойства NextSibling и PreviousSibling в XmlNode.

XmlDocument

Расширяет XmlNode. Представляет весь документ. Реализует спецификации DOM Level 1 и Level 2.

XmlAttribute

Расширяет XmlNode. Объект атрибута объекта XmlElement.

XmlCDataSection

Расширяет XmlCharacterData. Объект, который представляет раздел документа CData.

XmlCharacterData

Абстрактный класс, который предоставляет методы манипуляции с текстом для других классов. Расширяет XmlLinkedNode.

XmlComment

Расширяет XmlCharacterData. Представляет объект комментария XML.

XmlDeclaration

Расширяет XmlLinkedNode. Представляет узел объявления (<?xml version='1.0' ...>)

XmlDocumentFragment

Расширяет XmlNode. Представляет фрагмент дерева документа.

XmlDocumentType

Расширяет XmlLinkedNode. Данные, связанные с объявлением типа документа.

XmlElement

Расширяет XmlLinkedNode. Объект элемента XML.

XmlEntity

Расширяет XmlNode. Синтаксически разобранный или неразобранный узел сущности.

XmlEntityReferenceNode

Расширяет XmlLinkedNode. Представляет ссылочный узел сущности

XmlNotation

Расширяет XmlNode. Содержит нотацию, объявленную в DTD или в схеме.

XmlProcessingInstruction

Расширяет XmlLinkedNode. Содержит инструкцию обработки XML.

XmlSignificantWhitespace

Расширяет XmlCharacterData. Представляет узел с разделителем. Узлы создаются, только если флаг PreserveWhiteSpace задан как true.

XmlWhitespace

Расширяет XmlCharacterData. Представляет разделитель в содержимом элемента. Узлы создаются, только если флаг PreserveWhiteSpace задан как true.

XmlText

Расширяет XmlCharacterData. Текстовое содержимое элемента или атрибута.

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

2.1. Чтение XML-документа с помощью XmlNodeList

Создадим новое приложение WinXML-DOM WindowsApplication, которое будет читать данные книжного каталога и загружать названия книг в окно списка.

Для разнообразия данные будем выводить в Listbox. Это аналогично примеру применения XmlReader. Отличие заключается в том, что осуществляется выбор, с какими узлами мы хотим работать, вместо того чтобы использовать весь документ. Вот код для выполнения этого примера в среде XmlNode.

Добавим на форму список и две кнопки. Кроме того, добавим текстовые поля для следующей версии программы.

При нажатии кнопки Чтение в список выводим названия книг. Обработчик кнопки:

      private void btmReadXML_Click(object sender, EventArgs e)

       {

        // изменить путь доступа в соответствии со структурой путей доступа

         doc.Load("book2.xml");

         // получить только те узлы, которые нужны

         XmlNodeList nodeLst=doc.GetElementsByTagName("TITLE");

         // итерации по списку XmlNodeList

        foreach(XmlNode node in nodeLst) listBox1.Items.Add(node.InnerText);

       }

Обратите внимание, что мы добавили следующее объявление на уровне модуля:

   public partial class Form1 : Form

   {      

       public XmlDocument doc = new XmlDocument();

        public Form1()

       {

           InitializeComponent();

       }

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

private void listBox1_SelectedIndexChanged(object sender, EventArgs e)

       {

           // создать строку поиска XPath

           string srch = "INVENTORY/BOOK[TITLE='" + listBox1.SelectedItem.ToString() + "']";

           // поиск дополнительных данных

           XmlNode foundNode = doc.SelectSingleNode(srch);

           if (foundNode != null) MessageBox.Show(foundNode.InnerText);

           else MessageBox.Show("Not found");

       }

В этом примере listbox с заголовками загружается из документа book2.xml. Когда мы щелкаем на окне списка, вызывая порождение события SelectedIndexChange, мы берем текст выбранного пункта в listbox, в данном случае заголовок книги, создаем оператор XPath и передаем его в метод SelectSingleNode объекта doc. Он возвращает элемент book, частью которого является TITLE (foundNode). Выведем для наглядности InnerText узла в окне сообщения. Мы можем продолжать щелкать на элементах в listbox сколько угодно раз, так как документ загружен и остается загруженным, пока мы его не освободим.

Небольшой комментарий в отношении метода SelectSingleNode. Это реализация XPath в классе XmlDocument. Существуют методы SelectSingleNode и SelectNodes. Оба они определены в XmlNode, на котором основывается XmlDocument. SelectSingleNode возвращает XmlNode, и SelectNodes возвращает XmlNodeList.

2.2. Вставка элементов (узлов)  в XML- документ

Ранее рассматривался пример XmlTextWriter, который создает новый документ. Ограничение состояло в том, что он не вставлял узел в текущий документ. Это можно сделать с помощью класса XmlDocument.

Создадим в обработчике кнопки Запись код, Добавляющий в список и файл новую книгу (элемент BOOK).

private void btmSaveXML_Click(object sender, EventArgs e)

       {

           // изменить путь доступа, как требуется существующей структурой

           doc.Load("book2.xml");

           // создать новый элемент 'book'

           XmlElement newBook = doc.CreateElement("BOOK");

           // создать новый элемент 'title'

           XmlElement newTitle = doc.CreateElement("TITLE");

           newTitle.InnerText = "Основы инженерии качества ПС";

           newBook.AppendChild(newTitle);

           // создать новый элемент author

           XmlElement newAuthor = doc.CreateElement("AUTHOR");

           newAuthor.InnerText = "Коротун Т.";

           newBook.AppendChild(newAuthor);

           XmlElement newName = doc.CreateElement("AUTHOR");

           newAuthor.InnerText = "Коваль Г.";

           newBook.AppendChild(newAuthor);

           // создать новый элемент Binding

        

           XmlElement newBind = doc.CreateElement("BINDING");

           newBind.InnerText = "Академпериодика";

           newBook.AppendChild(newBind);

           //

           XmlElement newPages = doc.CreateElement("PAGES");

           newPages.InnerText = "650";

           newBook.AppendChild(newPages);

           //

           XmlElement newPrice = doc.CreateElement("PRICE");

           newPrice.InnerText = "150";

           newBook.AppendChild(newPrice);

           

           // добавить к текущему документу

           doc.DocumentElement.AppendChild(newBook);

           // записать doc на диск

           XmlTextWriter tr = new XmlTextWriter("booksEdit.xml", null);

           tr.Formatting = Formatting.Indented;

           doc.WriteContentTo(tr);

           tr.Close();

           // загрузить listBox1 со всеми заголовками, включая новый

           listBox1.Items.Clear();

           XmlNodeList nodeLst = doc.GetElementsByTagName("TITLE");

           foreach (XmlNode node in nodeLst)     listBox1.Items.Add(node.InnerText);

       }

При выполнении этого кода будет получена функциональность предыдущего примера, но в окне списка появилась одна дополнительная книга "Основы инженерии  качества ПС". Щелчок мыши на заголовке этой книги приведет к выводу такой же информации, как и для других книг.

В этом примере сначала создается новый элемент BOOK:

           XmlElement newBook = doc.CreateElement("BOOK");

Метод CreateElement имеет три перегружаемые версии, которые позволяют определить имя элемента, имя и пространство имен URI, и, наконец, prefix (префикс), lоcalname (локальное имя) и namespace (пространство имен).

Потом добавляются новые элементы, вложенные в элемент BOOK.

           // создать новый элемент 'title'

           XmlElement newTitle = doc.CreateElement("TITLE");

           newTitle.InnerText = "Основы инженерии качества ПС";

           newBook.AppendChild(newTitle);

Здесь снова создается новый объект на основе XmlElement (newTitle). Присваиваем свойству InnerText заголовок новой книги и добавляем потомок к элементу book. Затем это повторяется для остальных элементов book.

Наконец, мы добавляем элемент newBook к узлу doc.DocumentElement. Это тот же уровень, что и у всех других элементов book. Мы заменили существующий документ новым, в отличие от XmlWriter, где можно было только создать новый документ. Последнее, что нужно сделать, это записать новый документ XML на диск. В этом примере мы создаем новый XmlTextWriter и передаем его в метод WriteContentTo. Не забудьте вызвать метод Close на XmlTextWriter, чтобы сбросить содержимое внутренних буферов и закрыть файл.

Методы WriteContentTo и WriteTo получают XmlTextWriter в качестве параметра. WriteContentTo сохраняет текущий узел и всех потомков в XmlTextWriter, в то время как WriteTo сохраняет текущий узел. Так как doc является объектом на основе XmlDocument, он представляет весь документ и поэтому будет сохранен. Можно было бы также использовать метод Save. Он всегда будет сохранять весь документ. Save имеет четыре перегружаемые версии. Можно определить строку с именем файла и путем доступа, объект на основе класса Stream, объект на основе класса TextWriter, или объект на основе XmlWriter. Именно это было использовано при выполнении примера. Добавим новый элемент в конец списка:

           listBox1.Items.Clear();

           XmlNodeList nodeLst = doc.GetElementsByTagName("TITLE");

           foreach (XmlNode node in nodeLst) listBox1.Items.Add(node.InnerText);

В этом примере содержимое элементов формировалось просто в обработчике кнопки.

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

Обработчик кнопки Добавить:

      private void btmAdd_Click(object sender, EventArgs e)

       {

           // изменить путь доступа, как требуется существующей структурой

           doc.Load("book2.xml");

           // создать новый элемент 'book'

           XmlElement newBook = doc.CreateElement("BOOK");

           // создать новый элемент 'title'

           XmlElement newTitle = doc.CreateElement("TITLE");

           newTitle.InnerText = txtName.Text;

           newBook.AppendChild(newTitle);

           // создать новый элемент author

           XmlElement newAuthor = doc.CreateElement("AUTHOR");

           newAuthor.InnerText = txtAuthor1.Text;

           newBook.AppendChild(newAuthor);

           if (txtAuthor2.Text.Length != 0)

           {

               XmlElement newName = doc.CreateElement("AUTHOR");

               newAuthor.InnerText = txtAuthor2.Text;

               newBook.AppendChild(newAuthor);

           }

           // создать новый элемент Binding

           XmlElement newBind = doc.CreateElement("BINDING");

           newBind.InnerText = txtPub.Text;

           newBook.AppendChild(newBind);

           //

           XmlElement newPages = doc.CreateElement("PAGES");

           newPages.InnerText = txtPages.Text;

           newBook.AppendChild(newPages);

           //

           XmlElement newPrice = doc.CreateElement("price");

           newPrice.InnerText = txtPrice.Text;

           newBook.AppendChild(newPrice);

           // добавить к текущему документу

           doc.DocumentElement.AppendChild(newBook);

           // записать doc на диск

           XmlTextWriter tr = new XmlTextWriter("booksEdit.xml", null);

           tr.Formatting = Formatting.Indented;

           doc.WriteContentTo(tr);

           tr.Close();

           // загрузить listBox1 со всеми заголовками, включая новый

           listBox1.Items.Clear();

           XmlNodeList nodeLst = doc.GetElementsByTagName("TITLE");

           foreach (XmlNode node in nodeLst) listBox1.Items.Add(node.InnerText);

      }

Если нужно создать документ с самого начала, можно использовать класс XmlTextWriter. Можно также использовать XmlDocument. Какой из них выбрать? Если данные, которые желательно поместить в XML, доступны и готовы для записи, то самым подходящий будет класс XmlTextWriter. Однако, если необходимо создавать документ XML постепенно, вставляя узлы в различные места, то наиболее приемлемым будет применение XmlDocument.

3. Обработка атрибутов

Обычно атрибуты не рассматриваются как часть структуры документа.  Но, при необходимости, можно определить их наличие и извлечь значения. Для извлечения и записи атрибутов можно (как для элементов) использовать классы XmlReader, XmlWriter, а также XmlDocument.

3.1. Извлечение атрибутов с помощью XmlReader

В таблице перечислены некоторые свойства и методы для обработки атрибутов.

HasAttributes

свойство. Возвращает значение true, если элемент имеет атрибуты и false – если нет

AttributeCount

свойство. Сообщает сколько атрибутов  имеет элемент

GetAttribute()

метод. Извлекает атрибут по имени или по индексу

MoveToFirstAttribute()

метод. Позволяет перейти к первому атрибуту

MoveToNextAttribute()

метод. Позволяет перейти к следующему атрибуту

Для демонстрации этих возможностей добавим в XML-файл booknew.xml в элемент book атрибуты:

<?xml version="1.0" encoding="utf-8"?>

<Catalog>

 <book genre="Программная инженерия"  yearpublic="2006" >

   <title>Основы инженерии качества программных систем</title>

   <author>

     <name>Коротун Т.М.</name>

     <name>Коваль Г.И.</name>

   </author>

   <price>120.00</price>

 </book>

</Catalog>

Откроем предыдущий проект Windows-XML.

Добавим на форму еще одну кнопку для извлечения атрибутов из элемента book. В обработчик кнопки вставим код:

       private void btnAttr_Click(object sender, EventArgs e)

       {

           //извлечение атрибутов из элемента

           richTextBox1.Clear();

           XmlReader rdr = XmlReader.Create("booknew.xml");

               //чтение узлов

           while (rdr.Read())

           {

               //проверить, не является ли он узлом

               if (rdr.NodeType == XmlNodeType.Element)

               {

               //Если это элемент, проверит его атрибуты

                   for (int i = 0; i < rdr.AttributeCount; i++)

                   {

                     richTextBox1.AppendText(rdr.GetAttribute(i) + "\r\n");

                   }

               }

     

           }

           rdr.Close();

       }

3.2. Вставка атрибутов  в документ с помощью XmlWriter

Добавим на форму кнопку WriteAttributes. Обработчик кнопки создает новый файл booknew.xml, в котором размещается документ Catalog, состоящий из одного вложенного элемента  book. В элементе book есть два атрибута "genre" и "yearpublic". Метод WriteAttributeString() добавляет атрибут к элементу.

    private void btmWriteAtt_Click(object sender, EventArgs e)

       {

           // запись в файл с атрибутами

           XmlWriterSettings setting = new XmlWriterSettings();

           setting.Indent = true;

           string fname = "booknew.xml";

           XmlTextWriter writer = new XmlTextWriter(fname, null);

           writer.Formatting = Formatting.Indented;

           writer.WriteStartDocument();

           //начало создания єлементов

           writer.WriteStartElement("Catalog");

           writer.WriteStartElement("book");

           writer.WriteAttributeString("genre", "Программная инженерия");

           writer.WriteAttributeString("yearpublic", "2006");

           writer.WriteElementString("title", "Основы инженерии качества программных систем");

           writer.WriteStartElement("author");

           writer.WriteElementString("name", "Коротун Т.М.");

           writer.WriteElementString("name", "Коваль Г.И.");

           writer.WriteEndElement();

           writer.WriteElementString("price", "120.00");

           writer.WriteEndElement();

           writer.WriteEndElement();

           writer.WriteEndDocument();

           //Очистка потока

           writer.Flush();

           writer.Close();

       }

В результате  будет создан файл booknew.xml, содержащий описание книги.

Другой способ добавления и извлечения атрибутов – применение модели DOM (класс XmlDocument).

Выводы

Классы C# обеспечивают разные способы обработки Xml-документов. Кроме рассмотренных в лекции, в .NetFramework есть классы для создания схем документов, проверки документов  на соответствие схеме, поиск информации по содержимому(XPath и XslTransform), обработку запросов, взаимодействие с базой данных.


 

А также другие работы, которые могут Вас заинтересовать

68916. Завантаження файлів 48 KB
  Завантаження файлів на сервер по протоколу HTTP здійснюється набагато чаші, чим ви можете подумати: Web-інтерфейси поштових сервісів дозволяють додати до листа вкладення, а для цього потрібно спершу завантажити файл на сервер, а тільки після цього додавати до листа.
68917. Масиви та списки. Операції над масивами 118 KB
  Масив — це впорядкований набір даних. Кожен елемент масиву має індекс або ключ. Індекс (ключ) служить для однозначної ідентифікації елементу усередині масиву. У одному масиві не може бути двох елементів з однаковими індексами.
68918. Користувацькі функції 45 KB
  У будь-якій мові програмування існують підпрограми. У мові С вони називаються функціями, в асемблері — підпрограмами і викликаються інструкцією CALL, а в мові Pascal існує навіть два види підпрограм: процедури і функції.
68919. Передача параметрів функції 40 KB
  При виклику функції func потрібно обов’язково вказати всі три параметри оскільки вони є обов’язковими. У РНР функції можуть володіти необов’язковими параметрами або параметрами за умовчанням про них ми поговоримо трохи пізніше. Функція не може змінити параметрзначення тобто він доступний...
68920. Операції над рядками. Робота з датою та часом 97 KB
  Чим же хороші самі рядки в РНР На відміну від С переваги PHPрядків полягають в наступному: Рядок може містити будьякі символи. Нагадаю що рядок не може містити символи з кодом 0 оскільки перший такий символ трактується як кінець рядка.
68921. Робота з файлами та каталогами 71.5 KB
  Як і в будь-якій мові програмування, робота з файлом здійснюється в три етапи: Відкриття файлу — при цьому повертається ціле число — ідентифікатор (дескриптор) файлу. Подальше звернення до файлу здійснюється через дескриптор, а не по імені. Обробка файлу (читання або запис). Закриття файлу.
68922. СУБД MySQL. Поля та їх типи 77.5 KB
  Програмне забезпечення яке управляє базою даних створює нові бази даних таблиці а також дозволяє використовувати вже створені об’єкти називається системою управління базою даних СУБД. Проте для написання нескладних сценаріїв роботи з базою даних приведеного матеріалу буде досить.
68923. Створення таблиць. Робота з таблицями 58.5 KB
  Примітка. Детально про ключі ми поговоримо пізніше, а поки використовуватимемо таблиці без ключів. Як модифікатори можна використовувати наступні значення: NOT NULL — поле не може містити невизначеного значення (NULL), тобто поле повинне явно ініціалізувати; PRIMARY KEY — поле буде первинним ключем...
68924. Функції РНР для роботи з MYSQL 100 KB
  Всі параметри функції є необов’язковими, оскільки значення за умовчанням можна прописати в конфігураційному файлі php.ini. Якщо ви хочете вказати інші ім’я MySQL-вузла, ім’я користувача і пароль, ви завжди можете це зробити. Параметр $hostname може бути вказаний у вигляді вузол: порт.