суббота, 28 августа 2010 г.

XML и ADO.NET – Часть 3

Элемент XSL:IF - фильтр

Рассмотрим теперь способы фильтрации строк таблицы. Первый пример использует старый синтаксис. В нем условие фильтрации указывается непосредственно в атрибуте select (ex04-1.xml, ex04-1.xsl).

Ниже приведена строка, в которую мы внесли необходимые изменения.

xsl:for-each select="tutorial/enimals/dogs/dog[dogWeight$gt$10] " order-by="number(dogWeight); dogName;">

И таблица результатов.

Кличка

Вес

Цвет

Шарик

18 кг

рыжий с черными подпалинами

Трезор

25 кг

черный

Вы видите, что в таблице остались только те собаки, чей вес превышает 10 кг, причем первым стоит Шарик, чей вес меньше.

Все дальнейшие примеры в этом параграфе работают только под управлением XML-парсера версии 3.

Более гибкие возможности нам предоставляет новый синтаксис (ex04-2.xml, ex04-2.xsl). Обратите внимание - в новом синтаксисе атрибут order-by в элементе xsl:for-each не поддерживается, вместо него мы вставили два элемента xsl:sort.

<xsl:sort order="ascending" select="number(dogWeight)"/>
<xsl:sort order="ascending" select="dogName"/>

Кроме того, условие фильтра у нас вынесено в отдельный элемент xsl:if.

<xsl:if test="dogWeight&gt;10">

Не забывайте указывать конечный тег элемента xsl:if.

<xsl:if test="dogWeight&gt;10">
<tr bgcolor="#F5F5F5">
<td><xsl:value-of select="dogName"/></td>
<td align="right"><xsl:value-of select="dogWeight"/> <xsl:value-of select="dogWeight/@caption"/></td>
<td><xsl:value-of select="dogColor"/></td>
</tr>
</xsl:if>

В этом примере таблица результатов полностью аналогична предыдущей.

Кличка

Вес

Цвет

Шарик

18 кг

рыжий с черными подпалинами

Трезор

25 кг

черный

Полностью преимущества нового синтаксиса проявляются при использовании функций.

Рассмотрим следующий пример (ex04-3.xml, ex04-3.xsl). В этом примере используется функция position(), определяющая порядковый номер фрагмента в исходном XML-файле.

Соответствующий элемент xsl:if.

<xsl:if test="position()<3">

Результат.

Кличка

Вес

Цвет

Шарик

18 кг

рыжий с черными подпалинами

Тузик

10 кг

белый с черными пятнами

Продемонстрируем теперь использование более интересных функций - start-with(string,startSubstring) и contains(string,anySubstring). Функция start-with(string,startSubstring) проверяет, начинается ли строка string с подстроки  startSubstring. Пример - ex04-4.xml, ex04-4.xsl).

Синтаксис элемента xsl:if.

<xsl:if test="starts-with($varDogName,$varStartWith)">

В этом элементе мы использовали переменные. Значения переменных были инициализированы ранее

<xsl:variable name="varStartWith">Т</xsl:variable>
<xsl:for-each select="tutorial/enimals/dogs/dog">
<xsl:variable name="varDogName"><xsl:value-of select="dogName"/></xsl:variable>

Переменная varStartWith представляет собой подстроку, с которой должны начинаться требуемые нам клички. Она не меняется, поэтому инициализируется перед циклом. Переменная varDogName содержит кличку собаки, она меняется на каждом шаге цикла и, соответственно, инициализируется в теле цикла.

Результат.

Кличка

Вес

Цвет

Тузик

10 кг

белый с черными пятнами

Трезор

25 кг

черный

Функция contains(string,anySubstring) проверяет, содержит ли строка string подстроку  anySubstring. Пример - ex04-5.xml, ex04-5.xsl.

Синтаксис элемента xsl:if.

<xsl:if test="contains($varDogName,$varStartWith)">

Этот пример полностью аналогичен предыдущему.

Результат.

Кличка

Вес

Цвет

Бобик

2 кг

бело-серый

Трезор

25 кг

черный

Два элемента xsl:if, вложенные друг в друга, дают нам эффект оператора AND (ex04-6.xml, ex04-6.xsl).

Соответствующий фрагмент XSL-файла.

<xsl:if test="dogWeight&gt;10">
<xsl:if test="dogWeight&lt;20">
...
</xsl:if>
</xsl:if>

Результат.

Кличка

Вес

Цвет

Шарик

18 кг

рыжий с черными подпалинами

