Перед многими часто встаёт задача распарсить XML с помощью C#. В данной статье опишу простейшие методы разбора XML без излишней сложности и без подключения библиотек сторонних разработчиков. Описанных примеров хватит для большинства существующих задач.
Создадим в Visual Studio проект Windows Form и набросаем кнопки и текстовые поля и получим примерно такую форму:

По кнопке «Машина» мы будем получать из XML марку, номер и регион, в котором зарегистрирован автомобиль. По кнопке «Страна 2» мы будем получать из XML название второй страны и выводить данные в поле результата. По кнопке «Параметры Страна 1» мы будем получать из XML параметры первой страны (валюта, язык, столица) и выводить данные в поле результата.
Подключим к проекту:
using System; using System.IO; using System.Xml; using System.Windows.Forms;
Объявим пару переменных:
/// <summary> Путь к рабочему каталогу, относительно исполняемого файла </summary> public static string dirWork = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); /// <summary> Файл, который необходимо парсить </summary> public static string fileXML = dirWork + @"\XMLFileForParse.xml";
«XMLFileForParse.xml» — это XML-файл который мы будем разбирать, и который имеет следующую структуру:
<?xml version="1.0" encoding="utf-8" ?>
<body>
<ns2:TransportResponse xmlns:ns2="http://webservices.victorz.ru/">
<TransportName>Газель</TransportName>
<TransportNumber>р999вд</TransportNumber>
<TransportRegion>77</TransportRegion>
</ns2:TransportResponse>
<country>
<name>Россия</name>
<param coin="рубль" language="русский" stolitsa="Москва" />
</country>
<country>
<name>USA</name>
<param coin="usd" language="english" stolitsa="New York" />
</country>
</body>
Давайте получим из XML марку автомобиля, номер и регион. Все три значения мы будем получать разными способами, чтобы охватить шире тему. В коде все строки стараюсь комментировать подробно:
/// <summary>
/// Кнопка "Машина"
/// </summary>
private void button2_Click(object sender, EventArgs e)
{
textBoxResult.Clear(); // очистить поле результатов
XmlDocument docXML = new XmlDocument(); // XML-документ
docXML.Load(fileXML); // загрузить XML
string _name = docXML.GetElementsByTagName("TransportName")[0].InnerText; // получаем значение тега "TransportName", так как тег "TransportName" единственный, то обращаемся к нему напрямую (указывая порядковый номер/индекс [0])
/* Далее попробуем получить данные поработав с пространством имён (в будущем может пригодиться)
* В тегах у нас имеется пространство имён "ns2" (ns2:TransportResponse)
* Адрес пространства имён искать в XML. Пишем код и читаем XML
*/
XmlNamespaceManager _namespaceManager = new XmlNamespaceManager(docXML.NameTable); // инициализация пространства имён
_namespaceManager.AddNamespace("ns2", "http://webservices.victorz.ru/"); // указываем значение пространства имён "ns2" (данные взяли из XML)
// вычислим регион отталкиваясь от родителя и при этом не с самого начала документа ведём поиск, индекс [0] обязателен
string _region = docXML.DocumentElement.SelectNodes("//ns2:TransportResponse/TransportRegion", _namespaceManager)[0].InnerText; // получаем значение тега "TransportRegion"
/* Определим номер машины по полному пути, т.е. перечисляя все теги с самого начала документа
* Обратите внимание, что используя пример ниже можно не объявлять пространство имён, если оно присутствует, а просто указываем тег вместе с пространством
*/
string _number = docXML["body"]["ns2:TransportResponse"]["TransportNumber"].InnerText; ; // получаем значение тега "TransportNumber"
textBoxResult.Text = _name + " - " + _number + " - " + _region; // выводим результат: Газель - р999вд - 77
}
У нас в XML есть одинаковые теги «country», «name», «param».
Давайте получим название второй страны, тег «name»:
/// <summary>
/// Кнопка "Страна 2"
/// </summary>
private void button3_Click(object sender, EventArgs e)
{
textBoxResult.Clear(); // очистить поле результатов
/* У нас несколько тегов со странами нам нужно получить название второй страны это можно сделать несколькими способами */
XmlDocument docXML = new XmlDocument(); // XML-документ
docXML.Load(fileXML); // загрузить XML
// выводим результат: USA
textBoxResult.Text = docXML.GetElementsByTagName("name")[1].InnerText; // ищем сразу тег "name" с названием страны и получаем значение (указывая порядковый номер/индекс [1])
// или
textBoxResult.Text = docXML.DocumentElement.SelectNodes("//country/name")[1].InnerText; // ищем в теге "country" тег "name" с названием страны и получаем значение (указывая порядковый номер/индекс [1])
}
До этого мы получали значения тегов, однако у тегов есть атрибуты. Далее рассмотрим получение значения атрибутов у тега «param». Давайте получим значения атрибутов тега «param» у первой страны:
/// <summary>
/// Кнопка "Параметры Страна 1"
/// </summary>
private void button4_Click(object sender, EventArgs e)
{
textBoxResult.Clear(); // очистить поле результатов
/* Получим все значения атрибутов тега "param" у первой страны */
XmlDocument docXML = new XmlDocument(); // XML-документ
docXML.Load(fileXML); // загрузить XM
string _coin = docXML.DocumentElement.SelectNodes("//country/param")[0].Attributes["coin"].Value; // получаем значение атрибута "coin"
string _language = docXML.DocumentElement.SelectNodes("//country/param")[0].Attributes["language"].Value; // получаем значение атрибута "language"
string _stolitsa = docXML.DocumentElement.SelectNodes("//country/param")[0].Attributes["stolitsa"].Value; // получаем значение атрибута "stolitsa"
textBoxResult.Text = _coin + " - " + _language + " - " + _stolitsa; // выводим результат: рубль - русский - Москва
}
Основы рассмотрели. Надеюсь в работе вам это поможет. Для наглядности приложил пример проекта с расширенными комментариями.









