Разбор XML-файлов в .NET
Заметил я вот какую странную вещь – мало я пишу про 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 доставляла Вам истинное удовольствие.
2. easyAPI. Удаленная загрузка XML.
И вот, наконец, долгожданная, вторая статья из раздела easyAPI.
Сегодня мы узнаем, как загрузить XML-данные с удаленного домена. Подобная задача возникает, например, когда владелец сайта на бесплатном (а значит – без серверного кода) хостинге хочет вставить в страницу погодный XML-информер. Именно на этом примере мы и рассмотрим сегодня удаленную загрузку XML-файлов.
Итак, для фоновой загрузки данных мы привыкли использовать так называемый AJAX, то есть объект XMLHttpRequest, про эту технологию я уже не раз писал в статьях блога. Однако, эта технология в данном случае никуда не годится. Почему? А потому что объект XMLHttpRequest не позволяет делать запросы к доменам, иным, чем тот, в котором работает скрипт, создающий этот объект.
И здесь к нам на помощь приходит технология, получившая название JSONP, что значит JavaScript Object Notation with Padding. Про сам JSON можео почитать вот здесь JSON, а JSONP представляет собой объект в нотации JSON обернутый в вызов функции, что-то вроде этого:
onSuccess('JSON-object')
А теперь объясню, зачем это нужно. Хоть XMLHttpRequest и не позволяет делать запросы к удаленным доменам, однако все браузеры позволяют нам загружать JavaScript’ы с любых доменов, то есть страница, загруженная с домена localdomain.ru, позволяет выполнить в ее рамках следующую инструкцию:
<script type='text/javascript' src='http://remotedomain.ru'> </script>
А теперь смотрите, что происходит. Наша страница загружает скрипт с удаленного домена, а скрипт этот возвращает нам JSONP-конструкцию, которая после загрузки скрипта тут же и выполнится, а значит, вызовет некую предопределенную заранее функцию onSuccess, которая получит в качестве аргумента тот самый XML-файл. И теперь мы можем делать с ним все, что захотим!
Осталось только одно – завладеть таким remotedomain.ru, который вернет нам то, что нам нужно. Скажу, что домен этот – http://easyapi.ru. Да-да, именно на этом, предусмотрительно приобретенном не так давно домене, и будут жить все наши полезные, жизненно необходимые почти каждому веб-разработчику, функции. 🙂 Скромненько и со вкусом…
Итак, в рамках домена easyapi.ru я уже создал ответную часть для удаленной загрузки XML-документов. Живет она вот здесь: http://easyapi.ru/xml/get.php и принимает на входе два GET-параметра: url и callback. Первый из них – адрес, с которого будет загружаться XML-файл, а второй – имя JavaScript-функции, которая будет вызвана после загрузки, и которая должна будет обработать полученный XML-документ.
Не откладывая дело в долгий ящик, приведу ниже содержимое страницы, которая, используя наш сервис easyAPI, загружает данные об XML-погоде в городе Москва и при помощи XSLT-шаблона преобразует эти данные в красивый информер, который вы, кстати, изучив основы XSLT-преобразований, сможете оформить по своему усмотрению.
Вот исходный код страницы:
<html> <head> <script type="text/javascript"> 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; } } 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 loading not supported"); return null; } } 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; } } </script> </head> <body> <div id="res"></div> <script type="text/javascript"> function onSuccess(res) { var xslt = getXMLDocument("http://easy-4-web.ru/samples/easyxml/gis.xsl"); var xml = getXMLFromString(res.result); var res = transformXslt(xml, xslt); document.getElementById("res").innerHTML=res; } </script> <script src="http://easyapi.ru/xml/get.php?url=http://informer.gismeteo.ru/xml/27612_1.xml&callback=onSuccess" type="text/javascript"></script> </body> </html>
В первой части страницы мы видим три функции, все они – кроссбарузерные:
- getXMLFromString(s) – преобразует валидную строку s в XML-документ
- getXMLDocument(url) – загружает XML-документ с адреса url
- transformXslt(source,style) – преобразует XML-документ source при помощи XSLT-шаблона style
В нижней части исходного кода мы видим функцию onSuccess – ока как раз и выполнится после загрузки xml-документа с удаленного домена. Она отрисует загруженный и полученный в переменной res.result XML-Документ при помощи XSLT-файла, хранящегося по адресу http://easy-4-web.ru/samples/easyxml/gis.xsl
И в самой-самой нижней части исходного кода мы видим вот такую конструкцию:
<script src="http://easyapi.ru/xml/get.php?url=http://informer.gismeteo.ru/xml/27612_1.xml&callback=onSuccess" type="text/javascript"></script>
Вот эта часть и представляет собой загружалку XML-документов с удаленных доменов. Как видим в атрибуте src тега SCRIPT мы указали, кто будет заниматься загрузкой (http://easyapi.ru/xml/get.php), что он будет загружать (url=http://informer.gismeteo.ru/xml/27612_1.xml) и какая функция займется обработкой документа (callback=onSuccess)
Здесь вы можете скачать исходные коды приведенного примера. А вот здесь – посмотреть, как это работает.
Кроссбраузерное XSLT-преобразование в JavaScript
Столкнулся я однажды с необходимостью отобразить 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+XSLT на примере XML-погоды от gismeteo.ru
Итак, выполняя свое обещание, публикую статью, посвященную отображению информера погоды gismeteo.ru.
Как вы помните, в прошлый раз в статье Парсинг XML в JavaScript на примере XML-погоды от gismeteo.ru мы написали длинный (в нескольких местах запутанный и непонятный) скрипт на JavaScript, который радостно преобразовывал XML-Данные от ГИС-метео в HTML-формат, который мы и отображали в нашем браузере.
Этот вариант имел ряд недостатков:
1) При отключенном JavaScript в браузере пользователя мы вообще ничего не увидим.
2) Шаблоны, используемые в этом скрипте были настолько запутанные, что иногда и я сам терялся в том, что значит каждый из тегов этого шаблона.
3) И вообще это не модно и несовременно!
Ведь есть технология лучше: XML+XSLT !
Вот выдержка из wikipedia:
XSLT (Extensible Stylesheet Language Transformations) — часть спецификации XSL, задающая язык преобразований XML-документов. Спецификация XSLT является рекомендацией W3C.
При применении таблицы стилей XSLT, состоящей из набора шаблонов, к XML-документу (исходное дерево) образуется конечное дерево, которое может быть другой XML-структурой, HTML-документом или обычным текстом. Правила выбора (и, отчасти, преобразования) данных из исходного дерева пишутся на языке запросов XPath.
XSLT имеет множество различных применений, в основном в области web-программирования и генерации отчётов. Одной из задач, решаемых языком XSLT, является отделение данных от их представления, как часть общей парадигмы MVC (англ. Model-view-controller). Другой стандартной задачей является преобразование XML-документов из одной XML-схемы в другую.
В общем, XSLT – это тоже XML особого вида, главной целью которого является преобразование XML-данных из одного вида в другой.
Собственно, эта статья подразумевается именно как практическое введение в XSLT, а поэтому я сразу приведу результирующий XSLT-шаблон, а затем буду его построчно объяснять. Вот он.
<?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"> <xsl:output method="xml" indent="yes" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/> <!--Шаблон, преобразующий номер дня недели в его текстовое представление--> <xsl:template name="get-day-of-the-week-abbreviation"> <xsl:param name="day-of-the-week"/> <xsl:choose> <xsl:when test="$day-of-the-week = 1">Вс</xsl:when> <xsl:when test="$day-of-the-week = 2">Пн</xsl:when> <xsl:when test="$day-of-the-week = 3">Вт</xsl:when> <xsl:when test="$day-of-the-week = 4">Ср</xsl:when> <xsl:when test="$day-of-the-week = 5">Чт</xsl:when> <xsl:when test="$day-of-the-week = 6">Пт</xsl:when> <xsl:when test="$day-of-the-week = 7">Сб</xsl:when> <xsl:otherwise>?</xsl:otherwise> </xsl:choose> </xsl:template> <!--Шаблон, преобразующий порядковый номер месяца в его текстовое представление--> <xsl:template name="get-month-name"> <xsl:param name="month"/> <xsl:choose> <xsl:when test="$month = 1">янв</xsl:when> <xsl:when test="$month = 2">фев</xsl:when> <xsl:when test="$month = 3">мар</xsl:when> <xsl:when test="$month = 4">апр</xsl:when> <xsl:when test="$month = 5">май</xsl:when> <xsl:when test="$month = 6">июн</xsl:when> <xsl:when test="$month = 7">июл</xsl:when> <xsl:when test="$month = 8">авг</xsl:when> <xsl:when test="$month = 9">сен</xsl:when> <xsl:when test="$month = 10">окт</xsl:when> <xsl:when test="$month = 11">ноя</xsl:when> <xsl:when test="$month = 12">дек</xsl:when> <xsl:otherwise>?</xsl:otherwise> </xsl:choose> </xsl:template> <!--Шаблон, показывающий текстовое представление облачности--> <xsl:template name="get-cloudiness"> <xsl:param name="cloudiness"/> <xsl:choose> <xsl:when test="$cloudiness = 0">ясно</xsl:when> <xsl:when test="$cloudiness = 1">малооблачно</xsl:when> <xsl:when test="$cloudiness = 2">облачно</xsl:when> <xsl:when test="$cloudiness = 3">пасмурно</xsl:when> <xsl:otherwise>?</xsl:otherwise> </xsl:choose> </xsl:template> <!--Шаблон, показывающий текстовое представление атмосферных явлений--> <xsl:template name="get-precipitation"> <xsl:param name="precipitation"/> <xsl:choose> <xsl:when test="$precipitation = 4">дождь</xsl:when> <xsl:when test="$precipitation = 5">ливень</xsl:when> <xsl:when test="$precipitation = 6">снег</xsl:when> <xsl:when test="$precipitation = 7">снег</xsl:when> <xsl:when test="$precipitation = 8">гроза</xsl:when> <xsl:when test="$precipitation = 10">без осадков</xsl:when> <xsl:otherwise>?</xsl:otherwise> </xsl:choose> </xsl:template> <!--Корневой шаблн результирующей страницы--> <xsl:template match="/"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>gis meteo informer</title> <style type="text/css"></style> </head> <body> <!--Здесь мы выбираем только самый первый(ближайший) прогноз под номером 1 --> <xsl:apply-templates select="MMWEATHER/*/TOWN/FORECAST[1]"/> </body> </html> </xsl:template> <!--Базовый шаблон, отображающий информер--> <xsl:template match="MMWEATHER/*/TOWN/FORECAST"> <div id="informer0"> <table cellspacing="0" cellpadding="1" width="100%" border="0" id="gmtbl5"> <tr> <td width="100%" colspan="3"> <table cellspacing="0" cellpadding="0" width="100%"> <tr> <td height="20" width="100%" id="gmtdttl5" colspan="3"> <b><a target="_blank" id="tgmtdttl5" href="http://www.gismeteo.RU/city/daily/4368">Москва</a></b> </td> </tr> </table> </td> </tr> <tr> <td width="15%"> <!--Здесь вставляем шаблон, отображающий атмосферные явления--> <xsl:apply-templates select="PHENOMENA"/> </td> <td width="85%" id="tgmtdtext50"> <xsl:value-of select="@day"/> <!--Далее идет вызов шаблонов, отображающих дату в удобном формате--> <xsl:call-template name="get-month-name"> <xsl:with-param name="month" select="@month" /> </xsl:call-template> - <xsl:call-template name="get-day-of-the-week-abbreviation"> <xsl:with-param name="day-of-the-week" select="@weekday" /> </xsl:call-template><br/> <!--Здесь вставляем шаблон, отображающий температуру--> <b><xsl:apply-templates select="TEMPERATURE"/></b><br/> <a target="_blank" id="lgmtdtext50" href="http://www.gismeteo.RU"> GISMETEO.RU</a> </td> </tr> <tr> <td colspan="3" heigth="5"/> </tr> </table> </div> </xsl:template> <!--Шаблон, отображающий температуру--> <xsl:template match="TEMPERATURE"> <xsl:value-of select="@min"/>..<xsl:value-of select="@max"/> °C </xsl:template> <!--Шаблон, отображающий атмосферные явления--> <xsl:template match="PHENOMENA"> <xsl:element name="img"> <xsl:attribute name="height">60</xsl:attribute> <xsl:attribute name="width">59</xsl:attribute> <xsl:attribute name="alt"> <xsl:call-template name="get-cloudiness"> <xsl:with-param name="cloudiness" select="@cloudiness" /> </xsl:call-template>, <xsl:call-template name="get-precipitation"> <xsl:with-param name="precipitation" select="@precipitation" /> </xsl:call-template> </xsl:attribute> <xsl:attribute name="src">http://informer.gismeteo.ru/getcode/html/images/animbg/<xsl:value-of select="@cloudiness"/>.gif</xsl:attribute> </xsl:element> </xsl:template> </xsl:stylesheet>
Собственно, строки 1 и 3 – стандартные заголовки для XML-файла. Замечу лишь, что мы используем версию XSLT 1.0. Есть еще и 2.0 версия, но о ней мы поговорим в следующих статьях.
Строка 4 говорит, что результирующий вывод будет HTML.
Строки 7 и 19 задают именованный шаблон get-day-of-the-week-abbreviation, который в будущем мы будем использовать как функцию преобразования номера дня недели в его строковое представление. В строке 8 задается входно параметр day-of-the-week этого шаблона, нечто вродеаргумента функции. Это собственно сам номер дня недели.
В строках 9 и 18 объявляется секция <xsl:choose>, которая, тестируя некторое условие, вставляет в зависимости от результатов тестирования булева выражения соответствующую строку. Сами проверки заключены в теги <xsl:when></xsl:when> где само тестируемое условие задано аттрибутом test
Собственно, все вплоть до строки 65 – это вспомогательные шаблоны преобразований кодов в их текстовое представление, думаю, что в особых комментариях эти шаблоны не нуждаются.
Строки 68-80, это корневой шаблон, то есть тот шаблон, который будет вызван один раз для корневого элемента исходного XML-файла. Как мы видим, это просто вполне стандартный заголовок HTML-файла. Элемент(ы), для которого(которых) шаблон сработает, задается в атрибуте match шаблона. В нашем случае это “/”. Вообще селекторы (то есть то, что расположено в атрибуте match) пишутся на языке XPath, прочитать про основы которого можно в Википедии, вот здесь. Сам контент результирующей страницы вставляется между тегами <body></body> при помощи конструкции apply-templates.
В строках 83-120 задается базовый шаблон, в котором, собственно можно видеть всю разметку информера. Замечу только, что атрибут atname текущего элемента вставляется в результирующий документ с помощью конструкции <xsl:value-of select=“@atname”/>, как в строке 103, например.
Вызов именованного шаблона осуществляется при помощи такой разметки:
<xsl:call-template name="get-month-name"> <xsl:with-param name="month" select="@month" /> </xsl:call-template>
Как видно, атрибутом name тега xsl:call-template задается имя вызываемого шаблона (помните, мы объявляли их в начале файла?), а внутри секции call-template при помощи тегов xsl:with-param задаются сами подаваемые в шаблон параметры.
А вот еще одна маленькая хитрость. Конструкция:
<xsl:element name="img"> <xsl:attribute name="height">60</xsl:attribute> <xsl:attribute name="width">59</xsl:attribute> </xsl:element>
Она позволяет вставить в результирующий документ элемент IMG, с атрибутами width и height, да и в принципе, любой другой элемент, с любыми другими атрибутами. В данном примере будет вставлен элемент <img width=”59″ height=”60″/>
И чуть не забыл! В самом XML-файле необходимо указать шаблон, посредством которого он будет обрабатываться. Это нужно только если вы собираетесь доверить XSLT-парсинг самому браузеру, в котором вы откроете XML-файл. О других методах парсинга расскажу в следующих статьях.
Вот, собственно и все, что я хотел рассказать.
Ссылка на результат работы здесь.
Ссылка на архив с работающим примером – здесь.
Парсинг XML в ActionScript 3.0
Возникла у меня однажды задача – создать Flash-контрол, в котором постоянно сверху вниз прокручивается список неких сайтов, причем при наведении мыши на этот контрол прокручивание останавливается, а содержимое пункта списка, на который наведена мышь, разворачивается, и мы теперь можем наблюдать саму ссылку на сайт и краткое описание сайта внизу. Как-то так:
Собственно, хотелось создать универсальный контрол, такой, чтобы и список сайтов и все цвета, и скорость прокрутки, и вообще все изменяемые параметры хранились бы где-то отдельно от самого Flash-контрола, чтобы, когда дизайнеру захочется поменять оформление этого котнрола или его содержимое, он бы меня не дергал лишний раз. Разумное желание. И решил я остановиться на хранении всех этих данных в XML-файле.
Файл этот имеет вот такой формат:
<?xml version="1.0" encoding="UTF-8"?> <config> <control speed="10" indent="24.9"/> <sites> <site name="веб-разработка" link="easy-4-web.ru" url="http://easy-4-web.ru/" descr="веб-дизайнер и веб-программист срывают оковы, освещают темные места" height="38"/> <site name="Яндекс" link="yandex.ru" url="http://yandex.ru/" descr=" Поиск от Яндекс. Найдется все!" height="38"/> <site name="почта от google" link="gmail.com" url="http://gmail.com/" descr="Бесплатная почта от google. Попробуй, не пожалеешь." height="38"/> </sites> </config>
Здесь мы видим один корневой элемент <config> в который вложены: элемент <control> одержащий в себе атрибуты, касающиеся всего контрола в целом, и элемент <sites> содержащий в себе дочерние узлы <site>, каждый из которых описывает отдельный элемент прокручиваемого в контроле списка.
Осталось теперь разобраться как разобрать этот файл при помощи ActionScript.
Но для начала структурируем немного в виде классов информацию, хранящуюся в XML-файле.
Элемент <site> мы опишем следующим классом (файл SiteItem.as):
package inc{ public class SiteItem extends Object { public var pName:String; public var pLink:String; public var pURL:String; public var pDescr:String; public var pHeight:Number; public function SiteItem(p_Name:String, p_Link:String, p_URL:String, p_Descr:String, p_Height:Number){ pName=p_Name; pLink=p_Link; pURL=p_URL; pDescr=p_Descr; pHeight=p_Height; } } }
Как видно, это просто класс с открытыми полями и одним конструктором. Ничего сложного.
А вот еще один класс, описывающий весь XML-файл (ScrollerParameters.as):
package inc{ public class ScrollerParameters extends Object{ public var list:Array; public var indent:Number; public var speed:Number; public function ScrollerParameters(){ list=new Array(); } } }
Здесь также есть набор открытых полей и конструктор.
А вот и сам скрипт разбора XML-данных (scrollrequest.as).
package inc{ import flash.display.MovieClip; import flash.net.URLRequest; import flash.net.URLLoader; import flash.events.*; import flash.net.URLLoaderDataFormat; public class scrollrequest extends MovieClip { private var xml:XML; public var parameters:ScrollerParameters=new ScrollerParameters(); public function scrollrequest(url:String) { var loader:URLLoader=new URLLoader(); loader.dataFormat = URLLoaderDataFormat.TEXT; loader.addEventListener(Event.COMPLETE, loadXML); loader.load(new URLRequest(url)); } private function loadXML(e:Event):void { try { xml=new XML(e.target.data); parseXML(); } catch(e:TypeError) { trace( "Could not parse text into XML" ); trace( e.message ); } } private function parseXML(){ var control:XML=xml["control"][0]; parameters.speed=control.attribute("speed"); parameters.indent=control.attribute("indent"); var sites:XMLList=xml["sites"][0].child("site"); for(var i:Number=0; i<sites.length(); i++){ var site=sites[i]; var s=new SiteItem(site.attribute("name"), site.attribute("link"), site.attribute("url"), site.attribute("descr"), site.attribute("height")); parameters.list.push(s); } notifyListeners("LOAD"); } private function notifyListeners(ev:String) { var e:Event = new Event(ev, false, false); dispatchEvent(e); } } }
Как можно заметить, загрузка XML-файла происходит в конструкторе класса scrollrequest, в принципе, загрузку файла я использую лишь один раз в жизненном цикле этого класса, а потому не стал делать отдельный метод для загрузки файла с сервера.
Для загрузки XML-файла с сервера используется стандартная схема загрузки при помощи класса URLLoader.
Обработчик loadXML срабатывает после полной загрузки файла с сервера и вызывает метод parseXML(), который, собственно, и осуществляет разбор XML-Данных.
Чтобы получить список всех узлов с именем control мы используем оператор “квадратные скобки – “xml[“control”], а чтобы получить единственный узел с таким именем нужмно использовать кщк один оператор “квадратные скобки”, чтобы обратиться к первому и единственному элементу в списке узлов. То есть вот так xml[“control”][0].
Обращение к конкртеному атрибуту узла происходит посредством метода attribute(‘par’), которому в качестве параметра передается имя атрибута.
Чтобы получить список всех дочерних элементов узла, применяется метод child(‘par’), которому в качестве параметра передается имя дочерних узлов, которые мы хотим увидеть в списке. То есть вот так xml[“sites”][0].child(“site”) мы получим массив всех эелементов <site> у которых родителем является элемент <site>.
Пробег по всем элементам списка осущетсвляется обычным циклом for.
Вот и все, что я хотел сегодня рассказать.