E4X – это новый подход (спецификация ECMAScript)
к работе с XML данными, который был интегрирован в ActionScript 3.
Класс XML по умолчанию использует эту реализацию применительно ко всем
более ранним XML классам. Прежний XML класс в ActionScript 3 был
переименован в XMLDocument (flash.xml.XMLDocument). Прежний класс XMLNode также называется XMLNode (flash.xml.XMLNode).
E4X предоставляет более простой, более интуитивный метод доступа к
содержимому XML файла, используя синтаксис точки. Вместо прохождения
циклом по всем дочерним узлам внутри XML файла, можно ссылаться на
элементы по имени, и даже фильтровать узлы с использованием простых
условий. Кроме того, XML теперь может быть записан внутри ActionScript. // XML writtin inline in ActionScript 3 // no quote characters needed var xml:XML = <inline> <example /> </inline>;
Это
делает XML файл более простым в использовании при внедрении в
ActionScript, так как теперь не нужно записывать его в виде непрерывной
строки.
Существуют два основных высокоуровневых класса ActionScript, которые флеш использует для работы с E4X XML; это XML ( XML) и XMLList ( XMLList).
Экземпляры XML содержат один корневой узел, который может состоять из
любого числа узлов потомков. Экземпляры XMLList являются набором или
списком экземпляров XML или узлов XML. Для
любого экземпляра XML можно дать ссылку на XMLList его потомка,
используя метод children(), который схож со свойством childNodes внутри
старшей модели XML. E4X предоставляет дополнительную опцию, позволяющую
ссылаться на потомка по его имени. Вместо того чтобы получить всех
потомков XML узла, вы можете получить XMLList потомков узла с заданным
именем, просто воспользовавшись этим именем в качестве свойства
экземпляра XML с помощью оператора точки (.) (средство доступа к
потомку).
// Child elements accessible as // properties of XML instance var sport:XML = <sport> <name>Basketball</name> <players>men</players> <players>women</players> <nationalTV>NBC</nationalTV> <nationalTV>ESPN</nationalTV> </sport>;
trace(sport.players is XMLList); // true trace(sport.players); /* output: <players>men</players> <players>women</players> */
При
ссылке на players из sport XML возвращается XMLList всех
элементов-потомков с именем players. Если вы потом захотите получить
доступ к первому узлу этого списка, то вам понадобиться войти в него
через players XMLList с помощью оператора доступа к массиву ([]) и
индекса элемента, так как вы будете внутри массива.
// Child elements accessible as // properties of XML instance var sport:XML = <sport> <name>Basketball</name> <players>men</players> <players>women</players> <nationalTV>NBC</nationalTV> <nationalTV>ESPN</nationalTV> </sport>;
trace(sport.players[0] is XML); // true trace(sport.players[0]); // traces "men"
Обратите
внимание, что вывод trace показывает текстовый узел внутри первого узла
players списка XMLList. Даже хотя элемент players является реальной
ссылкой для sport.players[0], вывод trace по умолчанию (toString())
фактически является текстовым содержимым этого элемента. Если вы хотите
увидеть полный XML элемент, то вам нужно будет использовать
XML.toXMLString().
// Show XML source string using toXMLString() // default value (toString()) just shows text var sport:XML = <sport> <name>Basketball</name> <players>men</players> <players>women</players> <nationalTV>NBC</nationalTV> <nationalTV>ESPN</nationalTV> </sport>;
trace(sport.players[0].toString()); // traces "men" trace(sport.players[0].toXMLString()); // traces "<players>men</players>"
Примечание: XML.text() XML.text() возвращает текстовое содержимое XML элемента и похож на значение строки по умолчанию (toString()) этого узла.
Подобно
точке - оператору доступа к потомку, E4X представляет похожий оператор
доступа к наследникам для доступа к наследникам, или потомкам и всем
потомкам потомка. Он имеет форму двойной точки, используемой в
выражении (..), за которым идет имя узлов наследуемого элемента,
которое вы хотите, чтобы было возвращено в XMLList. // Child (.) vs. descendant (..) access var channel:XML = <channel> <title>Feed Title</title> <description>Feed description.</description> <item> <title>Item 1 Title</title> <description>Item 1 description.</description> </item> <item> <title>Item 2 Title</title> <description>Item 2 description.</description> </item> </channel>
trace(channel.title.toXMLString()); // traces "<title>Feed Title</title>" trace(channel..title.toXMLString()); /* output <title>Feed Title</title> <title>Item 1 Title</title> <title>Item 2 Title</title> */ Вы
можете заметить, что при использовании доступа к потомку возвращаются
только те элементы, которые находятся на первом уровне иерархии под
целевым элементом (здесь это channel). При доступе к наследнику
возвращаются все именованные соответствующим образом элементы,
расположенные под целевым элементом. Получить
доступ к атрибутам XML можно также через синтаксис точки. Для
разграничения имен элементов от имен атрибутов у атрибутов имеется
оператор идентификации атрибута (@), стоящий перед именем атрибута.
// Access attributes with the @ // attribute identifier operator var item:XML = <item name="attribute"> <name>element</name> </item>;
trace(item.name); // traces "element" trace(item.@name); // traces "attribute"
Атрибуты (которые формально также являются узлами) могут также возвращаться в списке XMLList.
// Attributes as an XMLList var images:XML = <images> <img href="image1.jpg" /> <img href="image2.jpg" /> <img href="image3.jpg" /> </images>;
trace(images.img.@href is XMLList); // traces true trace(images.img.@href); // traces "image1.jpgimage2.jpgimage3.jpg" trace(images.img.@href[0]); // traces "image1.jpg"
Поскольку
вы можете ссылаться на элементы (и атрибуты) по имени, используя с E4X
XML синтаксис точки, вероятнее всего произойдет конфликт между именами
XML узла и реальными свойствами внутри экземпляра XML в ActionScript.
Чтобы предотвратить появление конфликта, вместо свойств XML класса
используются методы. Как вы могли уже заметить, прежнее свойство
childNodes теперь является методом children(). При использовании метода
у вас не возникнет конфликта при наличии XML с элементами имени
потомков. Другой пример – это метод name(), возвращающий имя узла XML
элемента.
// XML node access vs method access var family:XML = <family> <name>Hendersons</name> </family>;
trace(family.name); // traces "Hendersons" trace(family.name()); // traces "family"
Иногда
может случиться так, что в XML файле имеются имена элементов, которые
не являются правильными именами переменных для ActionScript. В этом
случае вам потребуется использовать метод XML.elements(), позволяющий
получить доступ к элементам по имени с использованием строки. Для
атрибутов существует похожий метод XML.attribute().
// Reference nodes by name using // elements() and attribute() var values:XML = <values for-example="see below"> <complex-name>simple value</complex-name> </values>;
// trace(values.@for-example); // Syntax error trace(values.attribute("for-example")); // traces "see below" // trace(values.complex-name); // Syntax error trace(values.elements("complex-name")); // traces "simple value"
Для
элементов-потомков использование оператора доступа к массиву ([]) по
большому счету будет работать так же, как метод элемента.
Условное фильтрованиеСсылаясь на
элементы-потомки, из экземпляра XML или XMLList по имени, фактически,
вы фильтруете узлы потомка по имени. Вы также можете фильтровать
XMLList, используя простые условия. Эти условия следуют через точку (.)
за ссылкой на узел и условием внутри фильтрующего логического оператора
(()), где условие может использоваться для дальнейшего фильтрования
списка XMLList. Примечание: Фильтрование не для потомков Хотя
точка используется для доступа к фильтрующему логическому оператору,
это не означает, что вы получаете доступ к потомку фильтруемого списка
XMLList. Фильтрующий логический оператор фильтрует экземпляр,
применительно к которому он используется, наподобие того, как метод
slice() удаляет элементы экземпляра Array.
Просмотрите следующий код XML var grades:XML = <grades> <student> <name>Tom</name> <quiz num="1"><score>60</score></quiz> <quiz num="2"><score>90</score></quiz> </student> <student> <name>Brett</name> <quiz num="1"><score>100</score></quiz> </student> <student> <name>Michelle</name> <quiz num="1"><score>90</score></quiz> </student> </grades>; Следующие выражения используют условное фильтрование, чтобы отследить результаты из этого кода XML. // Find students with the name Michelle trace(grades.student.(name == "Michelle")); /* output: <student> <name>Michelle</name> <quiz num="1"> <score>90</score> </quiz> </student> */ Здесь
фильтр используется на списке XMLList, созданном с помощью
grades.student. Здесь содержится список элементов с именем student,
который существует внутри файла grades XML. Внутри этого списка фильтр
находит все узлы student, где ссылающееся имя из этого узла принимает
значение "Michelle". В итоге, получаем один узел student, где, как вы
можете наблюдать, элемент name содержит текст "Michelle".
// Find quizes whose num attribute equals 1 trace(grades.student.quiz.(@num == "1")); /* output: <quiz num="1"> <score>100</score> </quiz> <quiz num="1"> <score>60</score> </quiz> <quiz num="1"> <score>90</score> </quiz> */ Этот
пример, наоборот, фильтрует контрольные элементы внутри
grades.students. он ищет контрольные элементы с числовым атрибутом,
значение которого равно 1. Так как фильтр используется со ссылкой
только на контрольные элементы, то будут возвращены только контрольные
элементы.
// Find students who are not Michelle that // have less than 2 quiz elements trace(grades.student.(name != "Michelle" && quiz.length() < 2)); /* output: <student> <name>Brett</name> <quiz num="1"> <score>100</score> </quiz> </student> */
Условие
в данном фильтре состоит из двух частей. Одна отвечает за то, что имя
студента не Michelle, а другая требует того, чтобы студент имел менее
двух контрольных элементов. Этот фильтр возвращает только элемент
student с именем Brett.
// Find students with a single score // element having a value of 90 trace(grades.student.(quiz.score == 90)); /* output <student> <name>Michelle</name> <quiz num="1"> <score>90</score> </quiz> </student> */
Как
вы уже заметили, у вас есть возможность перемещаться вниз по иерархии
внутри диапазона условия, что возвращает элементы student со значением
quiz.score, равным 90. Хотя элемент student с именем Tom также обладает
элементом score со счетом 90, он не попадает в этот фильтр, так как
quiz.score определяется как XMLList с двумя элементами, чье значение
несопоставимо с 90. Фильтр работает для Michelle, потому что элемент
quiz у этого элемента student имеет один узел score, чье значение равно
90. Когда это значение определено для условия, оно рассматривается как
значение, равное 90, а условие может быть установлено в true.
// Find students with any score // element that has a value of 90 trace(grades.student.(quiz.(score == 90).length())); /* output <student> <name>Tom</name> <quiz num="1"> <score>60</score> </quiz> <quiz num="2"> <score>90</score> </quiz> </student> <student> <name>Michelle</name> <quiz num="1"> <score>90</score> </quiz> </student> */
Этот
пример делает то, что не делал предыдущий пример; он находит всех
студентов, имеющих любой элемент score со значением 90. Это
осуществляется вложенным фильтром. Первый фильтр используется для того,
чтобы убедиться, что результаты были возвращены в набор элементов
student. Внутри этого фильтра имеется другой фильтр, используемый с
контрольным XMLList, который фильтрует этот список по элементам score,
чьи значения равны 90. Если внутри этого контрольного элемента
существует какой-либо score со значением 90, фильтр выведет результат в
контрольном XMLList с одним или более элементами, означая, что length()
будет возвращать 1 или больше, которая в оригинальном фильтре элемента
student означает условие, равное true. Узлы элемента student Tom и
Michelle имеют элемент score со значением 90, означая, что quiz.(score
== 90) создает XMLList с длиной равной 1 для каждого из них (содержащей
соответствующий элемент score). Эти узлы затем добавляются в XMLList,
поступая из фильтра элемента student.
В
любом фильтре у вас есть опция использования буквенных значений
(использовалась в примерах far) наряду с переменными ActionScript, так
как имя переменной не совпадает с именем элемента внутри XMLList,
использованного в фильтре. // Find students with a single score // element having a value of scoreCheck var scoreCheck:int = 90; trace(grades.student.(quiz.score == scoreCheck)); /* output <student> <name>Michelle</name> <quiz num="1"> <score>90</score> </quiz> </student> */
Этот
фильтр эквивалентен использованию выражения (quiz.score == 90),
предполагая, что grades.student не имеет элементов-потомков с именем
scoreCheck.
Каждое условие фильтра фактически сводиться к:
var result:XMLList = new XMLList(); for each (var node:XML in target) { with (node) { if (condition) { result += node; } } } return result;
Где
target является списком XMLList, с которым используется фильтр,
condition – это условие внутри фильтра, а result – это получающийся
XMLList после использования фильтра (result = target.(condition)).
Любая неузловая ссылка внутри условия фильтра будет передаваться
соответствующему определенному значению переменной в ActionScript (если
такое значение существует).
|