Март 2011

Руководство по actionscript. часть 3, стр. 053

Для обращения к атрибутам или элементам, имена которых содержат символы, считающиеся недопустимыми в идентификаторах языка ActionScript, вместо оператора «потомок» необходимо использовать метод экземпляра descendant^ ) класса XML. Оператор «потомок» не позволяет использовать запись вида элемент..["некоеИмя"].

Оператор «потомок» полезен сам по себе, однако при использовании возможностей фильтрации расширения Е4Х он становится просто незаменимым. Как только вы разберетесь с оператором «потомок» и возможностями фильтрации расширения Е4Х, сможете быстро и легко выполнять практически любую обработку данных в формате XML. Мы рассмотрим это в следующем разделе.

Фильтрация данных XML

Оператор фильтрующего предиката расширения Е4Х — это простой, но очень мощный инструмент поиска. Он может принимать любой объект XMLList и возвращать подмножество элементов из этого списка в соответствии с указанным условием.

Шу_ Термин «предикат» заимствован из спецификации языка XPath консорциума W3C. Более подробную информацию можно найти по адресу http://www. w3.org/TR/xpath20/#id-— predicates.

Оператор фильтрующего предиката записывается в следующем обобщенном виде:

объектХМИist. (условноеВыражение)

Для каждого элемента в объекте объектХМШ5Ь выражение условноеВыражение выполняется один раз. Если для элемента выражение условноеВыражение возвращает значение true, этот элемент добавляется в объект XMLList, который возвращается после обработки всех элементов. Стоит отметить, что при каждом выполнении выражения условноеВыражение текущий элемент временно добавляется в начало цепочки областей видимости, позволяя внутри выражения непосредственно обращаться к его потомкам и атрибутам по имени.

Использовать оператор фильтрующего предиката чрезвычайно просто. Рассмотрим новый XML-фрагмент и выполним фильтрацию. В листинге 18.12 новый фрагмент представляет список сотрудников компании.

Листинг 18.12. Список сотрудников

var staff:XML = EMPLOYEE ID=»501″ HIRED=» 1090728000000″> Marco Crawley James Porter 25000 Designer



Graham Barton

James Porter

35000

Designer

James Porter Dori an Schapi ro 55000 Manager

Теперь выполним нашу первую операцию по фильтрации данных: предположим, что мы хотим получить список сотрудников, которыми руководит James Porter. Мы можем отфильтровать список элементов из листинга 18.12 следующим образом:

// Сначала получаем объект XMLList. представляющий все элементы var all Employees:XMLList = staff.*;

// Теперь фильтруем список элементов

var employeesUnderJames:XMLList = all Employees.(MANAGER == «James Porter»);

Выражение a llEmployees. (MANAGER == «James Porter») возвращает объект XMLList, включающий все элементы из фрагмента a llEmployees, у которых элемент содержит текст «James Porter». Вам должна понравиться простота и читабельность кода расширения Е4Х. Просто помните, что предыдущая строка кода работает потому, что каждый раз при выполнении выражения (MANAGER == «James Porter») проверяемый элемент из фрагмента allEmployees добавляется в цепочку областей видимости. Таким образом, выполняемое выражение (MANAGER == «James Porter») имеет следующее концептуальное значение, записанное в псевдокоде:

if (текущийСотрудник. MANAGER == «James Porter») // добавить текущийСотрудник в список результатов

Для сравнения приведем реальный код на языке ActionScript, который делает то же самое, что и выражение allEmployees. (MANAGER == «James Porter»):

var resultList:XMLList = new XMLList( ): var counter:int = 0:

for each (var employee:XML in allEmployees) { if (employee. MANAGER == «James Porter») { resultList[counter] = employee: counter++;

}

}

Рассмотрим еще несколько примеров, которые демонстрируют, как можно обращаться к информации из листинга 18.12, основываясь на множестве условий. Следующее выражение возвращает список сотрудников, зарплата которых меньше либо равна $35 ООО.

Руководство по actionscript. часть 3, стр. 054

Staff.*.(SALARY <= 35000)

Следующее выражение возвращает список сотрудников с зарплатой от $35 ООО до 50 ООО:

staff.*.(SALARY >= 35000 && SALARY <= 50000)

Это выражение возвращает список дизайнеров, работающих в компании:

staff.*.(POSITION == «Designer»)

Следующее выражение возвращает список сотрудников с идентификационным номером 238 (так получилось, что в этом примере только один сотрудник с указанным номером, но данный элемент все равно помещается в экземпляр класса XMLList).

