Разбор XML-файлов в .NET

Вячеслав Гринин, February 27, 2010

Заметил я вот какую странную вещь – мало я пишу про ASP.NET, несмотря на то, что сам я в основном программирую именно под ASP.NET. И решил я начинать исправлять эту ситуацию потихоньку. И теперь в нашем блоге будет появляться все больше статей, посвященных ASP.NET, да и вообще технологии .NET. И сегодня будет именно такая статья. Посвящена она работе с XML-файлами.

Вы уже наверное заметили, что я люблю парсить XML-файлы. Да просто формат этот очень уж удобный для передачи и хранения различных данных. Взять вот хотя бы тот же gismeteo-информер, который я уже успел распарсить несколькими различными методами. И все эти методы касались языка JavaScript. А теперь попробуем распарсить его и в .NET. Но давайте уж возьмем не сам по себе информер, а кое-какие другие XML-данные с сайта gismeteo.

Исходные данные: Mozilla с установленным FireBug, открытая в нем страница http://informer.gismeteo.ru/getcode/xml.php. Видите внизу три списка, соответственно: стран, регионов и городов? Так вот, когда Вы в нем выбираете страну, то в списки регионов и городов загружаются регионы и города выбранной страны. При этом происходит запрос на сервер gismeteo вот такого вида: http://informer.gismeteo.ru/getcode/index.php. При этом, в POST-параметрах запроса передаются параметры: a1=156 (для регионов), a2n=156 (для городов). 156 – это код России в справочниках gismeteo.

А назад мы получаем XML-файл вот такого вида (здесь я приведу лишь кусок файла):

<cities>
<city value="11845" old_id="99855">Абаза</city>
<city value="4723" old_id="29865">Абакан</city>
<city value="4659" old_id="29485">Абан</city>
<city value="4546" old_id="28581">Абатский</city>
<city value="4607" old_id="28815">Абдулино</city>
<city value="11657" old_id="99666">Абинск</city>
<city value="12874" old_id="89157">Автуры</city>
<city value="3967" old_id="23383">Агата</city>
</cities>

Итак захотел я распарсить именно этот файл. Скажу даже зачем мне это нужно. А вот нужно мне по названию города на русском языке получить соответствующий XML-документ с данными о погоде в этом городе. А XML этот лежит по вот такому пути: http://informer.gismeteo.ru/xml/99855_1.xml , где 99855 – это аттрибут old_id нужного мне города. Понятно, что разобранный файл я сохраню затем в базу данных, откуда и буду выбирать айдишники нужных мне городов. Наверное, можно было попросить эту базу у gismeteo, но я так и не нашел на их сайте работающих e-mail’ов. :) Да и не ищем мы легких путей. Будем самостоятельно парсить их базу .

Итак, вот готовый код для разбора подобного рода XML-файла:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.XPath;
using System.IO;

namespace ParseXML
{
class Program
{
static void Main(string[] args)
{
// Собственно XML
string xml = @"
<cities>
<city value=""11845"" old_id=""99855"">Абаза</city>
<city value=""4723"" old_id=""29865"">Абакан</city>
<city value=""4659"" old_id=""29485"">Абан</city>
<city value=""4546"" old_id=""28581"">Абатский</city>
<city value=""4607"" old_id=""28815"">Абдулино</city>
<city value=""11657"" old_id=""99666"">Абинск</city>
<city value=""12874"" old_id=""89157"">Автуры</city>
<city value=""3967"" old_id=""23383"">Агата</city>
</cities>";
// ЗАгружаем строку в XPathDocument
XPathDocument xPathDoc = new XPathDocument(new StringReader(xml));
XPathNavigator xPathNav = xPathDoc.CreateNavigator();
// Выбираем нужные узлы
XPathNodeIterator xPathIter = xPathNav.Select("/cities/city");
// Пробегаем по всем узлам
foreach (XPathNavigator nav in xPathIter)
{
// Метод GetAttribute извлекает аттрибут узла
int id = Int32.Parse(nav.GetAttribute("value", ""));
int old_id = Int32.Parse(nav.GetAttribute("old_id", ""));
// Свойство Value узла дает нам содержимое XML-узла, то есть строку,
// которая содержится между открывающим и закрывающим XML-тегами
Console.WriteLine("{0} \t id={1}, \t http://informer.gismeteo.ru/xml/{2}_1.xml",
nav.Value, id, old_id);
}
Console.ReadLine();
}
}
}