Можно добиться и эффекта оператора OR. Для этого нам нужно включить два цикла, в каждом из которых формируется своя выборка   (ex04-7.xml, ex04-7.xsl).

Соответствующий фрагмент XSL-файла.

<xsl:for-each select="tutorial/enimals/dogs/dog">
<xsl:sort order="ascending" select="number(dogWeight)"/>
<xsl:if test="dogWeight&lt;10">
<tr bgcolor="#F5F5F5">
<td><xsl:value-of select="dogName"/></td>
<td align="right"><xsl:value-of select="dogWeight"/> <xsl:value-of select="dogWeight/@caption"/></td>
<td><xsl:value-of select="dogColor"/></td>
</tr>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="tutorial/enimals/dogs/dog">
<xsl:sort order="ascending" select="number(dogWeight)"/>
<xsl:if test="dogWeight&gt;15">
<tr bgcolor="#F5F5F5">
<td><xsl:value-of select="dogName"/></td>
<td align="right"><xsl:value-of select="dogWeight"/> <xsl:value-of select="dogWeight/@caption"/></td>
<td><xsl:value-of select="dogColor"/></td>
</tr>
</xsl:if>
</xsl:for-each>

Результат.

Кличка

Вес

Цвет

Бобик

2 кг

бело-серый

Шарик

18 кг

рыжий с черными подпалинами

Трезор

25 кг

черный

Если сортировка не требуется, то можно вставить два элемента xsl:if в один элемент xsl:for-each.

Элемент XSL:IF - улучшение внешнего вида таблиц

Элемент xsl:if можно применять не только для фильтрации строк выборки. Очевидно, что он может быть полезен и во многих других областях. В этом параграфе мы разберем пример использования элемента xsl:if для улучшения внешнего вида таблицы. Заодно мы продемонстрируем реальное использование функции position(). Мы будем использовать эту функцию для того, чтобы чередовать цвет четных и нечетных строк таблицы  (ex04-8.xml, ex04-8.xsl).

Фрагмент XSL-файла, который отвечает за требуемое чередование.

<tr>
<xsl:if test="position() mod 2 = 0">
<xsl:attribute name="bgcolor">#CCCCCC</xsl:attribute>
</xsl:if>

С элементом xsl:if и с функцией position() мы уже знакомы. Оператор mod дает нам остаток от деления на 2. А элемент xsl:attribute позволяет нам динамически подставлять в файл результатов различные атрибуты. Это очень мощный элемент, мы разберем еще одно применение этого элемента в следующем параграфе. А сейчас приведем для полноты картины таблицу результатов.

Кличка

Вес

Цвет

Шарик

18 кг

рыжий с черными подпалинами

Тузик

10 кг

белый с черными пятнами

Бобик

2 кг

бело-серый

Трезор

25 кг

черный

Динамическое формирование атрибутов на примере параметров ссылки в теге <a>

Предположим теперь, что в каждой строке таблицы нам нужно сделать ссылку на некоторую страницу и передать на эту страницу два параметра - кличку и вес собаки. Понятно, что для каждой строки эти параметры - свои, и их нельзя прописать явно в XSL-файл. Тем не менее задача легко решается при помощи элемента xsl:attribute.

Мы не будем здесь строить специальный пример, ограничимся только соответствующим фрагментом XSL-файла.

<td>
<!-- Create reference to display details. Parameters - Dog Name and Dog Weight -->
<a target="_blank">
<xsl:attribute name="href">DisplayDetails.html?dogName=<xsl:value-of select="dogName"/>&amp;dogWeight=<xsl:value-of select="dogWeight"/></xsl:attribute>
<xsl:attribute name="title">To view some more details about <xsl:value-of select="dogName"/> click to dog name</xsl:attribute>
<xsl:value-of select="dogName"/>
</a>
</td>

В этом примере в ячейке таблицы мы размещаем ссылку на страницу с подробными описаниями. Ссылка указывается в атрибуте href тега <a>. Поскольку  на страницу передаются два параметра, значения которых берутся из XML-файла, этот атрибут формируется динамически. Обратите также внимание - символ & (амперсанд), разделяющий передаваемые параметры, записывается в XSL-файле в виде &amp;. Во втором атрибуте нам нужна всплывающая подсказка (атрибут title), которая появляется при наведении курсора мыши на ссылку. Текст этой подсказки тоже меняется динамически. Наконец, статический атрибут target мы разместили непосредственно в теге <a>.

И, наконец, мы ознакомились с комментариями в XSL-файлах. Это вторая строка приведенного фрагмента.

<!-- Create reference to display details. Parameters - Dog Name and Dog Weight -->

