|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
2003 г
XML и XSLT в примерах для начинающихЛеонов Игорь ВасильевичПредварительная
подготовка Предварительная подготовкаДля того, чтобы работать с данным документом, вам необходимо располагать как минимум браузером Internet Explorer версии 5.0 и выше. При этом будут работать некоторые из приведенных в тексте примеров. Для того, чтобы у вас работали все
примеры, необходимо установить XML-парсер версии 3.
Если пример работает только под управлением
XML-парсера версии 3, то в каждом случае это
оговаривается особо. Отметим, что версии IE вплоть
до 5.5 используют более ранние версии парсера,
поэтому устанавливать его все равно придется. О
более старших версиях IE узнайте самостоятельно. А теперь перейдем к основной части нашего документа. ВведениеРассмотрим простой пример XML-файла (ex01.xml). <?xml version="1.0"
encoding="WINDOWS-1251"?> Если мы откроем этот файл в браузере Internet Explorer, то мы увидим тот же самый текст, который приведен выше, вместе со всеми тегами и служебной информацией. Но нам не нужны теги и служебная информация! Мы хотим видеть только ту информацию, которая относится к делу, а при помощи тегов - управлять внешним видом этой информации. Эта задача решается легко и просто: необходимо к XML-файлу добавить шаблон преобразования - XSL-файл. Перепишем наш XML-файл в следующем виде (ex01-1.xml). <?xml version="1.0"
encoding="WINDOWS-1251"?> И создадим XSL-файл ex01-1.xsl. Текст файла приведен ниже. <xsl:stylesheet
version="1.0" xmlns:xsl="http://www.w3.org/TR/WD-xsl"> Если мы теперь откроем файл ex01-1.xsl в браузере Internet Explorer, то мы увидим, что наша задача решена, - на экране осталась только необходимая нам информация, все теги исчезли. Результат, который вы получите на экране браузера, приведен ниже.
"Заметки об XSL" Леонов Игорь Васильевич
Легко также увидеть, что порядок вывода строк у нас определяется только содержанием шаблона преобразования - XSL-файла. При необходимости шаблон можно легко поменять, абсолютно не меняя наш основной XML-файл. Перепишем XML-файл. Информационную часть изменять не будем, а шаблон укажем другой ex01-2.xml. <?xml version="1.0"
encoding="WINDOWS-1251"?> Создадим XSL-файл ex01-2.xsl. Текст файла приведен ниже. <xsl:stylesheet
version="1.0" xmlns:xsl="http://www.w3.org/TR/WD-xsl"> Если мы теперь откроем файл ex01-2.xsl в браузере Internet Explorer, то результат будет другим. Леонов Игорь Васильевич "Заметки об XSL" Отметим теперь момент, который является ключевым для разработчиков баз данных. Информация в XML-странице появляется, как правило, в результате запроса к базе данных. Запрос к базе данных в многопользовательской среде - это весьма дорогостоящая операция. Предположим теперь, что у нас нет XML и мы формируем стандартные статические HTML-страницы. В этом случае для решения задачи простого преобразования внешнего представления информации, например, для изменения сортировки, у нас есть два способа решения проблемы: выполнить запрос и сохранить результаты в каком-либо временном буфере на сервере или каждый раз при изменении внешнего представления выполнять новый запрос и формировать HTML-страницу заново. Первый способ требует трудоемкого программирования, второй способ значительно увеличивает нагрузку на сервер базы данных, производительность которого часто является узким местом системы, - пользователю всегда хочется получать результаты быстрее. XML и XSL - это исчерпывающее решение описанной выше проблемы. Фактически XML-страница - это и есть временный буфер для результатов запросов. Только вместо нестандартного и трудоемкого программирования мы теперь используем стандартный механизм XSL. Есть и еще одно соображение, которое может быть существенным для разработчиков баз данных. Большинство современных СУБД могут форматировать результаты запроса к базе данных в виде XML-файла. То есть при построении интерфейса пользователя в рамках технологии XML и XSL мы добиваемся определенной независимости от поставщика СУБД. В части организации вывода - практически полной независимости. А эта часть весьма велика в большинстве прикладных систем, ориентированных на работу с базами данных. Конечно, помимо вывода есть еще ввод и серверная обработка бизнес-логики, но здесь вам придется искать какие-то иные решения. Первые шагиРазберем теперь более подробно первый пример. Напомним его текст. <?xml version="1.0"
encoding="WINDOWS-1251"?> Первая строка информирует браузер о том, что файл имеет формат XML. Атрибут version является обязательным. Атрибут encoding не является обязательным, но если у вас в тексте есть русские буквы, то необходимо вставить этот атрибут, в противном случае XML-файл просто не будет обрабатываться, - вы получите сообщение об ошибке. Следующие строки - это тело XML-файла. Оно состоит из элементов, которые в совокупности образуют древовидную структуру. Элементы идентифицируются тегами и могут быть вложены друг в друга. Элементы могут иметь атрибуты, значения которых тоже могут обрабатываться в соответствии с шаблоном. На верхнем уровне XML-файла всегда находится один элемент. То есть файл вида <?xml version="1.0"
encoding="WINDOWS-1251"?> не будет обрабатываться браузером. Для преобразования в корректный XML-файл нужно добавить теги элемента верхнего уровня, например <?xml version="1.0"
encoding="WINDOWS-1251"?> Отметим, что имена тегов чувствительны к регистру символов. Подробнее об этом можно прочесть в любой книге по XML - элементам и атрибутам в этих книгах уделяется достаточно большое внимание. Перейдем теперь к шаблону преобразования - к XSL-файлу. Задача XSL-файла - преобразовать дерево XML-файла в другое дерево, которое, например, будет соответствовать формату HTML и может быть изображено на экране браузера с учетом форматирования, выбора шрифтов и т.п. Для того, чтобы браузер выполнил необходимое преобразование, нужно в XML-файле указать ссылку на XSL-файл <?xml version="1.0"
encoding="WINDOWS-1251"?> Рассмотрим теперь текст XSL-файла <xsl:stylesheet
version="1.0" xmlns:xsl="http://www.w3.org/TR/WD-xsl"> Первая строка файла содержит тег элемента xsl:stylesheet. Атрибуты элемента - номер версии и ссылка на пространство имен. Эти атрибуты элемента xsl:stylesheet являются обязательными. В нашем случае пространство имен - это все имена элементов и их атрибутов, которые могут использоваться в XSL-файле. Для XSL-файлов ссылка на пространство имен является стандартной. Заметим, что XSL-файл является одной из разновидностей XML-файлов. Он не содержит пользовательских данных, но формат его тот же самый. Файл содержит элемент верхнего уровня xsl:stylesheet, а далее идет дерево правил преобразования. В настоящем документе мы не будем подробно пояснять, что означает каждый элемент XSL-файла. Мы будем приводить различные примеры и показывать результат в каждом примере. Читатель сможет самостоятельно сопоставить различные элементы XSL-файла и инициируемые этими элементами преобразования исходного XML-файла с пользовательской информацией. В дальнейшем тексты XML- и XSL-файлов мы будем приводить в черно-белом варианте. Вы всегда сможете открыть реальный файл и посмотреть все в цвете. При необходимости закомментируйте ссылку на XSL-файл. Синтаксис комментария следующий - <!-- Текст комментария -->. В текст комментария нельзя вставлять символы --. В первом примере мы посмотрели, как с помощью элемента xsl:value-of можно вывести в HTML-формате содержание элемента (текст, заключенный между тегами). Теперь мы посмотрим, как при помощи того же самого элемента можно вывести значение атрибута элемента. Рассмотрим следующий XML-файл ex02-1.xml <?xml version="1.0"
encoding="WINDOWS-1251"?> В этом файле информация хранится не в содержании элементов, а в виде значений атрибутов. Файл ex02-1.xsl имеет вид <xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/TR/WD-xsl"> Обратите внимание на синтаксис ссылки на атрибут элемента - //dog/@name. Имя элемента и имя атрибута разделены парой символов "/@". В остальном синтаксис тот же самый, что и для ссылки на содержание элемента. Результат имеет следующий вид: Собака: Шарик. 18 кг, рыжий с черными подпалинами. Обратим теперь внимание на следующий момент. В XSL-файле мы никак не использовали элемент tutorial. На самом деле можно было использовать полный путь. Перепишем наш XML-файл, увеличив глубину дерева (ex02-2.xml) <?xml version="1.0"
encoding="WINDOWS-1251"?> Файл ex02-2.xsl имеет вид <xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/TR/WD-xsl"> Результат будет тем же самым. Собака: Шарик. 18 кг, рыжий с черными подпалинами. В этом примере мы использовали полную ссылку для значений атрибутов. При выводе одиночных значений оба варианта - полная и сокращенная ссылка - работают одинаково. На этом мы закончим разбор примеров с выводом одиночных значений и перейдем к выводу табличной информации - к выводу результатов запроса. Вывод результатов запросаДо тех пор, пока мы работаем с несколькими реквизитами одного и того же объекта, разницы между XML и HTML практически нет. Однако стоит нам перейти к информации, содержащей несколько строк, как выгоды XML становятся очевидны. Но прежде чем перейти к выгодам, научимся выводить на экран простую таблицу. Рассмотрим следующий XML-файл - ex03.xml. Текст его приведен ниже. <?xml version="1.0"
encoding="WINDOWS-1251"?> Предположим, что это результат запроса к базе данных и выведем на экран соответствующую таблицу. Простая таблицаПервый шаг - это, как всегда, добавление шаблона преобразования. Модифицируем наш файл, добавив в него ссылку на шаблон. В результате получим файл ex03-1.xml. В этот файл добавлен шаблон преобразования ex03-1.xsl. Рассмотрим этот шаблон подробнее. Вот его текст. <?xml version="1.0" encoding="WINDOWS-1251" ?> Первая строка - новая для вас в XSL-файле (но не в XML-файлах!). Она говорит о том, что в XSL-файле нужно нормально воспринимать русские буквы. Без этой строки браузер не сможет корректно обработать русский текст в XSL-файле. Следующие две строки шаблона являются уже привычными. Следующие шесть строк - это строка, содержащая заголовки столбцов таблицы. Конструкция для извлечения текста заголовков таблицы вам уже знакома. А вот десятая строка тоже является новой: <xsl:for-each select="tutorial/enimals/dogs/dog"> Этот элемент шаблона позволяет выбрать и просмотреть все группы информации, полный путь к которым задается списком тегов "tutorial/enimals/dogs/dog". Обратите внимание - путь задается полностью, ни один из тегов опустить нельзя. Далее в ячейки таблицы помещается информация о наших собаках. В отличие от первых примеров путь к соответствующей информации тоже задается полностью. Попробуем, например, разместить информацию о кличке чуть-чуть иначе ex03-2.xml: <dogName> Если мы в соответствующем XSL-файле поставим ссылку <xsl:value-of select="dogNick"/>, то в соответствующем столбце никакой клички мы не увидим. Ссылка должна быть полной - <xsl:value-of select="dogName/dogNick"/>. Вы можете самостоятельно поэкспериментировать с файлом ex03-2.xsl. Правильный результат приведен ниже.
СортировкаВ предыдущих примерах порядок строк в таблице полностью соответствовал группам тегов в XML-файле. Этот порядок можно изменять. Добавим в тег <xsl:for-each select="tutorial/enimals/dogs/dog"> атрибут order-by <xsl:for-each select="tutorial/enimals/dogs/dog" order-by="dogName"> Наша таблица примет вид (ex03-3.xml, ex03-3.xsl).
Более интересные результаты мы получим, если попытаемся отсортировать таблицу по столбцу "Вес". Вначале попробуем сделать по аналогии с предыдущим примером - атрибут order-by="dogName" заменим на order-by="dogWeight". Результат приведен ниже (ex03-4.xml, ex03-4.xsl).
Таблица действительно отсортирована по столбцу "вес", но это не числовая, а строковая сортировка! Для того, чтобы браузер воспринял значения как числа, ему необходимо об этом сказать, - вместо order-by="dogWeight" необходимо написать order-by="number(dogWeight)". Теперь мы получили правильный результат (ex03-5.xml, ex03-5.xsl).
Приведем теперь пример сортировки по нескольким столбцам. Различные элементы в атрибуте order-by должны разделяться символом ";" - order-by="number(dogWeight); dogName" (ex03-6.xml, ex03-6.xsl). Таблица приведена ниже.
Следующий пример работает только под управлением XML-парсера версии 3. В нем строки сортируются по одному столбцу - по кличке собаки. Этот пример уже приводился выше, однако теперь мы используем новый синтаксис (ex03-7.xml, ex03-7.xsl). Отметим разницу. При использовании нового синтаксиса используется ссылка на другое пространство имен <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> Это очень важный момент, и его никогда нельзя упускать из виду. Кроме того, мы убрали атрибут order-by в элементе xsl:for-each и добавили другой элемент <xsl:sort order="ascending" select="dogName"/> Если элемент xsl:sort присутствует в элементе xsl:for-each, то он всегда должен стоять сразу после элемента xsl:for-each. Синтаксис элемента xsl:sort достаточно очевиден. В нем используются два атрибута: атрибут order - способ сортировки (по возрастанию или по убыванию) и атрибут select - имя поля, по которому производится сортировка. Если нам нужно отсортировать по первому элементу, как в данном примере, то вместо "dogName" можно было поставить точку - ".", для других элементов нужно указывать его имя, например "dogColor", если нам нужно отсортировать записи по цвету собаки. На самом деле атрибутов может быть пять - select, lang, data-type, order и case-order, но мы не будем здесь рассматривать все эти атрибуты, поскольку здесь мы не преследуем цель дать полное описание всех элементов, используемых в XSL, и их атрибутов. Таблица результатов приведена ниже.
С использованием нового синтаксиса легко сменить сортировку по возрастанию на сортировку по убыванию (ex03-8.xml, ex03-8.xsl). Этот пример работает только под управлением XML-парсера версии 3. Разница заключается в одной строке <xsl:sort order="descending" select="dogName"/> Мы изменили значение атрибут order - значение ascending заменено на descending. Таблица результатов приведена ниже.
Покажем теперь сортировку по нескольким полям (ex03-9.xml, ex03-9.xsl). Этот пример работает только под управлением XML-парсера версии 3. В этом примере у нас фигурируют две строки с элементом xsl:sort. <xsl:sort order="ascending"
select="number(dogWeight)" data-type="number"/> Строки вначале сортируются по весу собаки, а затем по их кличкам в алфавитном порядке. Обратите внимание - для того, чтобы сортировка выполнялась в числовой последовательности, в элемент xsl:sort мы добавили атрибут data-type. Таблица результатов приведена ниже.
Заменив значение атрибута order by на descending, мы легко сгруппируем записи о собаках с одинаковым весом так, что клички будут идти в обратном алфавитном порядке. Соответствующий пример вы легко построите сами.
Элемент 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;"> И таблица результатов.
Вы видите, что в таблице остались только те собаки, чей вес превышает 10 кг, причем первым стоит Шарик, чей вес меньше. Все дальнейшие примеры в этом параграфе работают только под управлением XML-парсера версии 3. Более гибкие возможности нам предоставляет новый синтаксис (ex04-2.xml, ex04-2.xsl). Обратите внимание - в новом синтаксисе атрибут order-by в элементе xsl:for-each не поддерживается, вместо него мы вставили два элемента xsl:sort. <xsl:sort order="ascending"
select="number(dogWeight)"/> Кроме того, условие фильтра у нас вынесено в отдельный элемент xsl:if. <xsl:if test="dogWeight>10"> Не забывайте указывать конечный тег элемента xsl:if. <xsl:if
test="dogWeight>10"> В этом примере таблица результатов полностью аналогична предыдущей.
Полностью преимущества нового синтаксиса проявляются при использовании функций. Рассмотрим следующий пример (ex04-3.xml, ex04-3.xsl). В этом примере используется функция position(), определяющая порядковый номер фрагмента в исходном XML-файле. Соответствующий элемент xsl:if. <xsl:if test="position()<3"> Результат.
Продемонстрируем теперь использование более интересных функций - 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> Переменная varStartWith представляет собой подстроку, с которой должны начинаться требуемые нам клички. Она не меняется, поэтому инициализируется перед циклом. Переменная varDogName содержит кличку собаки, она меняется на каждом шаге цикла и, соответственно, инициализируется в теле цикла. Результат.
Функция contains(string,anySubstring) проверяет, содержит ли строка string подстроку anySubstring. Пример - ex04-5.xml, ex04-5.xsl. Синтаксис элемента xsl:if. <xsl:if test="contains($varDogName,$varStartWith)"> Этот пример полностью аналогичен предыдущему. Результат.
Два элемента xsl:if, вложенные друг в друга, дают нам эффект оператора AND (ex04-6.xml, ex04-6.xsl). Соответствующий фрагмент XSL-файла. <xsl:if test="dogWeight>10"> Результат.
Можно добиться и эффекта оператора OR. Для этого нам нужно включить два цикла, в каждом из которых формируется своя выборка (ex04-7.xml, ex04-7.xsl). Соответствующий фрагмент XSL-файла. <xsl:for-each
select="tutorial/enimals/dogs/dog"> Результат.
Если сортировка не требуется, то можно вставить два элемента xsl:if в один элемент xsl:for-each. Элемент XSL:IF - улучшение внешнего вида таблицЭлемент xsl:if можно применять не только для фильтрации строк выборки. Очевидно, что он может быть полезен и во многих других областях. В этом параграфе мы разберем пример использования элемента xsl:if для улучшения внешнего вида таблицы. Заодно мы продемонстрируем реальное использование функции position(). Мы будем использовать эту функцию для того, чтобы чередовать цвет четных и нечетных строк таблицы (ex04-8.xml, ex04-8.xsl). Фрагмент XSL-файла, который отвечает за требуемое чередование. <tr> С элементом xsl:if и с функцией position() мы уже знакомы. Оператор mod дает нам остаток от деления на 2. А элемент xsl:attribute позволяет нам динамически подставлять в файл результатов различные атрибуты. Это очень мощный элемент, мы разберем еще одно применение этого элемента в следующем параграфе. А сейчас приведем для полноты картины таблицу результатов.
Динамическое формирование атрибутов на примере параметров ссылки в теге <a>Предположим теперь, что в каждой строке таблицы нам нужно сделать ссылку на некоторую страницу и передать на эту страницу два параметра - кличку и вес собаки. Понятно, что для каждой строки эти параметры - свои, и их нельзя прописать явно в XSL-файл. Тем не менее задача легко решается при помощи элемента xsl:attribute. Мы не будем здесь строить специальный пример, ограничимся только соответствующим фрагментом XSL-файла. <td> В этом примере в ячейке таблицы мы размещаем ссылку на страницу с подробными описаниями. Ссылка указывается в атрибуте href тега <a>. Поскольку на страницу передаются два параметра, значения которых берутся из XML-файла, этот атрибут формируется динамически. Обратите также внимание - символ & (амперсанд), разделяющий передаваемые параметры, записывается в XSL-файле в виде &. Во втором атрибуте нам нужна всплывающая подсказка (атрибут 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> В заключение приведем реальный пример из складской системы. По своим функциональным возможностям этот пример полностью аналогичен предыдущему, детали только в реализации 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 заканчивается. Заключительные замечанияВ процессе работы над этим документом использовались примеры Microsoft и примеры с сайта http://www.zvon.org. Рекомендую всем, кто интересуется Web-технологиями, посетить этот сайт. Вы найдете там полные руководства и большое количество примеров по HTML, CSS, различным аспектам XML и т.п. Все материалы на английском языке. Многие документы, например, XSLT Reference можно скачать в виде архива и держать под рукой. Книга Эрика Рея "Изучаем XML", Москва, "Символ", 2001. В этой книге - великолепное введение в XML и смежные стандарты (XPath, XSL и т.п.) Объем материала многократно превышает то, что есть в данном обзоре. Плюс качественный разбор основных понятий и идеи возможных применений различных технологий в реальных проектах. Рекомендую также русскоязычный перевод спецификации "Язык преобразований XSL 1.0" (XSL Transformations 1.0), расположенный по адресу http://www.online.ru/it/helpdesk/xslt01.htm. Большое спасибо Radj I. Halfin, который подсказал мне решение проблемы с русскими буквами в XSL-файлах. Надеемся, что информации, приведенной в этом документе в совокупности с вашей фантазией и XSLT Reference, вам будет достаточно для воплощения в жизнь самых смелых замыслов. |
|
CITForum © 1997–2025