Одна из ключевых особенностей островков XML_данных заключается в том, что они могут использоваться механизмом автоматического разворачивания шабло_ нов, при котором данные из этих островков автоматически вставляются в HTML_ элементы. Такого рода HTML_шаблоны в IE определяются добавлением в эле_ менты атрибутов datasrc и datafld (где префикс «fld» означает «field» – поле).
В этом разделе описываются приемы работы с XML_данными, уже упоминав_ шиеся в начале главы, а также приемы создания средствами XPath и DOM улуч_ шенного механизма разворачивания шаблонов, который будет работать в броузе_ рах IE и Firefox. Шаблон – это любой HTML_элемент с атрибутом datasource. Зна_ чением этого атрибута должен быть идентификатор островка XML_данных или URL_адрес внешнего XML_документа. Кроме того, элемент шаблона должен иметь атрибут foreach, значением которого является XPath_выражение, возвра_ щающее список XML_узлов, откуда должны извлекаться данные. Для каждого XML_узла, полученного в результате выполнения выражения foreach, в HTML_ документ вставляется развернутая копия шаблона. Разворачивание шаблона производится в результате поиска внутри него всех элементов, имеющих атрибут data. Данный атрибут – это еще одно XPath_выражение, которое выполняется в контексте узла, полученного от выражения foreach. Выражение data выполня_ ется вызовом метода XML.getNode(), а текст, содержащийся в полученном узле, ис_ пользуется как содержимое HTML_элемента, в котором этот атрибут определен.
Это описание станет понятнее после изучения конкретного примера. В приме_ ре 21.12 приводится простой HTML_документ, который включает островок XML_данных и использующий его шаблон. Разворачивание шаблона произво_ дится обработчиком события onload.
Пример 21.12. Островок XML'данных и HTML'шаблон
<html>
<!__ загрузить XML_утилиты для работы с островками данных и шаблонами __> <head><script src="xml.js"></script></head>
<!__ Развернуть все шаблоны документа после загрузки __> <body onload="XML.expandTemplates()">
<!__ Это островок XML_данных __>
<xml id="data" style="display:none"> <!__ скрытие с помощью CSS __> <contacts>
Наиболее важной частью примера 21.12 является обработчик события onload, который вызывает функцию XML.expandTemplates(). Реализация этой функции де_ монстрируется в примере 21.13. Программный код, который практически не за_ висит от платформы, основан на модели DOMLevel 1 и вспомогательных функ_ циях XML.getNode() и XML.getNodes(), реализованных в примере 21.10 и предназна_ ченных для работы с XPath_выражениями.
Пример 21.13. Разворачивание HTML'шаблонов
/*
* Разворачивает любые шаблоны, вложенные в элемент e. Если в каком_либо
* из шаблонов используются XPath_выражения с пространствами имен, во втором
* аргументе необходимо передать отображение префиксов пространств имен
* на соответствующие им URL_адреса, как в случае с XML.XPathExpression()
*
* Если элемент e не указан, используется document.body. Обычно эта функция
* вызывается без аргументов из обработчика события onload. В этом случае
* она автоматически разворачивает все шаблоны.
*/
XML.expandTemplates = function(e, namespaces) {
// Немножко подправить аргументы. if (!e) e = document.body;
else if (typeof e == "string") e = document.getElementById(e);
if (!namespaces) namespaces = null; // Значение undefined не работает
// HTML_элемент является шаблоном, если имеет атрибут "datasource".
// Рекурсивный поиск и разворачивание всех шаблонов.
// Обратите внимание: шаблоны внутри шаблонов недопустимы.
if (e.getAttribute("datasource")) {
// Если это шаблон _ развернуть его. XML.expandTemplate(e, namespaces);
}
else {
// Иначе рекурсивно обойти все дочерние узлы. Прежде чем развернуть
// шаблон, создается статическая копия потомка, чтобы развернутый
// шаблон не мешал итерации.
var kids = []; // Создать копию дочернего элемента for(var i = 0; i < e.childNodes.length; i++) {
var c = e.childNodes[i];
if (c.nodeType == 1) kids.push(e.childNodes[i]);
}
// Обойти все дочерние элементы for(var i = 0; i < kids.length; i++)
XML.expandTemplates(kids[i], namespaces);
}
21.6. Разворачивание HTML*шаблонов с использованием XML*данных
};
/**
* Разворачивает один указанный шаблон. Если XPath_выражение в шаблоне использует
* имена пространств, вторым аргументом следует передать отображение
* префиксов пространств имен на соответствующие им URL_адреса.