Работа с XML в .NET - Чтение документов с XmlDocument
ОГЛАВЛЕНИЕ
Чтение документов с XmlDocument
Класс XmlDocument реализует W3C Document Object Model (DOM) Level 1 Core и Core DOM Level 2. XmlDocument наиболее полезен в том случае, если нужно загрузить XML-документ в память для того, чтобы изменить атрибуты узлов, добавить или удалить новые элементы. DOM представляет XML-документ как дерево, хранящееся в памяти, с элементом-документом, являющимся корнем. Например, вот такой XML-документ, созданный нами ранее
<Заказы>
<Заказ Адрес="Уфа" Дата="21.04.2004">
<Товар Название="Товар_А" Цена="100" />
<Товар Название="Товар_Б" Цена="150" />
<Товар Название="Товар_В" Цена="370" />
</Заказ>
<Заказ Адрес="Москва" Дата="24.04.2004">
<Товар Название="Товар_Г" Цена="400" />
</Заказ>
<Заказ Адрес="Омск" Дата="28.04.2004">
<Товар Название="Товар_Д" Цена="255" />
</Заказ>
</Заказы>
будет представлен в виде такого дерева
Каждый узел в таком дереве является объектом класса XmlNode. Узел имеет только одного родителя и может иметь несколько атрибутов и дочерних узлов.
В нашем приложении XmlDocument применяется для загрузки данных о заказах из XML-файла. Рассмотрим эту функцию.
private void menuItemOpenDocument_Click(object sender, System.EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Filter = "Файлы XML (*.xml)|*.xml";
if (dlg.ShowDialog() != DialogResult.OK)
return;
XmlDocument doc = new XmlDocument();
orders.Clear();
try
{
doc.Load(dlg.FileName);
// получаем все заказы
XmlNodeList ordersList = doc.DocumentElement.ChildNodes;
foreach (XmlNode nodeOrder in ordersList)
{
Order order = new Order(nodeOrder.Attributes["Адрес"].Value, DateTime.Parse(nodeOrder.Attributes["Дата"].Value));
// получаем все товары из заказа
XmlNodeList goodsList = nodeOrder.ChildNodes;
foreach (XmlNode nodeGood in goodsList)
order.AddGood(nodeGood.Attributes["Название"].Value, float.Parse(nodeGood.Attributes["Цена"].Value));
orders.Add(order);
}
ShowOrders();
}
catch (Exception ex)
{
MessageBox.Show("Ошибка: " + ex.Message);
}
}
Функция Load() загружает XML-документ, выбранный пользователем. В случае возникновения ошибки при чтении файла или разборе XML-документа выбрасывается исключение XmlException и документ остается пустым. Есть и перегруженная версия функции, принимающая в качестве параметра объект Stream. Для получения корневого элемента документа существует свойство DocumentElement, возвращающий объект XmlElement если документ не пуст или null в противном случае. Для получения всем потомков узла существует свойство ChildNodes. В нашем примере мы получили корневой элемент документа, соответствующий тегу "Заказы", и перебрали дочерние элементы - теги "Заказ". Для получения значений атрибутов тега было использовано свойство Attributes. В нашем случае мы получали значение атрибутаа по имени, но можно было получить его по порядковому номеру или имени и пространству имен. Тег для товара в заказе является дочерним по отношению к тегу заказа, поэтому для получения всех товаров из заказа мы так же воспользовались свойством ChildNodes.
Кроме перебора всех узлов XML-документа существуют и другие способы нахождения нужной информации. Можно найти нужны узлы XML-документа, воспользовавшись выражением XPath (методы SelectSingleNode и SelectNodes) - этот способ мы рассмотрим далее. Или можно получить список XmlNodeList всех тегов определенного имени. Для получения дат всех заказов можно получить все теги "Заказ", и получить значение их атрибута "Дата".
XmlNodeList orders = doc.GetElementsByTagName("Заказ");
foreach (XmlNode node in orders)
Console.WriteLine(elemList[i].Attributes["Дата"]); }
Наш формат хранения данных очень прост и однозначен. В реальных случаях для разбора документов приходится использовать имя тега, его значение и тип, о которых мы говорили выше.
Класс XmlDocument обычно используется для изменения существующих XML-документ. Однако, можно загрузить XML-документ из текстовой строки методом LoadXML класса XmlDocumentа, а затем добавить в него новые узлы и сохранить в файл. При этом мы используем загруженный документ как шаблон, хотя можно создавать документ и с нуля. Приведем пример использования функции LoadXML .
XmlDocument doc = new XmlDocument();
doc.LoadXml("<Заказы></Заказы>");
XmlNode order = doc.CreateElement("Заказ");
XmlAttribute attrDate = doc.CreateAttribute("Дата");
attrDate.Value = DateTime.Today.ToShortDayString();
order.Attributes.Append(attrDate);
XmlAttribute attrAdr = doc.CreateAttribute("Адрес");
attrAdr.Value = "Уфа";
order.Attributes.Append(attrAdr);
doc.DocumentElement.AppendChild(order);
doc.Save("заказы.xml");
Вначале мы создаем пустой список заказов, вызывая LoadXml. Затем создаем узел для заказа и добавляем к нему атрибуты для даты и адреса методом CreateAttribute. Затем добавляем узел для заказа к корневому элементу документа функцией AppendChild и сохраняем документ в файл.