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

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

Таблица 18.1. Обзор: выражения расширения Е4Х и результаты

Выражение Тип данных параметра Результат

novel. AUTHOR String «Joyce, James»

novel. AUTHOR XML Ошибка несоответствия типов (невозможно преобразовать тип XMLList к типу XML)

novel. AUTHOR[0] String «Joyce, James»

novel. AUTHOR[0] XML Экземпляр класса XML, представляющий элемент

oopBook. AUTHOR String Строка, содержащая исходный код XML для четырех элементов

oopBook. AUTHOR XMLList Объект XMLList с четырьмя экземплярами класса XML, представляющими четыре элемента

Не беспокойтесь. Расширение Е4Х отлично продумано. Пусть его автоматическое поведение не тревожит вас. Большую часть времени оно будет помогать вам. Тем не менее при обращении к узлам XML с использованием синтаксиса обращения к переменным (оператор «точка») имейте в виду следующие потенциальные источники недоразумений.

? Выражение узелРодитель. имяУзлаРебенка является эквивалентным выражению узелРодитель. child [имяУзлаРебенка) и всегда ссылается на экземпляр класса XMLList, а не на экземпляр класса XML.

? Когда экземпляр класса XMLLis t содержит только один экземпляр класса XML, методы класса XML могут вызываться над экземпляром класса XMLList. Он автоматически переадресует эти вызовы экземпляру класса XML.

? Чтобы получить объектную ссылку на экземпляр класса XML, который содержится в элементе узелРодитель. имяУзлаРебенка, необходимо использовать выражение вида узелРодитель. имяУзлаРебенка [индекс], даже если нужный экземпляр класса XML является единственным элементом в объекте XMLLi s t (в этом случае для обращения к элементу используется выражение узелРоди тель. имяУзлаРебенка [ 0 ] ).

? Если XML-элемент содержит только текст (и не содержит других элементов-детей), в результате преобразования этого элемента в строку будет возвращен содержащийся в нем текст без окружающих тегов (например, в результате преобразования элемента UlyssesB строку будет возвращена строка «Ulysses», а не «Ulysses»).

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

Joyce, James

в строку будет получено

«Joyсе, James» а не

Joyce, James

Если вы сомневаетесь, то можете воспользоваться методами класса XML для обращения к интересующему вас содержимому. Явные названия методов класса XML иногда легче понять, несмотря на более громоздкую запись.

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

Var outField:TextField = new TextFieldC );

outField. width = 300:

outField. height = 300:

outField. text =•»Here is your order:\n»:

addChild(outField):

// Изначально общая стоимость заказа равна 0. var total:Number = 0:

// Этот цикл выполняется по одному разу для каждого элемента. for each (var item:XML in order.*) { // Отображаем описание данного элемента в текстовом поле outField. outField. text += item. QUANTITY

+ » » + item. NAME + «(s).»

+ » $» + item. PRICE + » eachAn»:

// Прибавляем стоимость этого элемента к общей стоимости заказа. // Обратите внимание, что операция умножения автоматически преобразует // значения количества и стоимости в числа, total += item. QUANTITY * item. PRICE:

}

// Отображаем общую стоимость заказа. outFi eld. appendText(«TOTAL: » + total):

Вот результат выполнения кода из листинга 18.9:

Here is your order:

3 Trinket(s). $9.99 each.

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

1 Gadget(s). $149.99 each.

2 Toy(s). $39.99 each. TOTAL: 259.94

Рассмотрим последний пример, демонстрирующий возможности управления содержимым заказа с помощью цикла for-each-in. Этот код присваивает одно и то же значение всем элементам из листинга 18.9:

// Большая РАСПРОДАЖА! // Все по цене $1!

for each (var item:XML in order.*) { item. PRICE = 1;

}

Более подробно возможность изменения содержимого элемента XML будет рассмотрена далее, в разд. «Изменение или создание нового содержимого XML».

Ошибочно полагать, что имена переменных экземпляров класса XML в объекте XMLList совпадают с названиями соответствующих элементов XML. Вместо этого экземпляры класса XML в объекте XMLList, как и элементы массива, расположены по порядку и в качестве имен переменных используются их порядковые номера. Это демонстрируется в следующем коде с помощью цикла for-in. Имена 0,1 и 2 представляют порядковый номер каждого экземпляра класса XML в объекте XMLList, возвращаемом выражением order. *.

for (var childName:String in order.*) { trace(childName);

}

// Вывод: // 0 // 1 // 2

^ I Более подробную информацию по инструкциям for-each-in и for-in можно найти frj. в гл. 15.

ф -

Обращение к потомкам

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

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

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

Листинг 18.10. Запись о взятых из библиотеки источниках

var loan:XML =

Ulysses

Joyce. James

Penguin Books Ltd



2001 A Space Odyssey

Stanley Kubrick

Warner Home Video



Spirited Away

Hayao Miyazaki

Walt Disney Video

В данном примере к потомкам элемента относятся:

? непосредственные дети: элемент и два элемента ;

