Модификация приложения Windows Forms : XML



 

Немного общих слов об XML-формате в целом.

Язык XML (расширяемый язык разметки) предназначен для хранения структурированных данных. Данные, хранящиеся в формате XML, можно передавать между программами. Поскольку данные в XML структурированные, в некоторых случаях использование этого формата может заменить базы данных. Кроме этого, у XML есть еще много других полезных применений.

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

 

Типичный документ выглядит так:

 

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

<recipe name="хлеб" preptime="5" cooktime="180">

<title>Простой хлеб</title>

<ingredient amount="3" unit="стакан">Мука</ingredient>

<ingredient amount="0.25" unit="грамм">Дрожжи</ingredient>

<ingredient amount="1.5" unit="стакан">Тёплая вода</ingredient>

<ingredient amount="1" unit="чайная ложка">Соль</ingredient>

<instructions>

<step>Смешать все ингредиенты и тщательно замесить.</step>

<step>Закрыть тканью и оставить на один час в тёплом помещении.</step>

<!-- <step>Почитать вчерашнюю газету.</step> - это сомнительный шаг... -->

<step>Замесить ещё раз, положить на противень и поставить в духовку.</step>

</instructions>

</recipe>

 

Главным является объявление XML:

 

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

 

Объявление отвечает за кодировку документа (кодировка символов), наличие внешних зависимостей и версия документа. В версии 1.0 объявление можно не указывать. В версии 1.1 оно обязательно.

 

Важнейшее обязательное синтаксическое требование заключается в том, что документ имеет только один корневой элемент (англ. root element) (также иногда называемый элемент документа (англ. document element)). Это означает, что текст или другие данные всего документа должны быть расположены между единственным начальным корневым тегом и соответствующим ему конечным тегом.

 

Следующий простейший пример — правильно построенный документ XML:

 

<book>Это книга: "Книжечка"</book>

 

Комментарии доступны и здесь. Тэги внутри комментариев не обрабатываются:

 

<!-- Это комментарий -->

 

Остальная часть этого XML-документа состоит из вложенных элементов, некоторые из которых имеют атрибуты и содержимое. Элемент обычно состоит из открывающего и закрывающего тегов, обрамляющих текст и другие элементы. Открывающий тег состоит из имени элемента в угловых скобках, например, <step>, а закрывающий тег состоит из того же имени в угловых скобках, но перед именем ещё добавляется косая черта, например, </step>. Имена элементов, как и имена атрибутов, не могут содержать пробелы (иначе эти пробелы заменяются специальной последовательностью символов, что будет показано ниже), но могут быть на любом языке, поддерживаемом кодировкой XML-документа. Имя может начинаться с буквы, подчёркивания, двоеточия. Остальными символами имени могут быть те же символы, а также цифры, дефис, точка.

 

Содержимым элемента (англ. content) называется всё, что расположено между открывающим и закрывающим тегами, включая текст и другие (вложенные) элементы. Ниже приведён пример XML-элемента, который содержит открывающий тег, закрывающий тег и содержимое элемента:

 

<step>Замесить ещё раз, положить на противень и поставить в духовку.</step>

 

Кроме содержания у элемента могут быть атрибуты — пары имя-значение, добавляемые в открывающий тег после названия элемента. Значения атрибутов всегда заключаются в кавычки (одинарные или двойные), одно и то же имя атрибута не может встречаться дважды в одном элементе. Не рекомендуется использовать разные типы кавычек для значений атрибутов одного тега.

 

<ingredient amount="3" unit="стакан">Мука</ingredient>

 

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

 

Для начала добавим функциональности к уже имеющемся кода нашего приложения. Для этого в начале файла LWP 10 Main . cs добавим следующее:

 

using System.Xml; // XML

 

Найдём:

 

       OleDbDataAdapter DataAdapter = new OleDbDataAdapter(); // DataAdapter - посредник между базой данных и DataSet

       DataAdapter.SelectCommand = new OleDbCommand(SQL_OLE, ConnectionOLE2);

       DataAdapter.Fill(DataSetOLE); // Данные из адаптера поступают в DataSet

 

Добавим после:

 

       DataSetOLE.DataSetName = "Главная таблица"; // Устанавливаем название корневого элемента XML-файла

       DataSetOLE.WriteXml("D:\\LWP10-DB-XML.xml"); // Запишем данные таблицы в XML-файл

 

Скомпилируем приложение (Debug) и запустим. В третьем блоке элементов выберем базу данных и нажмём на Прочитать все записи. На диске D появится новый XML-файл: LWP 10- DB - XML . xml с содержанием:

 