А для Json Есть пример работы??
Сейчас под рукой нет готового решения.
Используйте пакет «Newtonsoft.Json».
Как-нибудь на досуге напишу статью на эту тему.
Спасибо за статью! Мне нужно распарсить служебный файл, там сложная структура, во многом Ваша статья мне помогла. Но вот в одном месте не могу сообразить, как правильно написать. В общем, структура xml допустим такая (упростила)
Т.е. элемент с тегом docdetails встречается в файле несколько раз, но у него разное содержимое. Подскажите, как можно добавить условие, что:
if (элемент с тегом docdetails имеет потомка kind с тегом 01) { string text = значение тега number вложенного в этот docdetails (т.е. в данном случае это значение "08-03" }Спасибо заранее!
На скорую такой ответ:
1. Соберите все «kind» и запишите в массив или в список.
2. Определите в цикле какой из них содержит 01. Потом определите его порядковый номер в массиве.
3.1. Если количество тегов «kind» равно количеству тегов «docdetails», то мы сразу узнаем порядковый номер «docdetails» и считаем вложенный в него «number».
3.2. Или соберите все «number» в массив и порядковый номер «number» будет равен порядковому номеру «kind», его мы и считаем.
Если подумать подольше, то можно и ещё варианты подобрать.
ну и задали вы мне задачку, учитывая то, что я чуть ли ни вчера занялась программированием ))) По первому варианту есть вопрос. Допустим я создаю List
и мне нужно добавить значение всех тегов kind в него, но их может быть неограниченное (заранее неизвестное) количество. Вот как мне определить длину массива? Т.е. в данном файле их 3, и, если бы это было бы постоянная величина, то я бы написала так:
У List не надо задавать размер и это поможет, а по поводу реализации надо думать.
Первое что приходит в голову это получить количество «kind» так:
int count = xml.Elements("docdetails").Elements("kind").Count();не знаю, не получилось. По первому варианту вроде все срослось с одним файлом, но загрузила другой, а там «kind» вложен также в другой элемент (не только в «docdetails»)
Тогда вам надо определиться какие «kind» вам нужны. Если все, то Count получайте по всем. Если определённые, то Count получайте по примеру выше.
Отличная статья!
Отличная инфа бро! Пили есчо