? внуки: все элементы, , И ;

? правнуки: все текстовые узлы, содержащиеся в элементах, , И.

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

Для обращения к потомкам элемента используется оператор «потомок» (. .) расширения Е4Х, записываемый в следующем виде:

элемент, .идентификатор

Выражение для обращения к потомкам возвращает объект XMLLi st, представляющий всех потомков элемента элемент, имена которых соответствуют имени идентификатор. Например, следующее выражение возвращает объект XMLList, содержащий два экземпляра класса XML, которые представляют два элемента из листинга 18.10:

loan..DIRECTOR

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

loan..TITLE

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

traceCYou have borrowed the following items:»); for each (var title:XML in loan..TITLE) { trace(title);

// Вывод:

You have borrowed the following items: Ulysses

2001 A Space Odyssey Spirited Away

Это очень удобно!

Выражение a. b возвращает список всех непосредственных элементов-детей с именем Ь; выражение а..Ь возвращает список всех элементов-потомков с именем Ь. Синтаксис намеренно сделан похожим — единственным отличием является глубина возвращаемых узлов.

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

элемент. .$имяАтрибута

Например, следующее выражение возвращает объект XMLList, имеющий три экземпляра класса XML, которые представляют три атрибута DUE из листинга 18.10.

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

Loan..@DUE

Вот еще один удобный фрагмент кода:

tracer Your items are due on the following dates:»); for each (var due:XML in loan..@DUE) { trace(new Date(Number(due)));

‘}

// В часовом поясе стандартного восточного времени будут выведено следующее:

Your items are due:

Sun Jan 1 00:00:00 GMT-0500 2006

Sat Jan 7 00:00:00 GMT-0500 2006

Sat Jan 14 00:00:00 GMT-0500 2006

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

элемент. .*

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

loan. .*

Можете определить всех потомков? Все они представлены в листинге 18.11, нарисованном с помощью удобной псевдографики. Позиция каждого узла в объекте XMLList, возвращаемом выражением loan. . *, выделена круглыми скобками. Вы не забыли текстовые узлы, правда? Помните, что они считаются потомками?

Листинг 18.11. Узлы, возвращаемые выражением loan..*

BOOK (1) I-TITLE (2) j I-Ulysses (3) I

|-AUTHOR (4)

| |-Joyce. James (5)

I

I-PUBLISHER (6)

I-Penguin Books Ltd (7)

DVD (8) I-TITLE (9)

j |-2001 A Space Odyssey (10) I

j-AUTHOR (11)

I I-Stanley Kubrick (12) I

• I-DIRECTOR (13)

I-Warner Home Video (14)

DVD (15) I-TITLE (16)

j I-Spirited Away (17) I

I-AUTHOR (18)

I |- Hayao Miyazaki (19) I

I-DIRECTOR (20)

|- Walt Disney Video (21)

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

элемент. .@*

Например, следующий код возвращает объект XMLList, который содержит все атрибуты, определенные в потомках элемента (всего шесть). Стоит отметить, что если бы в элементе были определены атрибуты (у элемента они отсутствуют), они были бы включены в этот список.

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

Loan..@*

Следующий код выводит атрибуты, возвращаемые выражением loan. . @ *, с помощью цикла for-each-in. Для каждого атрибута отображается его имя и значение, а также содержимое элемента-ребенка его родителя.

for each (var attribute:XML in loan..@*) { trace(attribute. parent( ).TITLE

+ «: » + attribute. name( ) + «=» + attribute);

}

// Вывод:

Ulysses: ISBN=0141182806

Ulysses: DUE=1136091600000

2001 A Space Odyssey: ISBN=0790743086

2001 A Space Odyssey: DUE=1136610000000

Spirited Away: ISBN=078884461X

Spirited Away: DUE=1137214800000

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

элемент. .*.@*

или следующий более громоздкий, но менее загадочный код: элемент. .*.attributesC )

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

Руководство по 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.



Полезные ссылки
Случайные записи
  • 15.07.2010">Полезные термины для новичков.
  • 12.03.2011">Руководство по actionscript. часть 3, стр. 117
  • 15.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.52
  • 02.06.2010">Самоучитель по креативному веб-дизайну. Книга 3, стр.106
  • 14.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.63
  • 03.11.2011">Как создать кинопостер
  • 03.03.2011">Руководство по actionscript. часть 5, стр. 055
  • 22.01.2011">Руководство по actionscript. часть 1, стр. 136
  • 18.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.68
  • 11.03.2011">Руководство по actionscript. часть 4, стр. 006
  • 02.03.2011">Руководство по actionscript. часть 5, стр. 107
  • 06.10.2012">Google и американские издатели урегулировали семилетний спор
  • 23.01.2011">Руководство по actionscript. часть 1, стр. 080
  • 04.03.2011">Руководство по actionscript. часть 5, стр. 053
  • 14.03.2011">Руководство по actionscript. часть 3, стр. 064
Опрос

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

View Results

Loading ... Loading ...