Вот и все. Думаю, что код этот очень простой и в дополнительном комментировании не нуждается.

Кстати, скачать бесплатно мобильные игры java Вы можете на сайте mobi4uk4a.ru. Я скачал себе набор пасьянсов, теперь есть чем заняться пока еду в метро.

Нам и нашим четвероногим друзьям нужна квалифицированная ветеринарная помощь, ведь только в этом случае можно быть уверенным, что Ваш домашний любимец будет здоров и проживет долгую жизнь рядом с Вами. Не стоит надеяться на “авось”, если Ваш питомец заболел, и ни в коем случае нельзя заниматься самолечением – сразу идите в ветеринарную клинику “Биоконтроль”

На днях нашел замечательный ресурс посвященный фрилансу. Софт, книги, статьи для вебмастера – здесь есть все необходимое для того, чтобы Ваша работа в сфере web доставляла Вам истинное удовольствие.

Кроссбраузерное XSLT-преобразование в JavaScript

Вячеслав Гринин, October 25, 2009

Столкнулся я однажды с необходимостью отобразить XML-данные погодного информера gismeteo посредством XSLT-шаблона. Причем возникла острая необходимость сделать это через JavaScript, так как на предлагаемом бесплатном хостинге не было поддержки PHP, а значит отпарсить XML на сервере не представлялось возможным.

В результате этой острой необходимости родился код на JavaScript, который я и предлагаю на ваше рассмотрение.

function transformXslt(source,style) {
    if(window.ActiveXObject)
    {
        return source.transformNode(style);
    }
    else if(window.XSLTProcessor)
    {
        var xsltProcessor=new XSLTProcessor();
        xsltProcessor.importStylesheet(style);
        var resultDocument = xsltProcessor.transformToDocument(source);
        var xmls = new XMLSerializer();
        return xmls.serializeToString(resultDocument);
    }
    else
    {
        alert("Преобразование XML не поддерживается браузером");
        return null;
    }
}

Что мы здесь видим?

А видим мы здесь кроссбраузерное решение данной задачи. XSLT-преобразование в IE производится посредством метода transformNode XML-документа. Во всех остальных браузерах(FF, Chrome, Safari, Opera) XSLT-преобразование делается совсем по-другому. И делается оно посредством объекта XSLTProcessor, в который методом importStylesheet загружается файл стилей XSLT, а результирующий документ генерируется методом transformToDocument(xml). И напоследок мы поручим объекту XMLSerializer сгенерить строковое представление результирующего XML-документа.

И напоследок еще одна полезная, и такая же кроссбраузерная, функция, которая преобразует строковое представление XML (и XSLT)-документа собственно в сам документ, готовый для его дальнейшего использования.

function getXMLFromString(s) {
    if(window.ActiveXObject)
    {
        var xml;
        xml=new ActiveXObject("Microsoft.XMLDOM");
        xml.async=false;
        xml.loadXML(s);
        return xml;
    }
    else if(window.DOMParser)
    {
      var parser = new DOMParser();
      return parser.parseFromString(s,'text/xml');
    }
    else
    {
        alert("Загрузка XML не поддерживается браузером");
        return null;
    }
}

Этот код я собираюсь оставить без комментариев, так как в нем и так все понятно. :)

Скачать файл с этими функциями вы можете здесь

Парсинг XML в JavaScript на примере XML-погоды от gismeteo.ru

Вячеслав Гринин, March 20, 2009

Итак, заинтересовала меня тема, как распарсить XML-файл посредством JavaScript. Немного порыскав в поисковиках наткнулся на весьма познавательную статью по этой теме XML в Microsoft Internet Explorer 5.0. Есть у этой статьи маленький недостаток – она посвящена только IE, а мы в нашем блоге твердо решили писать только кроссбраузерный код. Однако, для начала хватило и этой статьи, сначала весь код был написан для IE, и затем была осуществлена безуспешная попытка запустить его также в Opera, Mozilla, Chrome. Но как я уже говорил “не боги горшки обжигают”, все некроссбраузерные баги были успешно найдены и исправлены. Это р-раз.

В качестве подопытного кролика был взят XML-файл, содержащий в себе данные о погоде на ближайшие сутки от Gismeteo.ru. Собственно, открыв эту страницу, и выбрав интересующий вас город, вы можете ниже на той же странице наблюдать содержимое этого XML-файла, и описание его структуры. Это д-два.

