Март 2011

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

Интерпретация экземпляра класса XMLL i s t как экземпляра класса XML делает использование расширения Е4Х более простым и удобным, но при этом порождает некоторые сбивающие с толку детали, особенно когда эта возможность применяется вместе с автоматическим преобразованием строк. Поближе познакомимся с этой проблемой.

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

В нашем коде мы создаем метод displayAuthor ( ), который выводит имя автора. В первой реализации метода мы будем требовать, чтобы имя автора передавалось в виде строки:

public function displayAuthor (name:String):void { // authorField ссылается на экземпляр класса TextField, // в котором отображается имя автора authorField. text = name;

}

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

displayAuthor(novel. AUTHOR):

Данная инструкция проста и интуитивно понятна, но, как мы уже знаем из этой главы, «за кадром» происходит очень много действий. В качестве повторения проанализируем, как это работает. Во-первых, среда выполнения Flash передает выражение novel. AUTHOR в метод displayAuthor ( ) в качестве значения параметра name. Типом данных параметра name является String, поэтому среда Flash автоматически пытается преобразовать значение выражения novel. AUTHOR в строку, используя следующее выражение:

novel. AUTHOR. toString( )

По умолчанию вызов метода toString ( ) над объектом возвращает строку в формате [obj ect ИмяКласса], но выражение novel. AUTHOR представляет экземпляр класса XMLList, а класс XMLList переопределяет метод toString ( ) собственной версией. В частности, версия метода toString ( ) класса XMLList узнает, что значение выражения novel. AUTHOR содержит только один элемент, поэтому возвращается результат вызова метода toString( ) класса XML над этим элементом. Таким образом, вызов novel. AUTHOR. toString ( ) автоматически преобразуется в вызов novel. AUTHOR [ 0 ] . toString ( ). Что же является возвращаемым значением выражения novel. AUTHOR [ 0 ] . toString ( )? Как мы уже знаем, ответ основан на факте, что выражение novel. AUTHOR [0] представляет простой элемент XML, который не содержит других элементов-потомков. Для элемента XML, не содержащего других элементов, метод toString ( ) класса XML возвращает текстовый узел данного элемента в виде строки, исключая охватывающие теги. Значит, выражение novel. AUTHOR [0] .toString( ) в качестве окончательного значения, передаваемого в метод displayAuthor ( ), вернет значение «Joyce, James» (а не «Joyce/ James«).

Подведем итоги.

? Передача значения выражения novel. AUTHOR в качестве параметра типа String приводит к неявному преобразованию значения выражения novel. AUTHOR в строку.

? Значение выражения novel. AUTHOR преобразуется в строку с помощью вызова novel. AUTHOR. toString ( ).

? Выражение novel. AUTHOR. toString ( ) автоматически возвращает результат выражения novel. AUTHOR [ 0 ] . toString ( ), поскольку значение выражения novel. AUTHOR представляет экземпляр класса XMLList с одним-единственным элементом.

? Выражение novel. AUTHOR [0] . toString ( ) возвращает текст, содержащийся в элементе («Joyce, James»), в соответствии с реализацией метода toString ( ) класса XML (дополнительную информацию можно найти далее, в разд. «Преобразование объектов XML и XMLList в строки»).

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

После всего сказанного и сделанного выражение

displayAuthor(novel. AUTHOR);

преобразуется в выражение

displayAuthor(«Joyce, James»);

которое мы и предполагали увидеть.

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

var novel:XML = Ulysses

Joyce, James

February 2 1882

Penguin Books Ltd

Соответственно изменим метод displayAuthor ( ), чтобы он принимал элемент в качестве параметра и получал имя и дату рождения автора непосредственно из элементов-детей и :

public function displayAuthor (author. XML):void { authorField. text = «Name: » + author. NAME

+ » Birthdate: » + author. BIRTHDATE;

}

Обратите внимание, что в данном коде тип данных параметра был изменен с типа String на XML. Если сейчас мы попытаемся передать значение выражения novel. AUTHOR в метод displayAuthor ( ), на этапе выполнения возникнет ошибка несоответствия типов, поскольку среда Flash не может осуществить неявное преобразование значения выражения novel. AUTHOR (которое является объектом XMLList) к экземпляру класса XML:

displayAuthor(novel. AUTHOR); //Ошибка #1034: Ошибка операции приведения

//типов: невозможно преобразовать XMLList в XML

Чтобы исправить данную ошибку, мы должны явно ссылаться на экземпляр класса XML, представляющий элемент , при передаче его в метод displayAuthor ( ), как показано в следующем коде:

di splayAuthor(novel. AUTHOR[0]); // Передаем единственный экземпляр класса

// XML, принадлежащий значению выражения’ // novel. AUTHOR, в метод displayAuthor( )

Обратите внимание на важное отличие: когда мы хотим обратиться к тексту, содержащемуся в элементе , как к значению типа String, мы можем положиться на автоматическое поведение расширения Е4Х. Однако когда мы хотим обратиться к настоящему экземпляру класса XML, представляющему элемент , то должны явно ссылаться на этот экземпляр.

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

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

Листинг 18.7. Фрагмент с несколькими авторами

var oopBook:XML = Head First Design Patterns

Eric Freeman

January 1 1970



E1i sabeth Freeman

J a n u a ry 1 1971


Kathy Sierra

Ja nua ry 1 1972


Bert Bates

January 1 1973

0′Reilly Media, Inc ;

Для работы с новой структурой XML мы изменим метод displayAuthor ( ), чтобы он принимал объект XMLList, представляющий несколько элементов (а не один элемент из предыдущего примера). В новой версии метода displayAuthor ( ) для перемещения по элементам используется инструкция for-each-in (мы рассмотрим использование инструкции for-each-in далее, в разд. «Обработка данных XML с помощью циклов for-each-in и for-in»).

public function displayAuthor (authors:XMLList):void { for each (var author:XML in authors) { authorField. text += «Name: » + author. NAME

+ «, Birthdate: » + author. BIRTHDATE + «\n»;

}

}

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

di splayAuthor(oopBook. AUTHOR);

Эта строка кода соответствует нашему первоначальному подходу, а именно: displayAuthor(novel. AUTHOR);

На этот раз объект XMLLi st передается непосредственно в метод di splayAu thor ( ) без преобразования, поскольку типом данных получаемого параметра является XMLList, а не String. И снова обратите внимание на отличие: если при передаче объекта XMLList в функцию мы хотим преобразовать список в значение типа String, то для получаемого параметра указываем тип данных String и позволяем «колдовать» расширению Е4Х. Однако если мы хотим сохранить тип данных списка, то должны указать XMLList в качестве типа данных получаемого параметра. И сама ссылка (oopBook. author), и тип данных получаемого параметра (authors) оказывают влияние на поведение кода.

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



Полезные ссылки
Случайные записи
  • 30.05.2013">В течение недели LG продемонстрирует гибкую панель OLED в 5 дюймов
  • 20.03.2011">Руководство по actionscript. часть 2, стр. 058
  • 13.03.2011">Руководство по actionscript. часть 3, стр. 098
  • 21.03.2011">Руководство по actionscript. часть 2, стр. 051
  • 26.02.2011">Руководство по actionscript. часть 6, стр. 075
  • 04.03.2011">Руководство по actionscript. часть 5, стр. 039
  • 28.02.2011">Руководство по actionscript. часть 6, стр. 019
  • 13.03.2011">Руководство по actionscript. часть 3, стр. 090
  • 28.02.2011">Руководство по actionscript. часть 6, стр. 018
  • 22.01.2011">Руководство по actionscript. часть 1, стр. 107
  • 01.03.2011">Руководство по actionscript. часть 5, стр. 112
  • 04.03.2011">Руководство по actionscript. часть 5, стр. 045
  • 15.02.2010">Типографы. Проверка и подготовка слова к web-изданию
  • 10.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.127
  • 10.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.112
Опрос

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

View Results

Loading ... Loading ...