staff.*.(@ID == «238″)

Следующий код получает список сотрудников, которые работают в компании с 2004 года (для представления времени мы используем стандартный формат «мил-лисекунды-с-1970-года», применяемый в классе Date):

staff.*.(©HIRED >= 1072933200000 && ©HIRED <= 1104555600000)

Наконец, мы выводим дату, когда был нанят сотрудник Graham:

// В часовом поясе стандартного восточного времени будет отображено: // Fri Mar 5 00:00:00 GMT-0500 2004

trace(new Date(Number(staff.*.(NAME == «Graham Barton»).©HIRED))); Забавно, не правда ли? Предикаты — это сильно!

Itsjjjfi Чтобы отфильтровать список, в котором не каждый элемент имеет заданный атрибут

L-1 или элемент-ребенка, мы должны использовать метод hasOwnProperty() для проверки

существования данного атрибута или ребенка перед применением фильтра. В противном случае возникнет ошибка обращения. Например, следующий код возвращает все элементы документа некийДокумент, у которых для атрибута color установлено значение «red»:

некийДокумент. .*.(hasOwnProperty(«@color») && ©color == «red»)

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

Руководство по actionscript. часть 3, стр. 055

Обход деревьев XML

В терминах программирования обход означает обращение к каждому узлу в структуре данных и его обработку. Обход дерева означает использование рекурсивного алгоритма для обхода узлов древовидной структуры.

В реализациях языка XML, основанных на модели DOM (например, унаследованный класс flash. xml. XMLDocument), для поиска информации программисты часто пишут собственный код, осуществляющий обход деревьев XML. Например, программа для работы с персоналом может включать код, который просматривает весь документ XML в поисках сотрудников с должностью «руководитель» или с зарплатой, находящейся в заданном интервале. Как мы уже видели в предыдущем разделе, такой пользовательский код для обхода деревьев почти не нужен в расширении Е4Х, поскольку большинство операций поиска могут быть выполнены с помощью операторов «потомок» и фильтрующего предиката расширения Е4Х. Однако бывают ситуации, в которых необходимо выполнить обход дерева даже в расширении Е4Х. К счастью, для этих целей код расширения Е4Х прост.

В расширении Е4Х мы можем использовать оператор «потомок» вместе с групповым символом свойств, чтобы получить объект XMLList, содержащий все узлы-потомки для данного элемента, как показано в следующем коде:

некийЭлемент. * II Возвращает список, содержащий все потомки // элемента некийЭлемент

Можно также использовать инструкцию for-each-in для перемещения по всем элементам объекта XMLList. Объединив эти методики вместе, мы легко обойдем любой узел в дереве XML, как показано в следующем коде:

for each (var ребенок:Ш. in некийЭлемент. *) { II обработка элемента ребенок…

}

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

var tempRoot:XML = ; tempRoot. appendChi16(некийЭлемент); for each (var ребенок\Ш. in tempRoot..*) { // Обработка элемента ребенок…

}

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

разметку HTML. Чтобы ответы соответствовали стандарту XHTML, мы хотим, чтобы все имена тегов, найденные в ответах пользователей, преобразовывались в нижний регистр. Вот пример ответа, который включает проблематичный верхний регистр и смешанные регистры в именах тегов:

var message:XML =

HEY1 I just wanted to say that your site is so cool!!

You should Visit mine sometime.

Руководство по actionscript. часть 3, стр. 056

:

Рассмотрим код для обхода дерева, который преобразует имена всех элементов и атрибутов из предыдущего XML-фрагмента в нижний регистр:

for each (var chi1d:XML in message..*) { // Если узел является элементом… if (child. nodeKind( ) == «element») { // …преобразуем его имя в нижний регистр, child. setName(child. named ).toString( ).toLowerCase( )): // Если узел имеет атрибуты, преобразуем их имена в нижний регистр, for each (var attribute:XML in child.@*) { attribute. setName(attribute. name( ).toString( ).toLowerCase( )):

}

}

}

Вот новый фрагмент XML, полученный в результате выполнения предыдущего кода, — все имена тегов и атрибутов преобразованы в нижний регистр.



HEY!I just wanted to say that your site is so cool!!

You should Visit mine sometime.



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

Изменение или создание нового содержимого XML

В расширении Е4Х наиболее распространенные операции добавления и изменения существующего экземпляра класса XML могут быть выполнены с помощью обычных операторов присваивания. Тем не менее результаты операторов присваивания расширения Е4Х отличаются и зависят от типа присваиваемого значения и типа целевого объекта присваивания. Рассмотрим различные сценарии по отдельности.

