Статья даёт ответы на следующие вопросы:
- Как использовать 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; } } }