На этом мы завершим рассмотрение возможностей чистого XSLT и перейдем к последнему параграфу в этом документе - к динамическому изменению содержимого Web-страницы при помощи возможностей JavaScript и XML/XSLT без каких-либо дополнительных обращений к базе данных.

JavaScript и XML

Объединим теперь наши знания XML с возможностями, которые нам предоставляет JavaScript. Предположим, что нам нужно иметь возможность динамически изменять сортировку столбцов таблицы при щелчке на заголовке того или иного столбца. Понятно, что для этого нам нужно иметь один XML-файл, содержащий строки таблицы, несколько XSL-файлов, каждый из которых содержит требуемую сортировку и нечто, что объединит это все вместе и заставит работать.

Перейдем к реализации этой программы.

В качестве XML-файла возьмем привычный нам файл со списком собак - ex05-1.xml. Обратите внимание - мы убрали из файла ссылку на XSL-файл - нам нужно менять шаблон преобразования динамически.

Создадим также три XSL-файла, в каждом из которых у нас будет свой элемент xsl:sort, задающий сортировку строк - ex05-1a.xsl, ex05-1b.xsl, ex05-1c.xsl.

Приведем здесь текст элемента xsl:sort для каждого файла

<xsl:sort order="ascending" select="dogName"/>

<xsl:sort order="ascending" select="number(dogWeight)" data-type="number"/>

<xsl:sort order="ascending" select="dogColor"/>

Теперь нам осталось только объединить все это вместе. Ниже мы полностью приводим текст файла ex05-1.htm, сопроводив его необходимыми комментариями.

<html>
<head>
<script language="JavaScript">
var source;
var style;
Функция инициализации необходимых объектов. В этой же функции выводится первоначальный вариант на экран.
function init() {
Создаем объект для файла - источника данных.
source = new ActiveXObject("Microsoft.XMLDOM");
source.async = false;
Создаем объект для файла с шаблоном преобразования (для файла стиля).
style = new ActiveXObject("Microsoft.XMLDOM");
style.async = false;
Загружаем записи в файл - источник данных.Записи берем из существующего XML-файла.
source.load("ex05-1.xml");
Загружаем файл стиля. Первоначальная сортировка - по цвету.
style.load("ex05-1a.xsl");
Теперь нам нужно вывести информацию на экран. Внимательно проанализируйте синтаксис и запомните его.
document.all.item("xslresult").innerHTML = source.transformNode(style);
return true;
}
Сортируем записи по кличке.
function orderByNick() {
style.load("ex05-1a.xsl");
document.all.item("xslresult").innerHTML = source.transformNode(style);
return true;
}
Сортируем записи по весу.
function orderByWeight() {
style.load("ex05-1b.xsl");
document.all.item("xslresult").innerHTML = source.transformNode(style);
return true;
}
Сортируем записи по цвету.
function orderByColor() {
style.load("ex05-1c.xsl");
document.all.item("xslresult").innerHTML = source.transformNode(style);
return true;
}
</script>
</head>
При загрузке страницы создадим все необходимые объекты и выведем первоначальный вариант на экран.
<body onLoad="init()">
<div id="xslresult">
<!-- Здесь будет размещаться окончательный вариант HTML-содержимого  -->
</div>
</body>
</html>
Мы добились своей цели - при щелчке мышью на заголовке столбца строки сортируются в соответствии со значениями в выбранном столбце.

В заключение приведем реальный пример из складской системы. По своим функциональным возможностям этот пример полностью аналогичен предыдущему, детали только в реализации JavaScript-функций и в конкретных данных.

Основная страница - Mgr.html. Эта страница содержит два фрейма - MgrTop.html (страница управления, содержащая все JavaScript-функции) и MgrMain.html - страница-пустышка, в которую в дальнейшем подставляется результат преобразования XML-файла. Страница данных - MgrMainXml.xml. Эти данные получены в результате запроса к реальной базе данных. Для разработчиков на Cache приведем текст CSP-страницы, которая служит источником данных - MgrMainXml.csp. Мы пошли на некоторые ухищрения и вместо реальных страниц MgrTop.html и MgrMainXml.csp подгружаем их копии с расширением *.txt для того, чтобы в браузере можно было увидеть непосредственно исходный код страницы. Сами страницы MgrTop.html и MgrMainXml.csp тоже присутствуют в соответствующей директории, при этом MgrTop.html работает в нашем примере, а MgrMainXml.csp, естественно, бесполезна без Cache-сервера.

На этом наше введение в XML-XSLT заканчивается.

Комментариев нет:

Отправить комментарий