Изменение содержимого элемента

Чтобы изменить содержимое XML-элемента, мы присваиваем ему любое значение, не являющееся объектом XMLList или XML. Это значение преобразуется в строку и заменяет текущее содержимое элемента. Вспомним наш фрагмент :

var novel:XML =

Ulysses

Joyce, James

Penguin Books Ltd

Чтобы изменить содержимое элемента со строки «Ulysses» на строку «The Sun Also Rises», мы используем следующий код:

novel. TITLEC0] = «The Sun Also Rises»:

Однако не забывайте, что расширение Е4Х по возможности позволяет интерпретировать объект XMLList в виде объекта XML. Поскольку объект XMLList, возвращаемый выражением novel. TITLE, имеет один-единственный экземпляр класса XML, мы можем использовать следующий более удобный код:

novel. TITLE = «The Sun Also Rises»; // Опущено [0]

Однако если бы объект XMLList, возвращаемый выражением novel. TITLE, содержал несколько элементов, операция присваивания имела бы другой результат, описываемый далее, в подразд. «Присваивание значений объекту XMLList» разд. «Изменение или создание нового содержимого XML».

Руководство по actionscript. часть 3, стр. 057

Если вы хотите вспомнить отличие между выражением novel. TITLE[0] и novel. TITLE, обратитесь к подразд. «Интерпретация объекта XMLList как экземпляра класса XML» разд. «Обращение к данным XML».

Теперь также изменим имя автора и название издательства:

novel. AUTHOR = «Hemingway. Ernest»; novel. PUBLISHER = «Scribner»;

В качестве альтернативы содержимое элемента можно изменить с помощью метода экземпляра setChildren ( ) класса XML. Например:

novel. TITLE. setChi1dren(«The Sun Also Rises»);

Изменение значения атрибута

Чтобы изменить значение атрибута XML, просто присвойте атрибуту любое новое значение, используя оператор присваивания. Новое значение будет преобразовано в строку и заменит существующее значение атрибута. Например, следующий код изменяет значение атрибута ISBN со строки «0141182806″ на строку «0684800713″:

novel.0ISBN = «0684800713″;

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

Если присваиваемое атрибуту значение является объектом XMLLi s t, содержащим атрибуты, то значения атрибутов из этого объекта XMLList будут объединены в одну строку (в качестве разделителей используются пробелы), которая затем будет присвоена атрибуту. Это слегка необычное поведение может использоваться для объединения группы атрибутов в один атрибут. Например:

var books:XML =

;

var order:XML = ORDER ITEMS=»"/>; order. LITEMS = books.*.@ISBN;

// Выдает:

ORDER ITEMS=»0141182806 0684800713 0198711905″/>

Замена всего элемента

Чтобы заменить элемент XML новыми элементами, ему присваивается либо объект XMLList, либо объект XML. Например, в следующем коде элемент заменяет элемент :

var doc:XML = ООО

E4X is fun

:

doc. P = E4X is convenient;

// Выдает:

OIV>E4X is convenient

Содержимое элемента может также быть заменено с помощью метода экземпляра replace ( ) класса XML. Например:

// Тождественно: doc. P = E4X is convenient doc. replaceC’P», E4X is convenient);

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

var userl:XML = joe LinuxRules ;

var user2:XML = ken Default ;

Мы можем заменить элемент фрагмента user2 элементом фрагмента userl следующим образом:

user2.PASSWORD = userl. PASSWORD;

После замены два элемента будут иметь одинаковое содержимое:

trace(userl. PASSWORDS] == user2.PASSWORDS]); // Выводит: true

Но они ссылаются на разные экземпляры класса XML:

traceCuserl. PASSWORDS] === user2. PASSWORD^]); // Выводит: false

Получить информацию о различиях между двумя предыдущими выражениями равенства можно далее, в разд. «Определение равенства в расширении Е4Х».

Руководство по actionscript. часть 3, стр. 058

Добавление новых атрибутов и элементов

Мы можем добавлять новые атрибуты и элементы в документ, используя тот же синтаксис присваивания, который применяется для изменения и замены существующих атрибутов и элементов.

В расширении Е4Х, когда значение присваивается несуществующему атрибуту или элементу, среда выполнения Flash автоматически добавляет указанный атрибут или элемент в документ. В качестве примера создадим наш фрагмент * с нуля. Мы начнем с пустого элемента :

var novel:XML = ;