Сопоставив первые два пункта уже можно сваять свой собственный парсер XML-документов на JavaScript, однако если вам лень, то читайте статью дальше. В ней я расскажу о том, как провести анализ содержимого XML-файла и отобразить его в том виде, в котором вам хочется. Это т-три.

А вот сразу ссылка на результаты работы моего скрипта. Не расстраивайтесь, что выглядит все так просто, скриптик позволяет посредством шаблонов задать собственный вид отображения результатов, и об этой возможности я расскажу ниже.

Сразу хочу предупредить, что ниже пойдет теоретическая и практическая часть работы с XML-файлами, и если вам не хочется вникать во все эти подробности, то вы можете сразу перейти в самый конец статьи и по предложенной там ссылке скачать готовый скрипт обработки XML-документа, содержащего прогноз погоды от gismeteo.ru. А теперь теория…

Итак, что же такое XML? Wikipedia утверждает, что:

XML (eXtensible Markup Language — расширяемый язык разметки) — рекомендованный консорциумом W3C язык разметки, представляющий собой свод общих синтаксических правил. XML — текстовый формат, предназначенный для хранения структурированных данных, для обмена информацией между программами, а также для создания на его основе более специализированных языков разметки. Целью создания XML было обеспечение совместимости при передаче структурированных данных между разными системами обработки информации, особенно при передаче таких данных через Интернет.

Визуально структура XML может быть представлена как дерево. Важнейшее обязательное требование состоит в том, что документ должен иметь только один корневой элемент (в нашем случае это элемент MMWEATHER). Это значит, что данные всего документа должны быть расположены между единственным начальным корневым тегом и соответствующим ему конечным тегом.

Остальная часть XML-документа состоит из вложенных элементов, которые могут иметь атрибуты и содержимое. Элемент обычно состоит из пары тегов (открывающего и закрывающего), обрамляющих другие элементы. Открывающий тег состоит из имени элемента в угловых скобках, например, <FORECAST> ; закрывающий тег состоит из того же имени в угловых скобках, но перед именем ещё добавляется косая черта, например, </FORECAST>. Содержимым элемента называется всё, что расположено между открывающим и закрывающим тегами, включая текст и другие вложенные элементы.

Кроме содержания у элемента могут быть атрибуты — пары имя-значение, добавляемые в открывающий тег после названия элемента. Например в случае <PHENOMENA cloudiness=”2″ precipitation=”10″ rpower=”0″ spower=”0″/>
элемент PHENOMENA имеет 4 атрибута cloudiness, precipitation, rpower и spower имеющие соответственно значения 2, 10, 0, 0.

