Перед многими часто встаёт задача распарсить 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 встречается в файле несколько раз, но у него разное содержимое. Подскажите, как можно добавить условие, что:
Спасибо заранее!
На скорую такой ответ:
1. Соберите все «kind» и запишите в массив или в список.
2. Определите в цикле какой из них содержит 01. Потом определите его порядковый номер в массиве.
3.1. Если количество тегов «kind» равно количеству тегов «docdetails», то мы сразу узнаем порядковый номер «docdetails» и считаем вложенный в него «number».
3.2. Или соберите все «number» в массив и порядковый номер «number» будет равен порядковому номеру «kind», его мы и считаем.
Если подумать подольше, то можно и ещё варианты подобрать.
ну и задали вы мне задачку, учитывая то, что я чуть ли ни вчера занялась программированием ))) По первому варианту есть вопрос. Допустим я создаю List
и мне нужно добавить значение всех тегов kind в него, но их может быть неограниченное (заранее неизвестное) количество. Вот как мне определить длину массива? Т.е. в данном файле их 3, и, если бы это было бы постоянная величина, то я бы написала так:
У List не надо задавать размер и это поможет, а по поводу реализации надо думать.
Первое что приходит в голову это получить количество «kind» так:
не знаю, не получилось. По первому варианту вроде все срослось с одним файлом, но загрузила другой, а там «kind» вложен также в другой элемент (не только в «docdetails»)
Тогда вам надо определиться какие «kind» вам нужны. Если все, то Count получайте по всем. Если определённые, то Count получайте по примеру выше.
Отличная статья!
Отличная инфа бро! Пили есчо