Рис. 5. 1. Содержание файла LWP 10- DB - XML . xml

 

Как видно, пробелы в именах тэгов были заменены на символы «_x0020_». В остальном, документ точно повторяет структуру базы данных, из которой были выдраны данные.

 

Теперь создаём последнюю группу элементов. Она простая:

 

Рис. 5. 2. Расстановка элементов первой группы (XML)

 

Здесь у нас четыре кнопки, TextBox и большой ListBox. Также справа внизу элемент SaveFileDialog. Свойства элементов таковы:

 

Button:

(Name): B_XML_Search
Text: Выбрать место сохранения
Size: 200; 23

Button:

(Name): B_XML_Create
Text: Создать простой документ
Size: 200; 23

Button:

(Name): B_XML_Read
Text: Прочитать простой документ
Size: 200; 23

Button:

(Name): B_XML_DB
Text: База данных обоев
Size: 200; 23

TextBox:

(Name): TB_XML_Path
ReadOnly: True

ListBox:

(Name): LB_XML

GroupBox:

(Name): GB_XML
Text: XML

SaveFileDialog:

(Name): SFD_XML
FileName: XML-Test
InitialDirectory: D:\
Filter XML-файл|*.xml

 

Самая нижняя кнопка (База данных обоев) является кнопкой, открывающей новую форму, о чём пойдём немного ниже.

 

Событие Click кнопки Выбрать место сохранения:

 

   private void B_XML_Search_Click(object sender, EventArgs e)

   {

       SFD_XML.ShowDialog();

       TB_XML_Path.Text = SFD_XML.FileName;

   }

 

Событие Click кнопки Создать простой документ:

 

   private void B_XML_Create_Click(object sender, EventArgs e)

   {

       XmlWriterSettings SettingsXML = new XmlWriterSettings();

       SettingsXML.Indent = true; // Включаем отступ для элементов XML-документа

       SettingsXML.IndentChars = " "; // Задаём отступ (пробелами)

       SettingsXML.NewLineChars = "\n"; // Задаём переход на новую строку

       // Нужно ли опустить строку декларации формата XML документа

       // Речь идёт о строке вида "<?xml version="1.0" encoding="utf-8"?>"

       SettingsXML.OmitXmlDeclaration = false;

 

       using (XmlWriter OutputXML = XmlWriter.Create(SFD_XML.FileName, SettingsXML))

       {

           // Создали открывающийся тег

           OutputXML.WriteStartElement("XML-Test");

           // Добавляем атрибут для XML-Test

           OutputXML.WriteAttributeString("Count_Parameters", "4");

           // Создаем элемент <имя>элемент</имя>

           OutputXML.WriteElementString("Question", "Answer");

           Random R = new Random();

           OutputXML.WriteElementString("A", R.Next(0,1000).ToString());

           OutputXML.WriteElementString("B", SQL_OLE);

           OutputXML.WriteElementString("C", TB_XML_Path.Text);

           OutputXML.WriteStartElement("Names");

           OutputXML.WriteStartElement("Name");

           OutputXML.WriteAttributeString("Type", "Male");

           OutputXML.WriteString("John");

           OutputXML.WriteEndElement();

           OutputXML.WriteStartElement("Name");

           OutputXML.WriteAttributeString("Type", "Male");

           OutputXML.WriteString("Teo");

           OutputXML.WriteEndElement();

           OutputXML.WriteStartElement("Name");

           OutputXML.WriteAttributeString("Type", "Famale");

           OutputXML.WriteString("Miana");

           OutputXML.WriteEndElement();

           // Закрываем XML-Test

           OutputXML.WriteEndElement();

           // Сбрасываем буфферизированные данные

           OutputXML.Flush();

           // Закрываем фаил, с которым связан output

           OutputXML.Close();

           MessageBox.Show("Документ " + SFD_XML.FileName + " успешно создан!", "Работа с базами данных (C#) :: XML");

       }

   }

 

