Парсинг 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.
Вот и все, что я хотел сегодня рассказать.