Есть несколько методов работы с данными XML применительно к Интернету. Это CSS, XSL и JavaScript. Рассмотрим их по порядку.
Возможность использования CSS при работе с XML-документами очевидна: каскадные таблицы стилей позволяют лишь задать стиль для отображения данных, но никак не манипулировать содержимым документа. Хотя эта связка малопродуктивна, если есть желание, стоит лишь во второй строчке XML-документа написать <?xml-stylesheet type="text/css" href="main.css"?>. Структура .css-файла проста: имена стилей должны совпадать с именами тэгов, для которых предназначены эти стили. Почему малопродуктивна? Да просто XML приправлен своей аналогичной технологией — XSL, Extensible Stylesheet Language («расширенный язык таблицы стилей»). Как видно из названия, это тоже таблица стилей, хоть и с бо’льшими возможностями, нежели CSS. Однако и это не верх совершенства. Для использования XSL во вторую строчку кода пишется конструкция <?xml-stylesheet type="text/xsl" href="main.xsl"?>.
Теперь поговорим о JavaScript, хоть и не идеальном в плане скорости работы, однако, на мой взгляд, оптимальном средстве для обработки XML-данных в браузерах.
Как может использоваться XML и чем он может нам помочь? Использоваться — повсеместно, помочь же он может не только в структуризации контента, но и в экономии трафика и оптимизации размеров документов. Допустим, нам надо создать меню для сайта. XML-документ будет выглядеть так:
Напомню, что указанные в статье примеры не идеальны — возможно, у вас получится более выгодная структура, однако в качестве примера будем использовать эту. Итак, что характеризуют тэги <title> и <link>, думаю, ясно — скажу лишь, что тэг <style> сообщает нам, какой стиль CSS используется для этого пункта меню (естественно, эти стили должны быть созданы в .css-файле).
Корневой тэг содержит атрибут onmouseover со значением mouseOver1(). Этот атрибут говорит о том, какая JavaScript-функция будет вызываться при наведении мышки на пункт меню. Однако последний пункт меню имеет свой атрибут onmouseover с другим значением. Это сделано затем, чтобы иметь возможность назначать, к примеру, разные обработчики событий для разных пунктов меню (CSS-стиль у этого пункта меню тоже отличается от двух предыдущих). Итак, когда мы будем формировать меню, мы будем устанавливать параметры наших пунктов. В первых двух пунктах мы не найдем обработчика события (onmouseover), из чего сделаем вывод, что его следует искать на уровне выше, т.к. он, получается, общий для этих элементов. Это делается с целью экономии кода и трафика. Но т.к. третий пункт у нас отличается (нам так вздумалось), обработчик у него будет другой — мы его явно и указали.
Итак, попробуем загрузить в нашу JavaScript-программу XML-документ, сформировать из него меню и выдать пользователю. Для вставки меню предлагаю использовать слой (<div>). Предлагаю пробежать глазами следующий код и обсудить его построчно:
<html> <head> <title>Меню</title> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <link href="main.css" rel="stylesheet" type="text/css"> <script language="JavaScript"> function makeMenu() { var xmlMenu=new ActiveXObject("Microsoft.XMLDOM"); xmlMenu.async="false"; xmlMenu.load("menu.xml"); nodes=xmlMenu.documentElement.childNodes; content=<table width="150" border="0">; for (a=0; a<nodes.length; a++) { mouseOver=nodes.item(a).getAttribute("onmouseover"); if (mouseOver==null) { mouseOver= xmlMenu.documentElement.getAttribute("onmouseover"); } for (b=0; b<nodes.item(a).childNodes.length; b++) { if (nodes.item(a).childNodes.item(b).nodeName==title) { title=nodes.item(a).childNodes.item(b).text; } else if (nodes.item(a).childNodes.item(b).nodeName==style) { style=nodes.item(a).childNodes.item(b).text; } else if (nodes.item(a).childNodes.item(b).nodeName==link) { link=nodes.item(a).childNodes.item(b).text; } } content+=<tr><td><a href=" + link + " class=" + style + " onmouseover=" + mouseOver + "> + title + </a></td></tr>; } content+=</table>; document.all.menu.innerHTML=content; } </script> </head> <body> <a href="#" onclick="makeMenu()">Сформировать меню</a><br><br> <div id="menu"></div> </body> </html>
Итак, анализируем функцию makeMenu(). Первая строка создает объект, в который мы будем загружать XML-документ. Вторая строка сообщает, что обработка XML-документа начнется только после его полной загрузки. Дальше мы говорим, какой файл загружать. После присваиваем переменной nodes структуру дочерних элементов корневого тэга. То есть, в переменной nodes содержится все, что находится у нас внутри тэга <menu></menu> в нашем XML-документе. Именно параметр childNodes указывает на то, что мы желаем работать с дочерними нодами корневого элемента (xmlMenu — это созданный нами объект, в который загружен XML-файл; documentElement — корневой элемент; childNodes — дочерние элементы текущей ноды). После этого переменной content, в которую мы и будем записывать сформированное меню, мы присваиваем начальное значение в виде тэга открытия таблицы (впоследствии мы будем дописывать строки таблицы, а в конце поставим закрывающий тэг </table>). Далее запускаем цикл, количество оборотов которого соответствует количеству дочерних нод корневого элемента (nodes.length). После мы пытаемся присвоить переменной mouseOver значение атрибута onmouseover текущей ноды: nodes.item(a) определяет текущий элемент — в скобках указывается индекс (порядковый номер начиная с нуля) дочерней ноды в текущей родительской ноде, т.е. в ноде <menu> мы перебираем дочерние ноды <unit>, а выражение nodes.item(0), nodes.item(1), nodes.item(2) указывает на каждую из нод <unit> соответственно. Если в текущей ноде мы не нашли значения атрибута onmouseover, мы поднимаемся на уровень выше, в родительскую ноду, и смотрим там (это было предусмотрено нами при создании XML-файла). Для ноды <unit> нам необходимо просмотреть дочерние ноды и вывести оттуда необходимые нам данные (текст ссылки, саму ссылку и ее стиль). Поэтому мы спускаемся на уровень ниже и сообщаем, что хотим просмотреть дочерние ноды текущей ноды (текущая нода — <item>): nodes.item(a).childNodes. Проходит цикл (три раза, т.к. у нас три параметра — три ноды), после чего мы имеем нужные значения в переменных title, link и style, а затем добавляем в переменную content строчку таблицы с пунктом меню. Атрибут nodeName текущей ноды возвращает имя тэга (title, style, link), а атрибут text — содержимое ноды (О нас, menu1, about.html). В конце закрываем таблицу и вставляем в слой (<div>) значение переменной content. Вот наше меню и готово.
Естественно, если меню состоит всего из трех элементов, такая схема невыгодна ни по скорости, ни по объему загружаемой информации, однако если число пунктов перевалит за дюжину, мы будем в выигрыше. Помимо считывания, JavaScript позволяет добавлять и удалять ноды, изменять атрибуты. Для добавления ноды необходимо указать следующее:
newnode=xmlMenu.createElement("newnodename"); newtext=xmlMenu.createTextNode("Содержимое новой ноды"); newnode.appendChild(newtext); xmlMenu.documentElement.appendChild(newnode);
Newnodename — это имя тэга для создания ноды. Для установки атрибута используем следующий код:
При разработке приложений для внутреннего использования (в локальной сети) размер .xml-файла большой роли не играет. Но необходимо помнить, что скорость интернет-соединения недостаточно высока, чтобы можно было забыть о возможности оптимизации XML-документов (даже если скорость позволяет, зачем же неоправданно увеличивать трафик?) Можно иметь две версии .xml-файла: одну для разработки и ориентирования в структуре, другую (сокращенную) — для пользователей. Существенно сэкономить можно на именах тэгов. Не стоит злоупотреблять длинными значениями атрибутов. Вот как бы мог выглядеть наш .xml-файл, выложенный и Интернете:
Такая структура значительно экономит трафик; вдобавок, мы имеем полную версию — для ориентирования в структуре.
Используйте сокращения и в JavaScript. Например, достаточно часто в коде используется объект document.all. Его запросто можно присвоить переменной: DA=document.all, и потом использовать в конструкциях типа DA.menu.innerHTML=content.
Старайтесь писать имена нод и атрибутов и нижнем регистре, во избежание недоразумений (ноды регистрозависимы).