Событие Click кнопки Прочитать простой документ:

 

   private void B_XML_Read_Click(object sender, EventArgs e)

   {

       S = null;

       LB_XML.Items.Clear();

       // Создаём экземпляр класса

       XmlDocument InputXML = new XmlDocument();

       // Загружаем XML-документ из файла

       InputXML.Load(SFD_XML.FileName);

 

       // Загружаем XML-документ из строки

       // InputXML.LoadXML(Path);

 

       // Получаем всех детей корневого элемента

       // InputXML.DocumentElement - корневой элемент

       foreach (XmlNode Table in InputXML.DocumentElement.ChildNodes)

       {

           // Перебираем все атрибуты элемента

           foreach (XmlAttribute A in Table.Attributes)

           {

               // A.Name - имя текущего атрибута

               // A.Value - значение текущего атрибута

               S = A.Name + ": " + A.Value;

           }

           // Перебираем всех детей текущего узла

           foreach (XmlNode CN in Table.ChildNodes)

           {

           }

           // Получаем текст хранящийся в текущем узле

           S = S + Table.InnerText + "\n\t";

       }

       MessageBox.Show("Значения аттрибутов для элеметов и узлов файла "+ SFD_XML.FileName +":\n\n\t" + S + "\nЗначения получены автоматическим перебором!", "Работа с базами данных (C#) :: XML");

       // Вытаскиваем значения "руками"

       XmlNodeList XMLTestAttributes = InputXML.SelectNodes("/XML-Test[@Count_Parameters='4']");

 

       foreach (XmlNode XN in XMLTestAttributes)

         {

           LB_XML.Items.Add(XN.InnerText + " -- все значения"); // В ListBox получаем значения всех узлов

       }

       XmlNodeList Names = InputXML.SelectNodes("/XML-Test/Names/Name[@Type='Male']");

 

       foreach (XmlNode XN in Names)

       {

           LB_XML.Items.Add(XN.InnerText + " -- одно мужское имя"); // В ListBox получаем только два мужских имени по отдельности

       }

       XmlNode Question = InputXML.DocumentElement.SelectSingleNode("Question");

       LB_XML.Items.Add(Question.InnerXml);

       XmlNode ANode = InputXML.DocumentElement.SelectSingleNode("A");

       LB_XML.Items.Add(ANode.InnerText);

       XmlNode BNode = InputXML.DocumentElement.SelectSingleNode("B");

       LB_XML.Items.Add(BNode.InnerText);

       XmlNode CNode = InputXML.DocumentElement.SelectSingleNode("C");

       LB_XML.Items.Add(CNode.InnerText);

       XmlNode NamesNode = InputXML.DocumentElement.SelectSingleNode("Names");

          LB_XML.Items.Add(NamesNode.InnerText + " -- все имена"); // В Listbox получаем все имена

   }

 

Компилируем приложение (Debug) и запускаем:

 

Рис. 5. 3. Окончательная работа блока: XML

 

Нажатие на кнопку Создать простой документ, создаёт по указанному пути файл (в данном случае по рисунку: D :\ XML - Test . xml) следующего содержания:

 

При нажатии на кнопку Прочитать простой документ, происходит чтение всех записей в цикле (с выводом всплывающего окна), а затем вывод в ListBox. Выводятся все значения (верхняя строчка), затем только два мужских имени из блока < Names >...</ Names >, затем все значения узлов Question, A, B и С и наконец все имена.

Почему существует несколько классов для работы с одним и тем же (в частности в XML )? На этот вопрос, есть два ответа: «на вкус и цвет все фломастеры разные» и «в зависимости от предоставляемой функциональности один класс может оказаться удобнее в той или иной ситуации».

 

Несколько причин, почему стоит использовать классы для генерации XML документа, а не создавать его вручную:

1. Практически нулевой риск создать неправильный XML документ.

2. Можно задать форматирование (отступы и прочее) XML документа (очень сильно улучшает читаемость).

 

Наиболее подходящим для формирования XML-документа «за раз» является класс XmlWriter. Плюсы данного класса:

1. Форматирование результирующего XML документа.

2. Создание открывающего и закрывающего тега в одну команду, причём для создания закрывающего тега не требуется знать имя открывающего.

Для форматирования выводимого XML документа в XmlWriter используется класс XmlWriterSettings.

 

Используя функцию WriteElementString,тэг не только открывается, в него записываются данные, но и тут же закрывается, поэтому добавить атрибут к такому элементу НЕЛЬЗЯ! Для решения данной проблемы нужно использовать WriteStartElement, WriteAttributeString, WriteEndElement.

 

Для чтения XML-документа предусмотрен класс XMLReader, но он крайне не удобен, потому что осуществляет последовательное считывание и не позволяет «прыгать через»/обращаться сразу к нужному элементу.

 

Чтение и редактирование удобно производить через класс XmlDocument.

Из чего состоит XML-документ:

1. Строка вида <?xml … ?>

2. Родительский элемент (единственный).

3. Дальше, внутри родительского элемента располагаются элементы-потомки (child’ы) и далее по иерархии.

 


Дата добавления: 2019-09-13; просмотров: 214; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!