Затем добавим атрибут ISBN:

novel.@ISBN = «0141182806″;

Наконец, добавим элементы, и :

novel. TITLE = «Ulysses»;

novel. AUTHOR = «Joyce. James»;

novel. PUBLISHER = «Penguin Books Ltd»;

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



Ulysses

Joyce. James

Penguin Books Ltd

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



Dublin

Irel and

Для этого можно воспользоваться следующим кодом:

novel. SETTING. CITY = «Dublin»; novel. SETTING. COUNTRY = «Ireland»;

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

Ulysses Joyce. James Penguin Books Ltd Dublin Ireland

Мы можем использовать аналогичный подход, чтобы представить информацию о месте действия в одном элементе, имеющем следующий формат:



Для этого мы просто присваиваем желаемым атрибутам необходимые значения, как показано в следующем коде:

novel. SETTING.@CITY = «Dublin»; novel. SETTING.^COUNTRY = «Ireland»;

//Выдает:



Ulysses

Joyce. James

Penguin Books Ltd



В этом разделе мы узнали, что присваивание значения несуществующему элементу приводит к добавлению этого элемента в документ. Но что делать, если мы хотим добавить элемент с таким же именем, как имя существующего элемента? Например, как добавить несколько элементов к элементу? Ответы на этот вопрос вы найдете далее. По мере чтения следующих разделов обратите внимание на использование аддитивного оператора (+), который создает новый объект XMLList из набора экземпляров классов XML или XMLList. Аддитивный оператор принимает следующий вид:

ЭкземплярКлассаХМЫлиХМШ stl + ЭкземплярКлассаХМЫлиХМШ st2

Он возвращает новый экземпляр класса XMLList, содержащий объединенный список всех экземпляров класса XML из экземпляров ЭкземплярКлассаХМЫлиХМШstl и ЭкземплярКлассаХМЫлиХМШ st2.

Руководство по actionscript. часть 3, стр. 059

Добавление нового ребенка за всеми существующими детьми

Чтобы добавить нового ребенка последним к существующему элементу, используйте один из следующих способов:

родитель. insertChildAfter(родитель ^[родитель.*.length( )-1], ) или:

родитель *\_родитель * Л ength ( )-1] = родитель *\_родитель.*. length ( )-1] +

или:

родитель. appendChi1d()

Например, следующий код добавляет новый элемент к сразу за существующим элементом :

var novel:XML =

Ulysses

Joyce. James

Penguin Books Ltd

novel. insertChildAfter(novel.*[novel.*.length( )-l].

A modern classic);

Приведенная строка является синонимом следующего кода, который заменяет последнего ребенка элемента объектом XMLList, содержащим последнего ребенка элемента (элемент ) и элемент :

novel.*[novel.*.length( )-l] = novel.*[novel.*.length( )-l]

+ A modern classic:

Чтобы облегчить восприятие, рассмотрим данную строку кода еще раз, записав ее с помощью псевдокода:

// ПСЕВДОКОД:

= + A modern classic

To же самое мы можем записать, используя более сжатую форму (это настоящий код на языке ActionScript), как показано ниже:

novel.*[novel.*.length( )-1] += A modern classic; А вот наиболее удобный подход:

novel. appendChild(A modern classic);

Добавление нового ребенка за указанным существующим ребенком

Чтобы добавить нового ребенка за указанным существующим ребенком, используйте один из следующих способов:

родитель. insertChi1dAfter(родитель. существующийРебенок[п], ) или:

родитель. существующийРебенок[п] = родитель. существующийРебенок[п] +

или:

родитель *[индексРебенка] = родитель *[индексРебенка] +

Например, следующий код добавляет второй элемент к элементу сразу за существующим элементом :

novel. insertChildAfter(novel. AUTHOR[0], Dave Luxton);

В качестве первого аргумента в метод insertChildAf ter ( ) необходимо передавать экземпляр класса XML (а не класса XMLList!), поэтому мы должны использовать прямую ссылку на экземпляр класса XML — novel. AUTHOR [ 0 ].

Руководство по actionscript. часть 3, стр. 060

Чтобы вспомнить отличия между экземплярами классов XML и XMLList, обратитесь к подразд. «Интерпретация объекта XMLList как экземпляра класса XML» разд. «Обращение к данным XML».

В качестве альтернативы подходу с применением метода insertChildAf ter ( ) можно использовать следующий код:

novel. AUTHORC0] = novel. AUTHORCO] + Dave Luxton; Или более сжато:

