Рассылка закрыта
При закрытии подписчики были переданы в рассылку "LinuxCenter News Channel: новости Linux" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
Linux Gazette на русском
| Информационный Канал Subscribe.Ru |
Linux Gazette на русском | Выпуск #130 | Тираж 8585 экз.
Здравствуйте! Сегодня вашему вниманию предлагается статья, посвящённая
eXtensible Stylesheet Language for Transformations (Расширяемый Язык Стилей
для Преобразований), который, как правило, используется для преобразования
данных из формата XML в формат HTML.
Спасибо за перевод Андрею Киселёву!
Александр Куприн
Работаем с
XSLT.
Автор: Daniel
Guerrero
Перевод: Андрей Киселев
XSLT (от англ. eXtensible Stylesheet Language for Transformations -- Расширяемый Язык Стилей для Преобразований) используется, по большей части, для преобразования данных из формата XML в формат HTML. Однако, XSLT может использоваться для преобразования из XML (или любого другого формата, использующего пространство имен xml, подобно RDF) в любой другой формат, даже в простой текст.
Консорциум W3 определяет три составные части языка XSL (от англ. eXtensible Stylesheet Language -- Расширяемый Язык Стилей): XSLT, XPath (язык путей и выражений, используемый в XSLT для доступа к отдельным частям XML-документа) и XSL Formatting Objects -- словарь, определяющий семантику форматирования документов.
Встречаем XSLT
Прежде всего следует указать, что наш документ использует стилистику XML и импортировать пространство имен XML:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
...
</xsl:stylesheet>
Далее, основным элементом, который мы будем использовать,
является xsl:template match. Этот элемент вызывается
всякий раз, когда имя xml-узла совпадает со значением атрибута
xsl:template match:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/"> <!-- оператор '/' взят из XPath и ассоциируется с корневым элементом -->
<!-- выполнить какие либо действия с вложенными узлами -->
</xsl:template>
</xsl:stylesheet>
Внутри элемента xsl:template match следует указать
вложенные узлы элементом: xsl:value-of select. Давайте
для начала создадим xml-документ, содержащий некоторую информацию:
<!-- hello.xml --> <hello> <text>Hello World!</text> </hello>
Так должно выглядеть xslt-преобразование, которое вынимает узел
text из корневого элемента (hello):
<!-- hello.xsl -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<title> <xsl:value-of select="//text"/> </title>
<!-- в данном случае '//text' это: 'hello/text', но, поскольку я ленив сам по себе, я делаю это проще, используя выражение XPath -->
</head>
<body>
<p>
Содержимое узла <b>text</b> корневого элемента: <b><xsl:value-of select="//text"/></b>
</p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
В результате получится следующий HTML-документ:
<!-- hello.html -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Hello World! </title>
</head>
<body>
<p>
Содержимое узла <b>text</b> корневого элемента: <b>Hello World!</b>
</p>
</body>
</html>
Получение значений атрибутов
конструкция @att возвращает значение атрибута
att. Например:
<!-- hello_style.xml --> <hello> <text color="red">Hello World!</text> </hello>
XSLT-преобразование:
<!-- hello_style.xsl -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<title> <xsl:value-of select="//text"/> </title>
</head>
<body>
<p>
Содержимое узла <b>text</b> корневого элемента: <b><xsl:value-of select="//text"/></b>
и его атрибут <b>color</b> : <xsl:value-of select="//text/@color"/>
</p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Результирующий HTML-документ:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Hello World! </title>
</head>
<body>
<p>
Содержимое узла <b>text</b> корневого элемента: <b>Hello World!</b>
и его атрибут <b>color</b> : red
</p>
</body>
</html>
Если вы задумаете использовать атрибут color для вывода текста
Hello World! соответствующим цветом, то сделать это можно
двумя способами: создать переменную и использовать ее для задания
цвета шрифта или воспользоваться элементом
xsl:attribute.
Переменные
Переменные в XSLT отличается от переменных в обычных языках программирования из-за того, что их значения не могут изменяться. После того как переменной присвоено какое-то значение, оно остается постоянным.
(Странно, почему перменные названы переменными, а не константами. Прим.ред.)Определяются переменные просто:
<!-- variables.xsl -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<!-- definition of the variable -->
<xsl:variable name="path">http://somedomain/tmp/xslt</xsl:variable>
<html>
<head>
<title>Пример с переменными</title>
</head>
<body>
<p>
<a href="{$path}/photo.jpg">Фотография моего последнего путешествия</a>
</p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Результирующий HTML-документ:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Пример с переменными</title>
</head>
<body>
<p><a href="http://somedomain/xslt/photo.jpg">Фотография моего последнего путешествия</a></p>
</body>
</html>
Переменной можно присвоить значение узла или значение атрибута узла:
<!-- variables_select.xsl -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<title>Пример с переменными</title>
</head>
<body>
<xsl:apply-templates select="//photo"/>
</body>
</html>
</xsl:template>
<xsl:template match="photo">
<!-- определение переменных -->
<xsl:variable name="path">http://somedomain/tmp/xslt</xsl:variable>
<xsl:variable name="photo" select="file"/>
<p>
<a href="{$path}/{$photo}"><xsl:value-of select="description"/></a>
</p>
</xsl:template>
</xsl:stylesheet>
Исходный xml-документ (я не стал сопровождать статью своими фотографиями, чтобы не напугать вас :-) )
<!-- variables_select.xml -->
<album>
<photo>
<file>mountains.jpg</file>
<description>я - в горах</description>
</photo>
<photo>
<file>congress.jpg</file>
<description>я - на конгрессе</description>
</photo>
<photo>
<file>school.jpg</file>
<description>я - в школе</description>
</photo>
</album>
Результирующий HTML-документ:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Пример с переменными</title>
</head>
<body>
<p><a href="http://somedomain/tmp/xslt/mountains.jpg">я - в горах</a></p>
<p><a href="http://somedomain/tmp/xslt/congress.jpg">я - на конгрессе</a></p>
<p><a href="http://somedomain/tmp/xslt/school.jpg">я - в школе</a></p>
</body>
</html>
Как вы могли заметить, элемент <xsl:template
match="photo"> был вызван трижды, это произошло потому, что
всякий раз, когда xslt обнаруживает элемент, совпадающий с
xsl:apply-templates, он вызывает соответствующий
xsl:template match.
Итак! Вам не терпится вывести текст красным цветом? Попробуйте сделать это с помощью переменных, если не получится, то можете заглянуть в пример hello_style_variables.xsl
Сортировка
Сортировка XML-тегов в XSLT выполняется посредством элемента
<xsl:sort
select="sort_by_this_attribute"> Этот элемент
должен размещаться внутри xsl:apply-templates
(сортировка может производиться так же и в элементе
xsl:for-each прим. перев.).
Сортировка может выполняться как по самим xml-тегам, так и по их
атрибутам, порядок сортировки можно задавать по возрастанию или по
убыванию (если символы нижнего регистра должны предшествовать
символам верхнего регистра или наоборот).
Для демонстрации сортировки я использовал пример альбома с фотографиями, в который добавил элемент <xsl:sort>:
<xsl:apply-templates select="//photo">
<xsl:sort select="file" order="descending">
</xsl:apply-templates>
Здесь изменен порядок следования фотографий в выходном
html-документе. Теперь xslt сначала упорядочит все элементы
photo из xml-файла, а затем передаст их элементу
template-match, вот почему xsl:sort
должен находиться внутри элемента xsl:apply-templates.
Файлы xsl и html примера вы можете взять здесь:
Инструкция if
Иногда возникает необходимость поместить в выходной документ
некоторый текст, если задан какой-либо xml-элемент (или его
атрибут), либо другой текст, если этот элемент (или атрибут)
отсутствует. В таких случаях можно использовать элемент
xsl:if. Я продемонстрирую вам как это делается (этот
пример взят из моих наработок в проекте TLDP-ES). Если вам
известно, что некий исходный документ был преобразован в формат
PDF, PS или HTML, то это обстоятельство можно отразить в xml-файле,
т.е. если был создан PDF-файл, то в выходной html-файл вставляется
ссылка на него:
<xsl:if test="format/@pdf = 'yes'">
<a href="{$doc_path}/{$doc_subpath}/{$doc_subpath}.pdf">PDF</a>
</xsl:if>
Если атрибуту pdf документа присвоено значение "yes", как показано в примере:
<document>
<title>Bellatrix Library and Semantic Web</title>
<author>Daniel Guerrero</author>
<module>bellatrix</module>
<format pdf="yes" ps="yes" html="yes"/>
</document>
То в выходной html-файл будет вставлена ссылка на документ в PDF-формате. Если атрибуту присвоено значение "no" или любое другое, допустимое вашим преобразованием, значение, то ссылка не будет вставлена. Все вышесказанное вы можете увидеть в xsl и xml документах:
- documents.xml. Информация о документах
- documents.xsl. XSLT-преобразование
- documents.html. Выходной документ в формате HTML
Инструкция for-each
Если вы внимательно посмотрите на xml-документ, приведенный
выше, то заметите, что авторы представлены в виде списка имен,
разделенных запятыми. Очевидно, что наилучшим выходом было бы
поместить имена авторов в отдельные теги
<author>:
<document>
<title>Donantonio: bibliographic system for automatic distribuited publication. Specifications of Software Requeriments</title>
<author>Ismael Olea</author>
<author>Juan Jose Amor</author>
<author>David Escorial</author>
<module>donantonio</module>
<format pdf="yes" ps="no" html="yes"/>
</document>
И вывести каждое имя в отдельной строке с помощью
xsl:apply-templates и xsl:template match,
но то же самое можно сделать и с помощью инструкции
xsl:for-each.
<xsl:for-each select="author">
<tr>
<td>
Author: <xsl:apply-templates />
</td>
</tr>
</xsl:for-each>
В этом случае XSLT-процессор пройдет по списку авторов документа
и, если вас интересует какой шаблон я использовал для обработки
тегов <author>, я могу сказать - никакой. XSLT-процессор
воспримет элемент apply-templates как обычный 'print'
и выведет содержимое тега, выбранного элементом
for-each.
Инструкция choose
Последний xslt-элемент, который я хочу вам продемонстрировать,
это элемент choose. Он очень похож на инструкцию
switch языка программирования C.
Первым должен идти элемент xsl:choose, а за ним
дополнительные (один или несколько) элементы xsl:when,
если требуется обрабатывать значение не подпадающее ни под одно из
условий имеющихся элементов xsl:when, то вы можете
добавить элемент xsl:otherwise:
<xsl:variable name="even" select="position() mod 2"/>
<xsl:choose>
<xsl:when test="$even = 1">
<![CDATA[<table width="100%" bgcolor="#cccccc">]]>
</xsl:when>
<xsl:when test="$even = 0">
<![CDATA[<table width="100%" bgcolor="#99b0bf">]]>
</xsl:when>
<xsl:otherwise>
<![CDATA[<table width="100%" bgcolor="#ffffff">]]>
</xsl:otherwise>
</xsl:choose>
Функция position() возвращает порядковый номер
обрабатываемого элемента, в нашем случае -- документа. В данном
примере нас интересует только четность порядкового номера, тем
самым мы получаем возможность выделять четные и нечетные строки
таблицы различным цветом. Я поместил элемент
xsl:otherwise исключительно в демонстрационных целях,
фактически же вы никогда не увидите строку с белым фоном в нашей
таблице.
Если вы спросите меня зачем я вставил секцию CDATA,
то я вам отвечу, если бы я этого не сделал, то XSLT-процессор
генерировал бы сообщения об ошибке по поводу отсутствия
закрывающего тега (</table>), но в нашем случае
этот тег находится ниже. По той же самой причине, закрывающий тег
</table> так же должен быть оформлен в виде
секции CDATA.
Я привел лишь короткий отрывок из примера, полный текст файлов xsl и html вы найдете по ссылкам:
- documents_choose.xsl. XSLT-преобразование
- documents_choose.html. Результат преобразования
Процессоры XSLT
Saxon
Процессор Saxon написан на языке Java, я пользуюсь версией 6.5.2. Все нижеследующие инструкции касаются этой версии, если у вас другая версия, то вам следует обратиться к документации для вашей версии за получением информации по установке и запуску процессора.
Установка
После того как вы скачаете архив с процессором saxon вам нужно распаковать его:
[danguer@perseo xslt]$ unzip saxon6_5_2.zip
Затем, вам нужно добавить файл saxon.jar к пути поиска классов,
путь к jar-архиву можно передать с помощью ключа -cp
path (можно добавить путь к jar-файлу в переменную
окружения CLASSPATH прим. перев.). Я поместил
файл saxon.jar в каталог xslt, кроме того необходимо передать Java
используемый класс, в случае Saxon 6.5.2 используется класс
com.icl.saxon.StyleSheet и затем должны следовать
xml-документ и xsl-файл, например:
[danguer@perseo xslt]$ java -cp saxon.jar com.icl.saxon.StyleSheet document.xml tranformation.xsl
Эта команда отправит результат работы процессора на устройство стандартного вывода (STDOUT), перенаправить вывод в файл можно так:
[danguer@perseo xslt]$ java -cp saxon.jar com.icl.saxon.StyleSheet document.xml tranformation.xsl > file_processed.html
Например мы можем преобразовать наш первый пример XSLT с помощью процессора saxon:
[danguer@perseo xslt]$ java -cp saxon.jar com.icl.saxon.StyleSheet hello.xml hello.xsl > hello.html
xsltproc
Процессор xsltproc включен в состав большинства дистрибутивов, синтаксис вызова похож на вызов процессора saxon:
[danguer@perseo xslt]$ xsltproc hello.xsl hello.xml > hello.html
Я знаю о существовании и других процессоров, таких как sablotron, но я ими не пользовался, а потому не могу рекомендовать их вам ;-).
Ссылки
- Спецификация языка XSLT консорциума w3
- Домашняя страничка XSL
- Домашняя страничка Saxon
- Новости и ресурсы для XML-разработчиков (на русском языке)
- Школы консорциума w3 на русском языке
-
Примеры (пример 'card', был написан до того как я начал работу
над этой статьей, надеюсь он будет вам полезен):
- http://gazette.linux.ru.net/lg89/misc/danguer/cards.html
- http://gazette.linux.ru.net/lg89/misc/danguer/cards.xml
- http://gazette.linux.ru.net/lg89/misc/danguer/cards.xsl
- http://gazette.linux.ru.net/lg89/misc/danguer/hello.html
- http://gazette.linux.ru.net/lg89/misc/danguer/hello.xml
- http://gazette.linux.ru.net/lg89/misc/danguer/hello.xsl
- http://gazette.linux.ru.net/lg89/misc/danguer/hello_style.html
- http://gazette.linux.ru.net/lg89/misc/danguer/hello_style.xml
- http://gazette.linux.ru.net/lg89/misc/danguer/hello_style.xsl
- http://gazette.linux.ru.net/lg89/misc/danguer/hello_style_variables.html
- http://gazette.linux.ru.net/lg89/misc/danguer/hello_style_variables.xsl
- http://gazette.linux.ru.net/lg89/misc/danguer/variables.html
- http://gazette.linux.ru.net/lg89/misc/danguer/variables.xsl
- http://gazette.linux.ru.net/lg89/misc/danguer/variables_select.html
- http://gazette.linux.ru.net/lg89/misc/danguer/variables_select.xml
- http://gazette.linux.ru.net/lg89/misc/danguer/variables_select.xsl
- http://gazette.linux.ru.net/lg89/misc/danguer/sort.xsl
- http://gazette.linux.ru.net/lg89/misc/danguer/sort.html
- http://gazette.linux.ru.net/lg89/misc/danguer/documents.xml
- http://gazette.linux.ru.net/lg89/misc/danguer/documents.xsl
- http://gazette.linux.ru.net/lg89/misc/danguer/documents.html
- http://gazette.linux.ru.net/lg89/misc/danguer/documents_for.html
- http://gazette.linux.ru.net/lg89/misc/danguer/documents_for.xml
- http://gazette.linux.ru.net/lg89/misc/danguer/documents_for.xsl
- http://gazette.linux.ru.net/lg89/misc/danguer/documents_choose.xsl
- http://gazette.linux.ru.net/lg89/misc/danguer/documents_choose.html
Daniel Guerrero
Я заканчиваю обучение на степень бакалавра BUAP в городе Пуэбло (Puebla), Мексика. Учавствую в работе проекта TLPD-ES (испанский вариант The Linux Documentation Project прим. перев.) все мои познания об этих технологиях я приобрел здесь. В настоящий момент я изучаю Web-семантику.Copyright (C) 2003, Daniel Guerrero.
Copying license http://www.linuxgazette.com/copying.html
Published in Issue 89 of Linux Gazette, April
2003
Команда переводчиков:
Александр Куприн, Андрей Киселев, Александр Михайлов, Александр Саввин,
Владимир Меренков, Иван Песин, Игорь Яровинский, Павел Соколов, Роман Шумихин,
Сергей Скороходов, Юрий Прушинский
Со всеми предложениями, идеями и комментариями обращайтесь к Александру Куприну (ru_classic at mail.ru). Убедительная просьба: указывайте сразу, не возражаете ли Вы против публикации Ваших отзывов в рассылке.
Сайт рассылки: http://gazette.linux.ru.net
Эту статью можно взять здесь: http://gazette.linux.ru.net/lg89/danguer.html
Архивы выпусков находятся здесь: http://gazette.linux.ru.net/archive/
| http://subscribe.ru/
E-mail: ask@subscribe.ru |
Отписаться
Убрать рекламу |
| В избранное | ||
