Расширение EcmaScript для XML, больше известное как E4X, – это стандартное расширение1 языка JavaScript, которое определяет ряд дополнительных средств для работы с XML_документами. К моменту написания этих строк расширение E4X еще не получило широкого распространения. Броузер Firefox 1.5 поддер_ живает его, также оно доступно в Rhino версии 1.6 – интерпретаторе JavaScript, реализованном на языке Java. Компания Microsoft не планирует поддержку E4X в IE 7 и не совсем понятно, появится ли такая поддержка в других броузе_ рах, и если появится, то когда.
Несмотря на то, что расширение E4X является официальным стандартом, оно еще не получило достаточно широкого распространения, чтобы описывать его в этой книге полностью. Однако несмотря на ограниченную распространенность, уникальные возможности E4X, несомненно, заслуживают упоминания. Этот раздел представляет собой обзор расширения E4X в примерах. Возможно, в бу_ дущих изданиях книги это описание будет расширено.
Самое поразительное в E4X – то, что синтаксис XML становится частью языка JavaScript, благодаря чему появляется возможность включать XML_литералы непосредственно в JavaScript_код:
В синтаксисе литералов расширения E4X фигурные скобки используются в ка_ честве экранирующих символов, что позволяет размещать JavaScript_выраже_ ния прямо внутри XML_данных. Например, вот другой способ создания XML_ элемента, продемонстрированного в предыдущем примере:
pt = <periodictable></periodictable>; // Изначально таблица пуста var elements = ["Водород", "Гелий", "Литий"]; // Добавить элементы
// Создать XML_теги, используя содержимое массива
1 Расширение E4X описывается стандартом ECMA_357. Официальные специфика_ ции можно найти по адресу http://www.ecmainternational.org/publications/stan' dards/Ecma'357.htm.
В дополнение к синтаксису литералов существует возможность работать со стро_ ками в формате XML. Следующий фрагмент добавляет еще один элемент к пе_ риодической таблице:
pt.element += new XML('<element id="5"><name>Бор</name></element>');
Для работы с фрагментами XML_текста вместо метода XML() следует использо_ вать метод XMLList():
pt.element += new XMLList('<element id="6"><name>Carbon</name></element>' + '<element id="7"><name>Nitrogen</name></element>');
После того как XML_документ будет определен, обращаться к нему можно с по_ мощью интуитивно понятного синтаксиса E4X:
var elements = pt.element;
// Получить список всех тегов <element>
var
names = pt.element.name;
//
Список всех тегов <name>
var
n = names[0];
//
"Водород": содержимое нулевого тега <name>.
Расширение E4X добавляет также новый синтаксис для работы с XML_объекта_ ми. Две точки (..) – это оператор доступа к узлу_потомку; его можно использо_ вать вместо обычного оператора доступа к члену (.):
// Это еще один способ получить список всех тегов <name> var names2 = pt..name;
E4X позволяет использовать даже оператор группировки:
// Получить список всех потомков всех тегов <element>.
// Это еще один способ получить список всех тегов <name>. var names3 = pt.element.*;
В E4X имена атрибутов отличаются от имен тегов благодаря символу @ (этот син_ таксис заимствован из XPath). Например, запросить значение атрибута можно следующим образом:
// Получить атомный номер гелия
var atomicNumber = pt.element[1].@id;
Оператор группировки для имен атрибутов объединяет оба знака (@*):
// Список всех атрибутов всех тегов <element> var atomicNums = pt.element.@*;
Расширение включает даже удивительно мощный и краткий синтаксис фильт_ рации списков с произвольным условием:
// Получить список всех элементов и отфильтровать его так, чтобы
// он включал только те из них, которые имеют значение атрибута id < 3 var lightElements = pt.element.(@id < 3);
// Получить список всех тегов <element> и отфильтровать его так, чтобы
// он включал только те из них, имена которых начинаются с символа "Б".
// Затем получить список тегов <name> из оставшихся после фильтрации тегов <element>. var bElementNames = pt.element.(name.charAt(0) == 'Б').name;
21.8. E4X: EcmaScript для XML
В E4X определяется новый оператор цикла для обхода списка XML_тегов и их атрибутов. Цикл for/each/in напоминает цикл for/in, только вместо обхода свойств объекта выполняется обход значений свойств объекта:
// Вывести имена всех элементов периодической таблицы
// (Предполагается, что была определена функция print().) for each (var e in pt.element) {
print(e.name);
}
// Вывести атомные числа элементов
for each (var n in pt.element.@*) print(n);
В броузерах, поддерживающих E4X, данный цикл for/each/in может с успехом использоваться для обхода массивов.
E4X_выражения допускается указывать слева от оператора присваивания. Это позволяет изменять существующие и добавлять новые теги и атрибуты:
// Добавить новый атрибут в тег <element> для Водорода
// и новый дочерний элемент, чтобы он выглядел так:
С помощью стандартного оператора delete столь же просто удалять теги и атри_ буты:
delete pt.element[0].@symbol; // Удалить атрибут
delete pt..weight; // Удалить все теги <weight>
Расширение E4X спроектировано так, чтобы выполнять наиболее распростра_ ненные операции с XML_документами с использованием синтаксиса этого язы_ ка. Кроме того, E4X определяет методы XML_объектов. Вот пример вызова мето_ да insertChildBefore():
pt.insertChildBefore(pt.element[1],
<element id="1"><name>Дейтерий</name></element>);
Обратите внимание: объекты, созданные и управляемые E4X_выражениями, яв_ ляются XML_объектами. Это не DOM_объекты Node и Element, и с ними нельзя рабо_ тать, используя DOM API. Стандарт E4X определяет необязательный XML_метод domNode(), который возвращает DOM_объект Node, эквивалентный XML_объекту, но в Firefox 1.5 этот метод не реализован. Аналогично стандарт E4X утверждает, что DOM_объект Node может передаваться конструктору XML() для получения E4X_ эквивалента DOM_дерева. Эта возможность также не реализована в Firefox 1.5, что ограничивает область применения E4X в клиентских JavaScript_сценариях.
Расширение E4X полностью поддерживает пространства имен и включает язы_ ковые конструкции и API для работы с пространствами имен XML. Однако для простоты представленные примеры не используют этот синтаксис.