Работа с XML в .NET - Чтение документов с XmlTextReader

ОГЛАВЛЕНИЕ

Чтение документов с XmlTextReader

Класс XmlTextReader обеспечивает быстрое однонаправленное чтение потока XML-данных. Данные могут быть получены из файла, объекта потока Stream или объекта TextReader. XmlTextReader обычно применяется если нужно считать XML документ и получить из него данные. Так как XmlTextReader не загружает весь документ в память, он является наилучшим выбором при обработке больших XML файлов - логов, дампов БД и пр.

Прочитаем данные о заказах с помощью класса XmlTextReader из XML-файла, созданного нашей программой в предыдущем разделе.

OpenFileDialog dlg = new OpenFileDialog();
dlg.Filter = "Файлы XML (*.xml)|*.xml"; if (dlg.ShowDialog() ! = DialogResult.OK)
    return;

XmlTextReader reader = null;
orders.Clear();

try
{
    reader = new XmlTextReader(dlg.FileName);
    reader.WhitespaceHandling = WhitespaceHandling.None; // пропускаем пустые узлы

    while (reader.Read())
        if (reader.NodeType == XmlNodeType.Element)
            if (reader.Name == "Заказ")
            {
                 Order order = new Order(reader.GetAttribute("Адрес"), DateTime.Parse(reader.GetAttribute("Дата"))); 

                 // получаем товары в заказе
                 while (reader.Read() && reader.Name == "Товар")
                     order.AddGood(reader.GetAttribute("Название"), float.Parse(reader.GetAttribute("Цена")));
                 orders.Add(order);
            }

            ShowOrders();
}
catch (Exception ex)
{
    MessageBox.Show("Ошибка: " + ex.Message);
}
finally
{
    if (reader != null)
        reader.Close();
}

XML-данные, которые читает XmlTextReader, берутся из файла, выбранного пользователем в диалоге. Для подавления пустых строк мы устанавливаем значение None для свойства WhitespaceHandling. Метод Read() производит чтение из потока следующего узла XML-документа. Он возвращает true если удалось считать узел. Обязательно нужно вызвать метод Read перед первым обращением к данным, т.к. в момент инициализации XmlTextReader не содержит никаких данных.

Имя тега возвращает свойство Name. В момент, когда имя текущего тега "Заказ", мы создаем новый объект Order. Дату и адрес заказа мы получаем с помощью метода GetAttribute. Вложенные в заказ товары получаем перебирая теги в цикле while до тех пор, пока имя текущего тега "Товар". Важно то, что если запрашиваемый атрибут не найден, то возвращается пустая строка. При этом проверка того, является ли этот атрибут обязательным для текущего тега не производится. При чтении файла bad.xml, в одном из заказов не указан адрес. Однако, программа успешно считывает файл и выводит такие данные. Проверку допустимости XML-документа осуществляет класс XmlValidatingReader, о котором будем говорить ниже.

 

Тип узла можно определить по значению свойства NodeType - оно возвращает значение из перечисления XmlNodeType. Типом узла может быть элемент документа, атрибут, комментарий и т.д. Значение узла зависит от типа тега и возвращатся свойством Value. Например, для текстового тега возвращается текстовое значение, находящееся в теге, а для комментария - текст комментария.

Для идентификации текущего положения в документе существуют методы Depth, возвращающий уровень вложенности текущего тега, и LineNumber и LinePosition, возвращающие строку и позицию текущего тега в документе. Так как XmlTextReader часто применяется для получения значений только определенных узлов XML-документа, то для ускорения процесса поиска узлов можно применять метод Skip, который пропускает дочерние узлы текущего узла документа.