novel. AUTHOR[0] += Dave Luxton; А вот еще один аналогичный подход:

// Добавляем новый элемент XML за вторым ребенком элемента novel novel.*[1] = novel.*[1] + Dave Luxton;

И вновь предыдущая строка может быть записана более сжато:

novel.*[1] += Dave Luxton:

Добавление нового ребенка перед указанным существующим ребенком

Чтобы добавить нового ребенка перед указанным существующим ребенком, используйте один из следующих способов:

родитель. insertChi1dBefоге(ро//игель. существующийРебенок[п], ) или:

родитель. существующийРебенок[п] = родитель. существующийРебенок[п]

+

или:

родитель *[индексРебенка] = родитель *[индексРебенка] +

Например, следующий код добавляет новый элемент к нашей книге непосредственно перед первым элементом :

novel. insertChi1dBeforeCnovel. AUTHOR[0], 19.99);

Как и в случае с методом insertChildAf ter ( ), обратите внимание, что первым аргументом метода insertChildBef ore ( ) должен быть экземпляр класса XML (а не класса XMLList!).

Руководство по actionscript. часть 3, стр. 061

Предыдущая строка является синонимом следующей строки: novel. AUTHOR = 19.99 + novel. AUTHOR:

Вот еще один аналогичный подход:

// Добавление нового элемента XML

// перед вторым ребенком элемента novel

novel.*[1] = 19.99 + novel.

Добавление нового ребенка перед всеми существующими детьми

Чтобы добавить новый элемент в качестве первого ребенка существующего элемента, используйте любой из следующих способов:

родитель. insertChildBefore(родйгель.*[0]. ) или:

родитель.*[0] = + родитель.*[0] или:

родитель. prependChi ](\()

Например, следующий код добавляет новый элемент к нашей книге непосредственно перед существующим элементом :

novel. insertChi 1 dBeforeCnovel.*[0], 1040):

Предыдущая строка аналогична следующей:

novel.*[0] = 1040 + novel.*[0];

А вот наиболее удобный подход:

novel. prependChi ld( 1040):

Удаление элементов и атрибутов

Чтобы удалить элемент или атрибут из документа, используйте оператор delete следующим образом:

delete элементИлиАтрибут

Например, следующий код удаляет атрибут ISBN из элемента : delete novel.@ISBN:

Следующий код удаляет элемент из элемента : delete novel. TITLE:

Вот как можно удалить всех детей, содержащихся в элементе:

delete novel.*: // Удаляет, и // из исходного XML-фрагмента.

Руководство по actionscript. часть 3, стр. 062

Та же методика может применяться при удалении текстового содержимого из элемента:

delete novel. TITLE.*: // Удаляет «Ulysses»

// из исходного XML-фрагмента.

Вот как можно удалить все атрибуты элемента:

delete novel.@*; // Удаляет все атрибуты (в данном случае ISBN)

Ссылки на части документа не являются обновляемыми

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

var novel:XML =

Ulysses

Joyce, James

Penguin Books Ltd

var children:XMLList = novel.*:

Если теперь мы удалим элемент // Удаляем delete novel. PUBLISHER:

trace(novel): // Выводит: // Ulysses // Joyce. James

//


trace(children): // Выводит: Ulysses

// Joyce, James

// Penguin Books Ltd

// по-прежнему существует!

Возможно, будущие версии расширения Е4Х будут поддерживать обновляемые ссылки на части документа.



Полезные ссылки
Случайные записи
  • 07.03.2011">Руководство по actionscript. часть 4, стр. 125
  • 09.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.132
  • 28.02.2011">Руководство по actionscript. часть 6, стр. 022
  • 13.03.2011">Руководство по actionscript. часть 3, стр. 091
  • 14.07.2011">Бюджетные ноутбуки Acer
  • 14.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.76
  • 03.02.2010">Создание графиков и диаграмм на JavaScript
  • 11.03.2011">Руководство по actionscript. часть 4, стр. 006
  • 23.01.2011">Руководство по actionscript. часть 1, стр. 027
  • 01.04.2012">ЕС создаст центр по борьбе с киберпреступностью
  • 16.03.2011">Руководство по actionscript. часть 3, стр. 013
  • 15.03.2011">Руководство по actionscript. часть 3, стр. 036
  • 17.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.132
  • 27.07.2011">Швейцарские часы – эталон качества
  • 10.03.2011">Руководство по actionscript. часть 4, стр. 028
Опрос

Какие цвета вы предпочитаете?

View Results

Loading ... Loading ...