Чтение XML через LINQ и C#

Статья даёт ответы на следующие вопросы:

  • Как использовать Linq в С#?
  • Как считать данные из xml с помощью c# ling to xml?
  • Как обращаться к атрибутам, дочерним и родительским элементам в xml?

Довольно часто перед разработчиками встаёт задача интеграции приложений на основе формата xml.

Данная статья посвящена тому, как быстро прочитать существенный объём данных из xml-файла с использованием языка программирования C# и технологии Linq.

В примере обрабатывается xml-файл достаточно сложной структуры, когда значимой является информация элементов различного уровня вложенности.

В данном случае считывается информация из узлов Point и их родительских узлов Элемент. При этом в каждом узле Элемент размещён один узел Point. Качество структуры xml не бесспорно, но она позволяет наглядно продемонстрировать возможности технологии Linq.

Пример структуры считываемого xml-файла:

 <?xml version="1.0" encoding="UTF-8" ?> 
 <Выгрузка ДатаВыгрузки="09.06.2011 16:30:53" ДанныеФайла="трансферные цены" GUIDДанных="хххххххх-хххх-хххх-хххх-хххххххххххх" ContraName="Завод специальных деталей" ContraINN="7717027256" ContraKPP="771701001">
 <Элементы>
 <Элемент Date="01.04.2011 0:00:00" Price="779.00">
   
  
 <Элемент Date="01.04.2011 0:00:00" Price="1224.00">
   
  
 <Элемент Date="01.04.2011 0:00:00" Price="1278.00">
   
  
  
  

Для чтения этого файла создадим в Visual Studio 2010 новый проект типа Windows Forms Application на языке C#.

Разместим на форме следующие элементы интерфейса:

  • текстовое поле для отображения имени файла (TextBox: textBox1);
  • кнопку для открытия диалога выбора файла (button1);
  • кнопку для запуска процесса чтения файла (button2);
  • индикатор процесса чтения файла (ProgressBar: pb1);
  • текстовую область для отображения считанной из xml-файла информации (RichTextBox: rtb1).

Добавим в Solution Explorer в разделе References пространство имён: System.Xml.Linq.

Разберём подробнее основную процедуру загрузки данных XmlLoad().

private void LoadXML() {
            XElement doc = XElement.Load(textBox1.Text);
            IEnumerable childList =
                from el in doc.Elements().Elements().Elements("Point")
                select el;
            int num_el = childList.Count();
            int i = 0;
            string str = "";
            str += "номенклатура\tid\tцена\tдата\n";
            foreach (XElement el in childList)
            {
                str += el.Attribute("PointName").Value + "\t" + el.Attribute("PointGuid").Value + "\t" + el.Parent.Attribute("Price").Value + "\t" + el.Parent.Attribute("Date").Value + "\n";
                i++;
                pb1.Value = (int)((float)i / num_el * 100);
            }
            rtb1.Text = str;
        }

Вначале создаётся объект класса XElement, используемый для чтения xml-документа.

Далее формируется Linq-запрос к считанным данным. Запрос обращается к под-под-элементам xml-документа с именем Point. На выходе запроса формируется коллекция ChildList, доступная для последующего обхода в цикле.

Следующим значимым элементом кода является цикл, в котором перебираются элементы из ChildList. Этими элементами, как мы уже знаем, являются узлы xml-документа Point. Доступ к атрибутам каждого элемента доступен через свойство Attribute, а доступ к родительским элементам через свойство Parent.

Для оценки производительности использовался файл из ~ 3000 строк объёмом 253Кб. Время загрузки информации составило около 1 секунды.

Таким образом, технология Linq предоставляет разработчику эффективный и удобный инструмент по оперированию данными xml, практически исключая использование множественных циклов.

Полный код приложения на C#:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Xml.Linq;
using System.Text;
using System.Windows.Forms;

namespace MyLinqToXmlApp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
                OpenFileDialog openFileDialog1 = new OpenFileDialog();
                openFileDialog1.InitialDirectory = "c:\\" ;
                openFileDialog1.Filter = "xml files (*.xml)|*.xml|All files (*.*)|*.*" ;
                openFileDialog1.FilterIndex = 1 ;
                openFileDialog1.RestoreDirectory = true ;

                if(openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    textBox1.Text = openFileDialog1.FileName;
                }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (textBox1.Text == "") return;
            LoadXML();
        }

        private void LoadXML() {
            XElement doc = XElement.Load(textBox1.Text);
            IEnumerable childList =
                from el in doc.Elements().Elements().Elements("Point")
                select el;
            int num_el = childList.Count();
            int i = 0;
            string str = "";
            str += "номенклатура\tid\tцена\tдата\n";
            foreach (XElement el in childList)
            {
                str += el.Attribute("PointName").Value + "\t" + el.Attribute("PointGuid").Value + "\t" + el.Parent.Attribute("Price").Value + "\t" + el.Parent.Attribute("Date").Value + "\n";
                i++;
                pb1.Value = (int)((float)i / num_el * 100);
            }
            rtb1.Text = str;
        }
    }
}

Тэги: