Как стать автором
Обновить

XML-классы в ActionScript (Adobe Flex)

Когда я только начинал работать с Flex, одной из первых задач была загрузка XML-документа по HTTP-протоколу.
Для работы с HTTP в ActionScript этого предназначен класс HTTPService, в котором одним из основных оказалось загадочное (для меня тогда) свойство resultFormat, которое и определяло формат загруженных данных.

Вот как в документации описаны возможные значения этого свойства:
  • object Данные загружаются как XML и преобразуется в дерево объектов ActionScript.
  • array Данные загружаются как XML и преобразуется в дерево объектов ActionScript, которое загружается в массив
  • xml Данные загружаются как XML и преобразуется в XML как объект типа XMLNode.
  • flashvars Данные загружаются в виде пар name=value, разделенных амперсандом, и преобразуется в объект ActionScript.
  • text Данные загружаются как текст, без преобразования.
  • e4x Данные загружаются как XML и преобразуются в тип ActionScript XML, который можно обрабатывать при помощи E4X (EcmaScript for XML).

XML упоминается в четырех вариантах из шести, причем как явные xml-типы упоминаются два — XMLNode и XML. Какой следует выбрать?

Правильный ответ (скажем так, не правильный, а в большинстве случаев оптимальный) — это e4x, а совсем не xml, как можно было подумать (и как, кстати, я и решил сначала).

Связано это с тем, что в ActionScript/Flex существует два подхода к работе с XML-данными: один — используя классы из пакета flash.xml (именно данные такого типа и вернет HTTPService, если указать 'xml' в свойстве resultFormat), второй — используя встроенные (начиная с ActionScript 3.0) классы XML и связанный с ним класс XMLList (а для такой работы надо указать e4x).

Дополнительной путаницы добавляет то, что в ActionScript 2.0 класс XMLNode назывался XML, а в 3.0 его переименовали, а XML – это уже совершеннго другой класс.
Классы XMLDocument, XMLNode, XMLType в ActionScript 3.0 оставлены для обратной совместимости с версией 2.0 языка (довольно странная обратная совместимость, кстати — с переименованием типов). Классы реализуют стандартный механизм DOM, то есть все элементы XMLNode имеют стандартные методы наподобие appendChild, childNodes, nodeName, nodeType и т.д.

Значительно более удобен механизм E4X (EcmaScript for XML), появившийся в новой версии ActionScript 3.0. Данный интерфейс реализуют классы XML и связанный с ним XMLList.

Значительным преимуществом класса XML является то, что он является одним из базовых типов языка, то есть XML-данные можно вставлять в исходный без всякого преобразования. Например, можно объявить переменную и присвоить ей значение:

var x:XML = value of tag
;

или непосредственно передать XML в функцию:

function process(what:XML):void
….
process(text);

Обращаю внимание, что XML передается не как строки (String), а именно как XML-данные.

Еще одним огромным преимуществом является уже упомянутый E4X, который позволяет реализовывать весьма сложные выборки из XML-данных довольно простыми запросами.

Для примера сравним работу с одними и теми же данными (данные взяты из ActionScript language reference) при использовании XMLNode/XMLDocument и XML.
Вот данные, которые мы обрабатываем:

/>
/>
/>
/>
/>
/>


Предположим, нам надо извлечь из него все названия книг (аттрибут name тэга book) и поместить в массив list.
Вот реализация данного с использованием XMLNode и XMLDocument:

var x:XMLDocument = new XMLDocument;
x.parseXML(''+
'/>'+
'/>'+
'/>'+
'/>'+
'/>'+
'/>'+
'');
var list:Array = new Array;
for each(var s:XMLNode in x.childNodes[0].childNodes)
{
list.push(s.attributes.name);
}


Неудобства: 1)XML загружается как строка и потом парсится. Дополнительное время на обработку (конечно, не всегда актуально — в большинстве случаев XML-документ и так разбирается из полученной откуда-то строки), общее неудобство; 2)используются громоздкие конструкции типа .childNodes[0].childNodes. Здесь задача довольно простая, но легко представить, в какие монстрообразные конструкции это может развиться в случае более-менее сложных разветвленных данных.

Теперь реализаци того же на XML/ XMLList:

var xml:XML = />
/>
/>
/>
/>
/>
;
var list:Array = new Array;
for each(var bookName:String in xml.book.@name)
{
list.push(bookName);
}

Подход более удобен при программировании: XML задается непосредственно в исходном коде, для доступа к полям используются легкие конструкции E4X. E4X вообще довольно комфортный для работы язык, например, «получить значение аттрибута index для тэга item, у которого атрибут name равен строке s, а тэг является дочерним элементом корня XML-документа», описывается так: xml.item.(@name==s).@index

Исходя из рассмотренного, можно дать рекомендацию начинающим Flex-программистам: основное правило при работе с XML в ActionScript – это избегать использования классов XMLNode, XMLDocument и вообще пакета flash.xml (достаточно помнить о том, что это классы, оставленные для обратной совместимости с ActionScript 2.0) и изучить E4X, благо он используется не только в ActionScript, но и в других популярных проектах (http://en.wikipedia.org/wiki/ECMAScript_for_XML).

Список использованных ресурсов:
1. Adobe Language Reference
2. EcmaScript for XML
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.