Итак, со структурой XML-файла более-менее разобрались. Осталось только понять, каким образом все это богатство обрабатывать в JavaScript. Собственно, в статье XML в Microsoft Internet Explorer 5.0 можно обо всем этом прочесть, но я намерен вкратце обрисовать ниже основные приемы анализа XML-файлов в контексте поставленной в начале статьи задачи – разбора XML-документа, содержащего прогноз погоды на сутки от gismeteo.

  1. Загрузка XML-документа. Хочу сразу заметить, что загрузка любых файлов из JavaScript возможна при соблюдении одного обязательного условия – загружаемый файл должен быть расположен в том же домене, где и сама страница его загружающая. Поэтому невозможно со страницы, расположенной, например, по адресу http://easy4web.ru/samples/gismeteo/ загрузить файл с сайта http://gismeteo.ru. А это означает, что … проблему надо как-то решать. Есть два пути: либо скачать файл с сайта gismeteo.ru на свой домен, либо создать на вашем домене простой PHP-обработчик, который сам будет скачивать файл с другого домена и выдавать его содержимое от своего имени. В предлагаемом мною решении я пошел по второму пути и поэтому чуть ниже приведу вам PHP-скрипт, выполняющий данное действие. А теперь, собственно, о загрузке XML-документов.
    В IE эта операция производится с помощью следующего кода

    xml=new ActiveXObject("Microsoft.XMLDOM");
    xml.async=false;
    xml.load(url);

    После выполнения которого в переменной xml будет храниться обработанный XML-Документ. Конечно, если документ был верно отформатирован. В ином случае будет сгенерировано исключение.
    Во всех остальных браузерах (Opera, Firefox, Chrome) загрузка файлов выглядит иначе:

    xml=new window.XMLHttpRequest();
    xml.open("GET", url, false);
    xml.send("");

    После чего в поле xml.responseXML можно обнаружить обработанный XML-документ. Таким образом, полный текст функции, осуществляющей загрузку XML-документа, будет выглядеть следующим образом:

    function getXMLDocument(url)
    {
        var xml;
        if(window.XMLHttpRequest)
        {
            xml=new window.XMLHttpRequest();
            xml.open("GET", url, false);
            xml.send("");
            return xml.responseXML;
        }
        else
            if(window.ActiveXObject)
            {
                xml=new ActiveXObject("Microsoft.XMLDOM");
                xml.async=false;
                xml.load(url);
                return xml;
            }
            else
            {
                alert("Загрузка XML не поддерживается браузером");
                return null;
            }
    }
  2. Получение коллекции элементов по имени элемента производится использованием метода getElementsByTagName(tagname) объекта XMLDOMDocument. Например, получить массив всех элементов TOWN можно так: xml.getElementsByTagName(“TOWN”). Понятно, что в переменную xml уже должен быть загружен сам XML-документ.
  3. Просмотр коллекции элементов лучше проводить с помощью цикла for, так как итератор nextNode() пригодный для использования в цикле while, увы, не определен для результата, возвращаемого объектом XMLHttpRequest, а значит будет работать только в IE. Вот код для просмотра коллекции элементов циклом for:
    var towns=xml.getElementsByTagName("TOWN");
    if(towns)
    for(var i1=0; i1<towns.length; i1++)
    {
       town=towns[i1];
       // операции над текущим элементом town
    }
  4. Получение атрибутов элемента.
    Вообще, все атрибуты элемента хранятся в его коллекции attributes, однако доступ к ней неудобен, и поэтому я написал простую функцию, которая пробегает по всей коллекции атрибутов и распаковывает ее в удобный для работы массив, позволяющий получить доступ к любому атрибуту через оператор “квадратные скобки”. Вот эта функция:

    function getAttributes(node)
    {
      var ret = new Object();
      if(node.attributes)
      for(var i=0; i<node.attributes.length; i++)
      {
        var attr = node.attributes[i];
        ret[attr.name] = attr.value;
      }
      return ret;
    }

Вот собственно и вся предварительная подготовка. Используя эту информацию, уже можно написать анализатор XML-файлов с прогнозом погоды. Конечно, работа с XML-файлами гораздо сложнее, чем я здесь описал, но для пытливых умов существуют книги, интернет, поисковики.

Вот ссылка на готовый скрипт парсера XML-погоды. Вам следует только обратить внимание на шаблоны (переменная template) в конце файла index.html. Это объект в JSON-нотации, содержащий в себе следующие поля: “town”, “forecast”, “phenomena”, “pressure”, “temperature”, “wind”, “relwet”, “heat”, “t_forecast”, “t_template”. Первые 8 представляют собой строки, в которых хранятся шаблоны отображения конкретных нюансов прогноза: город, дата прогноза, атмосферные явления, давление, температура, ветер, относительную влажность, комфортную температуру. В HTML-разметку каждого шаблона вставляются конкретные данные прогноза, которые имеют вид соответствующих имен атрибутов, взятых в фигурные скобки. Все имена атрибутов вы можете увидеть внизу страницы Gismeteo.ru. Для некоторых числовых атрибутов существуют также их строковые псевдонимы, получаются они путем прибавления к атрибуту префикса “s”. Абсолютно все используемые в шаблонах атрибуты вы можете увидеть в конце HTML-разметки страницы index.html, в тегах <script>.

И еще два шаблона, используемых в переменной template. Это t_forecast и t_template. Первый задает разметку прогноза для конкретного времени суток, а второй – разметку для всех прогнозов одного города.

Понимаю, что последний абзац получился запутанным, но, надеюсь, взглянув в код, вы все поймете самостоятельно. Если же возникают вопросы, то пишите их в комментариях к посту, Отвечу на все.

Где-то в середине статьи я обещал показать код PHP-Обработчика, скачивающего XML с других сайтов. Код этот вы можете увидеть в архиве с исходниками в файле xml.php. Он короткий и в пояснениях не нуждается.

Поиск по блогу:
Подписаться:
Популярные:
Облако тегов:
Разное:
Счетчик: