Руководство по 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
Чтобы изменить содержимое элемента со строки «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 =
var user2:XML =
Мы можем заменить элемент
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
Синтаксис присваивания также может быть использован для добавления вложенной структуры XML с помощью одного оператора. Предположим, что мы хотим добавить следующее вложенное содержимое, описывающее место действия романа, к элементу :
Dublin
Irel and
Для этого можно воспользоваться следующим кодом:
novel. SETTING. CITY = «Dublin»; novel. SETTING. COUNTRY = «Ireland»;
Когда среда Flash пытается исполнить первую инструкцию, она определяет, что в документе нет ни элемента, ни элемента, и, следовательно, создает оба этих элемента. Когда среда Flash исполняет вторую инструкцию, она видит, что элемент уже существует, и поэтому не создает его повторно. Вместо этого среда выполнения просто добавляет элемент к существующему элементу. Вот так выглядит получившийся фрагмент XML:
Мы можем использовать аналогичный подход, чтобы представить информацию о месте действия в одном элементе, имеющем следующий формат:
Для этого мы просто присваиваем желаемым атрибутам необходимые значения, как показано в следующем коде:
novel. SETTING.@CITY = «Dublin»; novel. SETTING.^COUNTRY = «Ireland»;
//Выдает:
Ulysses
В этом разделе мы узнали, что присваивание значения несуществующему элементу приводит к добавлению этого элемента в документ. Но что делать, если мы хотим добавить элемент с таким же именем, как имя существующего элемента? Например, как добавить несколько элементов
ЭкземплярКлассаХМЫлиХМШ stl + ЭкземплярКлассаХМЫлиХМШ st2
Он возвращает новый экземпляр класса XMLList, содержащий объединенный список всех экземпляров класса XML из экземпляров ЭкземплярКлассаХМЫлиХМШstl и ЭкземплярКлассаХМЫлиХМШ st2.
Руководство по actionscript. часть 3, стр. 059
Добавление нового ребенка за всеми существующими детьми
Чтобы добавить нового ребенка последним к существующему элементу, используйте один из следующих способов:
родитель. insertChildAfter(родитель ^[родитель.*.length( )-1], ) или:
родитель *\_родитель * Л ength ( )-1] = родитель *\_родитель.*. length ( )-1] +
или:
родитель. appendChi1d()
Например, следующий код добавляет новый элемент к сразу за существующим элементом
var novel:XML =
Ulysses
novel. insertChildAfter(novel.*[novel.*.length( )-l].
A modern classic);
Приведенная строка является синонимом следующего кода, который заменяет последнего ребенка элемента объектом XMLList, содержащим последнего ребенка элемента (элемент
novel.*[novel.*.length( )-l] = novel.*[novel.*.length( )-l]
+ A modern classic:
Чтобы облегчить восприятие, рассмотрим данную строку кода еще раз, записав ее с помощью псевдокода:
// ПСЕВДОКОД:
To же самое мы можем записать, используя более сжатую форму (это настоящий код на языке ActionScript), как показано ниже:
novel.*[novel.*.length( )-1] += A modern classic; А вот наиболее удобный подход:
novel. appendChild(A modern classic);
Добавление нового ребенка за указанным существующим ребенком
Чтобы добавить нового ребенка за указанным существующим ребенком, используйте один из следующих способов:
родитель. insertChi1dAfter(родитель. существующийРебенок[п], ) или:
родитель. существующийРебенок[п] = родитель. существующийРебенок[п] +
или:
родитель *[индексРебенка] = родитель *[индексРебенка] +
Например, следующий код добавляет второй элемент
novel. insertChildAfter(novel. AUTHOR[0],
В качестве первого аргумента в метод insertChildAf ter ( ) необходимо передавать экземпляр класса XML (а не класса XMLList!), поэтому мы должны использовать прямую ссылку на экземпляр класса XML — novel. AUTHOR [ 0 ].
Руководство по actionscript. часть 3, стр. 060
Чтобы вспомнить отличия между экземплярами классов XML и XMLList, обратитесь к подразд. «Интерпретация объекта XMLList как экземпляра класса XML» разд. «Обращение к данным XML».
В качестве альтернативы подходу с применением метода insertChildAf ter ( ) можно использовать следующий код:
novel. AUTHORC0] = novel. AUTHORCO] +
novel. AUTHOR[0] +=
// Добавляем новый элемент XML за вторым ребенком элемента novel novel.*[1] = novel.*[1] +
И вновь предыдущая строка может быть записана более сжато:
novel.*[1] +=
Добавление нового ребенка перед указанным существующим ребенком
Чтобы добавить нового ребенка перед указанным существующим ребенком, используйте один из следующих способов:
родитель. insertChi1dBefоге(ро//игель. существующийРебенок[п], ) или:
родитель. существующийРебенок[п] = родитель. существующийРебенок[п]
+
или:
родитель *[индексРебенка] = родитель *[индексРебенка] +
Например, следующий код добавляет новый элемент
novel. insertChi1dBeforeCnovel. AUTHOR[0],
Как и в случае с методом insertChildAf ter ( ), обратите внимание, что первым аргументом метода insertChildBef ore ( ) должен быть экземпляр класса XML (а не класса XMLList!).
Руководство по actionscript. часть 3, стр. 061
Предыдущая строка является синонимом следующей строки: novel. AUTHOR =
Вот еще один аналогичный подход:
// Добавление нового элемента XML
// перед вторым ребенком элемента novel
novel.*[1] =
Добавление нового ребенка перед всеми существующими детьми
Чтобы добавить новый элемент в качестве первого ребенка существующего элемента, используйте любой из следующих способов:
родитель. insertChildBefore(родйгель.*[0]. ) или:
родитель.*[0] = + родитель.*[0] или:
родитель. prependChi ](\()
Например, следующий код добавляет новый элемент
novel. insertChi 1 dBeforeCnovel.*[0],
Предыдущая строка аналогична следующей:
novel.*[0] =
А вот наиболее удобный подход:
novel. prependChi ld(
Удаление элементов и атрибутов
Чтобы удалить элемент или атрибут из документа, используйте оператор delete следующим образом:
delete элементИлиАтрибут
Например, следующий код удаляет атрибут ISBN из элемента : delete novel.@ISBN:
Следующий код удаляет элемент из элемента : delete novel. TITLE:
Вот как можно удалить всех детей, содержащихся в элементе:
delete novel.*: // Удаляет,
Руководство по actionscript. часть 3, стр. 062
Та же методика может применяться при удалении текстового содержимого из элемента:
delete novel. TITLE.*: // Удаляет «Ulysses»
// из исходного XML-фрагмента.
Вот как можно удалить все атрибуты элемента:
delete novel.@*; // Удаляет все атрибуты (в данном случае ISBN)
Ссылки на части документа не являются обновляемыми
Изменяя или добавляя новое содержимое в объект XML, имейте в виду, что любые вносимые изменения не отражаются на переменных, которые ссылаются на части этого документа. Например, следующий код создает переменную children, которая ссылается на узлы-детей элемента :
var novel:XML =
Ulysses
var children:XMLList = novel.*:
Если теперь мы удалим элемент
trace(novel): // Выводит:
//
trace(children): // Выводит: Ulysses
//
//
//
Возможно, будущие версии расширения Е4Х будут поддерживать обновляемые ссылки на части документа.
Руководство по actionscript. часть 3, стр. 063
Использование сущностей XML для специальных символов
В расширении Е4Х реализованы особая интерпретация и правила для определенных символов пунктуации, когда они используются в литерале XML или в выражении присваивания значения XML-элементу. В табл. 18.2 показано, как включать эти символы в документ XML с помощью языка ActionScript. В левом столбце таблицы перечислены символы, а в остальных столбцах показан код, необходимый для включения этих символов в четырех различных контекстах. Для сравнения следующий код демонстрирует пример каждого из четырех типов контекста (контекст представлен текстом некийТекст).
II Текст литерала атрибута
var xml:XML =
II Текст, присваиваемый атрибуту
xml.@другойНекийАтрибут = «некийТекст»
II Текстовый узел в литерале элемента
var xml:XML = ^екм7екс7″
// Текстовый узел, присваиваемый элементу xml. другойНекийЭлемент = «некийТекст»;
Таблица 18.2. Присваивание специальных символов пунктуации
Символ Текст литерала атрибута Текст, присваиваемый атрибуту Текстовый узел в литерале элемента Текстовый узел, присваиваемый элементу
\ \\ \\ \\
& & & & &
II " \» или " V
•** 1
< < < < <
> > > > >
Новая строка (\п) Не поддерживается* Не поддерживается* Не поддерживает — \п
{ { { х7В {
} } } } }
В данных контекстах последовательность новой строки \п автоматически преобразуется в сущность хА;.
Руководство по actionscript. часть 3, стр. 064
Чтобы включить символ ‘ в значение атрибута, отделенного символамииспользуйте управляющую последовательность '.
Допускается применять последовательность \п, если значение элемента является вычисляемым. Например,
var val:Stri ng = «Newlines \n are \n okay \n here!»: var paragraph:XML =
{val}
:
В отличие от строк, в литерале XML символ обратного слэша (\) никогда не интерпретируется как начало управляющей последовательности.
Стоит отметить, что, хотя символы > и & могут быть использованы в любом литерале XML, когда среда Flash встречает их в текстовом узле при парсин-ге XML-документа, она автоматически преобразует эти символы в сущности > и &атр; соответственно. Подобным образом, когда среда выполнения встречает символ & в значении атрибута при парсинге документа XML, она автоматически преобразует этот символ в сущность &атр;. Однако при использовании в контексте строки эти сущности будут преобразованы обратно в исходные символы. Чтобы увидеть текстовый узел без преобразования его сущностей, используйте метод экземпляра toXMLString ( ) класса XML. Это демонстрирует следующий код:
var р:ХМ1_ = &>: trace(p. toString( )): // Выводит: &> trace(p. toXMLString( )): // Выводит:
&>
Наконец, обратите внимание, что, хотя символ 1 может использоваться для отделения значения атрибута в литерале XML, в процессе парсинга он преобразуется в символ «. Это демонстрирует следующий код:
var p:XML = :
trace(p. toXMLString( )): // Выводит:
Присваивание значений объекту XMLList
Как уже говорилось в подразд. «Изменение содержимого элемсч 1та», не существует разницы между присваиванием значения объекту XMLList, содержащему один-единственный экземпляр класса XML, и присваиванием значения непосредственно этому экземпляру класса XML. Тем не менее присваивание значения объекту XMLList, содержащему более одного экземпляра класса XML, может иметь множество различных результатов. В зависимости от типа присваиваемого значения и типа экземпляров класса XML, находящихся в списке, список может быть пзмеч кч i или даже полностью заменен.
Единственный типичный сценарий использования операции присваивания значения экземпляру класса XMLList — замена ребенка элемента-родителя новым XML-элементом или списком элементов. Например, следующий код заменяет два ребенка элемента одним элементом :
var doc:XML =
Errors are your friends
Backup often
:
doc* =
Practice coding everyday
; // Выдает:
Practice coding everyday
Присваивание значения объекту XMLList является редко используемой операцией, поэтому ее тщательное рассмотрение выходит за рамки этой книги. Читателям, интересующимся гротескными ситуациями в программировании, которой, например, является попытка присвоить список инструкций обработки списку атрибутов, предоставляется возможность самостоятельно познакомиться с ними.
Руководство по actionscript. часть 3, стр. 065
Загрузка XML-данных
Для наглядности в большинстве примеров этой главы ХМL-данные были записаны в виде литералов. Однако в реальных приложениях они зачастую загружаются из внешнего источника.
Для загрузки ХМL-данных из внешнего источника в экземпляр класса XML используйте такую последовательность действий.
1. Создайте объект URLRequest, описав местоположение внешних данных XML (это может быть либо файл, либо серверный сценарий, возвращающий данные в формате XML).
2. Создайте объект URLLoader и используйте его метод load ( ) для загрузки данных XML.
3. Подождите, пока загрузятся данные XML.
4. Передайте загруженные данные XML в конструктор нового экземпляра класса XML.
Хотя подробное рассмотрение классов URLRequest и URLLoader выходит за рамки этой главы, в листинге 18.13 представлен код, необходимый для загрузки XML-данных в экземпляр класса XML. Используемый в примере класс XMLLoader расширяет класс Sprite, чтобы его можно было откомпилировать в качестве основного класса приложения для тестирования. Информацию о классах URLRequest и URLLoader можно найти в справочнике по языку ActionScript корпорации Adobe. Информацию об обработке событий можно получить в гл. 12.
Листинг 18.13. Загрузка данных XML из внешнего источника
package { import flash. display.*; import flash. events.*; import flash. net.*;
// Демонстрирует код, необходимый для загрузки XML-данных
// из внешнего источника
public class XMLLoader extends Sprite {
// Переменная, которой будут присвоены загруженные XML-данные
private var novel:XML;
// Объект, используемый для загрузки XML-данных private var urlLoader:URLLoader;
// Конструктор
public function XMLLoader ( ) { // Указываем местоположение внешнего источника XML-данных var urlRequest:URLRequest = new URLRequest(«novel. xml»); // Создаем объект, который умеет загружать внешние текстовые данные urlLoader = new URLLoader( );
// Регистрируем обработчик, чтобы получить событие об окончании // загрузки XML-данных
urlLoader. addEventLi stener(Event. COMPLETE, completeLi stener); // Загружаем XML-данные urlLoader.1oad(ur1 Request);
}
// Метод, вызываемый автоматически по окончании загрузки XML-данных
private function completeListener(e:Event):void { // Строка, содержащая загруженные XML-данные, присваивается переменной // data объекта URLLoader (то есть urlLoader. data). Чтобы создать // новый экземпляр класса XML из этой загруженной строки, мы передаем // ее в конструктор класса XML novel = new XML(urlLoader. data);
trace(novel. toXMLString( )); // Отображаем загруженные XML-данные,
// преобразованные в объект XML
Обратите внимание, что все операции загрузки данных в языке ActionScript, включая операцию, представленную в листинге 18.13, попадают под действие ограничений безопасности приложения Flash Player. Полную информацию об ограничениях безопасности можно найти в гл. 19.