Книга: Технология XSLT
Выполнение XSLT-преобразований в JavaScript
Разделы на этой странице:
Выполнение XSLT-преобразований в JavaScript
JavaScript является одним из наиболее популярных скриптовых языков, которые применяются при программировании для Web. В этой главе мы покажем, как при помощи JavaScript и MSXML создать интерактивный каталог, основанный на XML и XSLT.
Предположим, что каталог организован в виде иерархии категорий приблизительно следующим образом.
Листинг 9.6. XML-документ каталога
<?xml version="1.0" encoding="windows-1251"?>
<catalog>
<category title="Компьютеры">
<category title="Настольные компьютеры"/>
<category title="Серверы"/>
</category>
<category title="Комплектующие">
<category title="Процессоры"/>
<category title="Материнские платы"/>
</category>
<category title="Расходные материалы">
<category title="Картриджи">
<category title="Картриджи для плоттеров"/>
<category title="Картриджи для принтеров"/>
</category>
<category title="Тонеры"/>
<category title="Бумага"/>
</category>
</catalog>
При отображении этого дерева мы будем раскрывать только определенную выбранную ветвь категорий. Скажем, если пользователь выбрал категорию "Расходные материалы", показывать информацию о компьютерах мы ему не будем. Иными словами, мы будем показывать только те категории, которые являются надкатегориями выбранной. Для того чтобы сделать это как можно эффективнее, мы выполним следующие шаги.
? При помощи ключа и уникального идентификатора, сгенерированного функцией generate-id
, мы найдем в дереве требуемую категорию и присвоим ее переменной $category
.
? Воспользовавшись осью ansector-or-self
, мы найдем все надкатегории данной, то есть все категории, которые прямо или косвенно содержат найденную. Путь выборки будет иметь вид $category/ancestor-or-self::category
. Найденное множество мы присвоим переменной $path
.
? При обработке каждой из категорий мы будем обрабатывать ее подкатегории только в том случае, если она является надкатегорией выбранной; иначе говоря — только в том случае, когда ее узел принадлежит множеству узлов $path
. Проверять это мы будем при помощи условия count(.|$path)=count($path)
.
Искомое преобразование в итоге запишется в виде.
Листинг 9.7. Преобразование обрабатывающее наш каталог
<?xml version="1.0" encoding="windows-1251"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Выводим документ в формате html и кодировке windows-1251 -->
<xsl:output method="html" encoding="windows-1251"/>
<!--
| Переменная, которая содержит уникальный
| идентификатор выбранного узла дерева
+-->
<xsl:param name="current" select="''"/>
<!-- Определение ключа категории -->
<xsl:key name="cat" match="category" use="generate-id(.)"/>
<!-- Находим текущую категорию -->
<xsl:variable name="category" select="key('cat',$current)"/>
<!--
| Находим надкатегории текущей категории, узлы которых
| мы будем раскрывать в дереве
+-->
<xsl:variable name="path"
select="$category/ancestor-or-self::category"/>
<!-- Шаблон обработки каталога -->
<xsl:template match="catalog">
<xsl:apply-templates select="category"/>
</xsl:template>
<!-- Шаблон обработки категории-->
<xsl:template match="category">
<!-- Параметр, указывающий отступ -->
<xsl:param name="indent"/>
<!-- Выводим отступ -->
<xsl:value-of select="$indent"/>
<!-- Выводим информацию о категории в виде ссылки -->
<а href="javascript:expand('{generate-id(.)}')">
<!-- Перед названием категории выводим соответствующую иконку -->
<img height="11" width="11" border="0">
<xsl:choose>
<!--
| Если категория не содержит субэлементов,
| выводим иконку с точкой
+-->
<xsl:when test="not(*)">
<xsl:attribute name="src">images/dot.gif</xsl:attribute>
</xsl:when>
<!--
| Если категория принадлежит ветке выбранной категории,
| выводим иконку с минусом, что означает раскрытую ветку
+-->
<xsl:when test="count(.|$path)=count($path)">
<xsl:attribute name="src">images/minus.gif</xsl:attribute>
</xsl:when>
<!--
| Если категория не принадлежит ветке выбранной категории,
| выводим иконку с плюсом, что означает нераскрытую ветку
+-->
<xsl:otherwise>
<xsl:attribute name="src">images/plus.gif</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</img>
<!--
| Выводим неразрывный пробел.
|   в Unicode соответствует
+-->
<xsl:text> </xsl:text>
<!-- Выводим название категории -->
<xsl:value-of select="@title"/>
</a>
<br/><xsl:text>
</xsl:text>
<!--
| Если категория принадлежит раскрываемой ветке,
| обрабатываем ее подкатегории
+-->
<xsl:if test="count(.|$path)=count($path)">
<xsl:apply-templates select="category">
<!-- Увеличиваем отступ на три пробела -->
<xsl:with-param name="indent"
select="concat($indent,'   ')"/>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Теперь осталось лишь только создать страницу, которая при помощи JavaScript и MSXML будет выполнять преобразования и выводить результат.
Для того чтобы воспользоваться возможностями MSXML, мы включим в нашу страницу два объекта:
<!-- Объект, представляющий входящий документ -->
<object
id="source"
width="0"
height="0"
classid="clsid:f5078f32-c551-11d3-89b9-0000f81fe221">
<param name="async" value="false">
<param name="validateOnParse" value="false">
</object>
<!-- Объект, представляющий документ преобразования -->
<object
id="stylesheet"
width="0"
height="0"
classid="clsid:f5078f32-c551-11d3-89b9-0000f81fe221">
<param name="async" value="false">
<param name="validateOnParse" value="false">
</object>
"Магический" код clsid:f5078f32-c551-11d3-89b9-0000f81fe221
, который присутствует в тегах обоих объектов, на самом деле не что иное, как уникальный идентификатор библиотеки MSXML 3.0, которую мы и будем использовать для выполнения преобразования. Итак, код нашей HTML- страницы будет выглядеть следующим образом.
Листинг 9.8. Код HTML-страницы
<html>
<head>
<meta
http-equiv="Content-Type"
content="text/html; charset=windows-1251" />
<style type="text/css">
body {font-family:Tahoma,Verdana,Arial,sans-serif; font-size:14px}
a:link {COLOR:#990000; BACKGROUND: #ffffff; TEXT-DECORATION: none}
a:hover {BACKGROUND: #dddddd; TEXT-DECORATION: none}
a:visited {COLOR: #990000; TEXT-DECORATION: none}
</style>
<script language="JavaScript">
<!--
// Объявляем глобальные переменные
// Входящий документ
var source;
// Преобразование
var stylesheet;
// Результат
var result;
// Функция, выполняющая действия по инициализации
function init() {
// Инициализируем ссылку на объект входящего документа
source = document.all['source'];
// Загружаем входящий документ
source.load('source.xml');
// Инициализируем ссылку на объект преобразования
stylesheet = document.all['stylesheet'];
// Загружаем документ преобразования
stylesheet.load('stylesheet.xsl');
// Находим элемент, в который мы будем выводить
// результат обработки
result = document.all['result'];
}
// Функция, выполняющая "раскрытие"
//определенной ветки дерева категорий.
function expand(id) {
// Получаем ссылку на атрибут select
// объявления параметра current
var attSelect = stylesheet.selectSingleNode(
"/xsl:stylesheet/xsl:param[@name='current']/@select");
// Изменяем значение этого атрибута. Одинарные кавычки необходимы
// для того, чтобы новое значение воспринималось как литерал.
attSelect.nodeValue = "'" + id + "'";
// Выполняем преобразование
strResult = source.transformNode(stylesheet);
// Обновляем страницу
result.innerHTML = strResult;
}
//-->
</script>
</head>
<body>
<!-- Объект, представляющий входящий документ -->
<object
width="0"
height="0"
classid="clsid:f5078f32-c551-11d3-89b9-0000f81fe221">
<param name="async" value="false">
<param name="validateOnParse" value="false">
</object>
<!-- Объект, представляющий документ преобразования -->
<object
width="0"
height="0"
classid="clsid:f5078f32-c551-11d3-89b9-0000f81fe221">
<param name="async" value="false">
<param name="validateOnParse" value="false">
</object>
<a href="javascript:expand(' ')">Каталог</а>
<!-- В этом элементе мы будем выводить результат -->
<div/>
</body>
</html>
В браузере эта страница будет выглядеть следующим образом (рис. 9.10).
Рис. 9.10. Динамический каталог на HTML с использованием JavaScript, MSXML на основе XML и XSLT
- XSLT и другие языки
- Выполнение XSLT-преобразований в Object Pascal
- Выполнение XSLT-преобразований в C/C++
- Выполнение XSLT-преобразований в PHP
- Выполнение XSLT-преобразований в JavaScript
- Выполнение XSLT-преобразований в VBScript/ASP
- Выполнение XSLT-преобразований в Python
- Выполнение XSLT-преобразований в PL/SQL
- Выполнение XSLT-преобразований в Java
- Краткие выводы
- Глава 9 Совместное использование XSLT с другими языками программирования
- Выполнение XSLT-преобразований в C
- Использование отдельных процессоров XSLT
- 8.4.5. Выполнение внешних команд
- Листинг 9.3. Пример JavaScript-файла, закрывающего всплывающее окно
- Глава 12 Краткий курс JavaScript
- Выполнение макросов
- Практическая работа 46. Выполнение расчетов с использованием Мастера функций
- Популярность XSLT-процессоров
- Преобразование в XSL-FO при помощи таблицы стилей XSLT
- Справочник по базовому JavaScript
- 9.4.2. Регистрация времени, потраченного на выполнение задания