Перейти к основному содержимому

XSLT

Разработчику Аналитику Архитектору

Семейство XSL

ЧастьНазначение
XSLT (Transformations)XML → другой XML, HTML, текст
XPathВыбор узлов внутри XSLT
XSL-FO (Formatting Objects)Вёрстка для PDF (печать) — отдельный стек

XSLT — декларативный язык: вы описываете шаблоны "если узел такой — выведи так", а процессор обходит дерево. Это не замена общему языку программирования, но силён для отчётов, маппинга схем и публикации.

Исходный XML (данные):

<library>
<book id="1">
<title>Война и мир</title>
<author>Лев Толстой</author>
<price>450</price>
</book>
<book id="2">
<title>Мастер и Маргарита</title>
<author>Михаил Булгаков</author>
<price>380</price>
</book>
</library>

Как работает преобразование

  1. Загружается исходный XML.
  2. Загружается таблица стилей (файл .xsl, корень xsl:stylesheet).
  3. Процессор (Saxon, xslt в .NET, xsltproc, встроенный в IDE) строит дерево результата и сериализует его (HTML, XML, текст).

Пространство имён XSLT 1.0: http://www.w3.org/1999/XSL/Transform, префикс обычно xsl:.


Минимальная таблица стилей

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h1>Каталог</h1>
<xsl:apply-templates select="library/book"/>
</body>
</html>
</xsl:template>

<xsl:template match="book">
<p><xsl:value-of select="title"/><xsl:value-of select="author"/></p>
</xsl:template>
</xsl:stylesheet>

Ключевые элементы XSLT 1.0

xsl:template

Определяет правило для узлов, совпадающих с XPath Pattern в match:

<xsl:template match="book[@id='1']">
<em><xsl:apply-templates/></em>
</xsl:template>

match="/" — точка входа с корня документа. priority и mode разрешают конфликты нескольких шаблонов.


xsl:value-of

Вставляет строковое значение первого узла из select:

<xsl:value-of select="title"/>
<xsl:value-of select="@id"/>

xsl:for-each

Цикл по узлам, выбранным XPath:

<xsl:for-each select="library/book">
<li><xsl:value-of select="title"/></li>
</xsl:for-each>

xsl:sort

Сортировка внутри for-each или apply-templates:

<xsl:for-each select="library/book">
<xsl:sort select="title" order="ascending" data-type="text"/>
<li><xsl:value-of select="title"/></li>
</xsl:for-each>

xsl:if

Одна ветвь без else (для elsechoose):

<xsl:if test="price &gt; 400">
<span class="expensive"><xsl:value-of select="title"/></span>
</xsl:if>

В XML/XSLT символ > в атрибутах пишут как &gt; или в CDATA.


xsl:choose

<xsl:choose>
<xsl:when test="@genre='classic'">Классика</xsl:when>
<xsl:when test="@genre='novel'">Роман</xsl:when>
<xsl:otherwise>Другое</xsl:otherwise>
</xsl:choose>

xsl:apply-templates

Делегирует обработку дочерним узлам другим шаблонам (рекурсивный обход):

<xsl:template match="library">
<ul><xsl:apply-templates select="book"/></ul>
</xsl:template>

select ограничивает, какие узлы передаются; mode — альтернативный набор шаблонов.


Продвинутые приёмы XSLT

Ниже — приёмы из практики трансформации — повторное использование логики, альтернативные проходы по дереву, нумерация и управление пробелами.

Именованные шаблоны — xsl:call-template

Именованный шаблон — подпрограмма с параметрами. В отличие от match, его вызывают явно по имени:

<xsl:template name="format-price">
<xsl:param name="amount"/>
<xsl:text>$</xsl:text>
<xsl:value-of select="format-number($amount, '#,##0.00')"/>
</xsl:template>

<xsl:template match="book">
<p>
<xsl:value-of select="title"/>
<xsl:call-template name="format-price">
<xsl:with-param name="amount" select="price"/>
</xsl:call-template>
</p>
</xsl:template>
МеханизмКогда использовать
match + apply-templatesОбход дерева "по событию" узла
name + call-templateОбщая форматировка (цена, дата, ссылка) из разных мест

Переменные и параметры

<xsl:variable name="currency" select="'RUB'"/>
<xsl:param name="show-author" select="true()"/>

xsl:param задаётся на уровне stylesheet или именованного шаблона; при вызове переопределяется через with-param. Константы и флаги так проще, чем дублировать XPath в каждом шаблоне.

Режимы — mode

Режим позволяет иметь несколько наборов шаблонов для одних и тех же узлов. Первый проход строит HTML, второй — оглавление, третий — сноски:

<xsl:template match="chapter" mode="toc">
<li><xsl:value-of select="title"/></li>
</xsl:template>

<xsl:template match="/">
<html><body>
<nav><ul>
<xsl:apply-templates select="//chapter" mode="toc"/>
</ul></nav>
<main>
<xsl:apply-templates select="//chapter" mode="body"/>
</main>
</body></html>
</xsl:template>

Вызов: apply-templates с атрибутом mode="toc". Шаблон без mode не участвует в режимном проходе и наоборот.

xsl:number — нумерация глав и списков

<xsl:template match="chapter">
<h2>
<xsl:text>Глава </xsl:text>
<xsl:number value="position()" format="1"/>
<xsl:text>. </xsl:text>
<xsl:value-of select="title"/>
</h2>
</xsl:template>
АтрибутПримерЭффект
valueposition()Текущая позиция в списке
format"1", "I", "a"Арабские, римские, буквенные
levelsingle, any, multipleОбласть подсчёта (раздел, документ)
countchapterКакие узлы считать

Для сквозной нумерации рисунков: count="figure" + level="any".

Пробелы и текст в результате

Процессор может сжимать пробелы между тегами в stylesheet. Для точного контроля:

  • xsl:text — буквальный текст без нормализации;
  • xsl:strip-space elements="*" / xsl:preserve-space — политика для исходного XML;
  • disable-output-escaping="yes" — редко, для совместимости с legacy HTML.
<xsl:text> </xsl:text> <!-- один пробел между словами -->
<xsl:comment> generated </xsl:comment> <!-- комментарий в HTML-результате -->

Фильтрация и сводки

Трансформация часто сужает документ — типичные задачи — оглавление по заголовкам, сводка по числовым полям, фильтр по дате:

ЗадачаПодход в XSLT
Оглавление по заголовкам//chapter/title в mode="toc"
Сводка расходовsum(//payment/amount) в XPath
Только записи за периодxsl:for-each select="entry[date >= '2026-01-01']"
Адаптер между двумя XSDШаблоны match на исходные теги → другие имена в результате

Пример сводки по библиотеке:

<xsl:template match="/">
<report>
<total-books><xsl:value-of select="count(library/book)"/></total-books>
<expensive>
<xsl:for-each select="library/book[price > 400]">
<title><xsl:value-of select="title"/></title>
</xsl:for-each>
</expensive>
</report>
</xsl:template>

Исходный XML не меняется — XSLT создаёт новый документ (отчёт, HTML, упрощённый XML для другой системы).

Объединение таблиц стилей

xsl:import и xsl:include собирают общие шаблоны (формат даты, макет страницы) с частными правилами. import задаёт приоритет (импортированные шаблоны слабее главного файла) — удобно для тем оформления поверх базовой DocBook-цепочки.


Полный пример — HTML-список с сортировкой

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html><body>
<h1>Список книг</h1>
<ul>
<xsl:for-each select="library/book">
<xsl:sort select="title"/>
<li>
<strong><xsl:value-of select="title"/></strong>
(<xsl:value-of select="author"/>)
<xsl:if test="price &gt; 400"> — премиум</xsl:if>
</li>
</xsl:for-each>
</ul>
</body></html>
</xsl:template>
</xsl:stylesheet>

Play ITЗагрузка интерактивного демо…

Полный перечень элементов и атрибутов XSLT 2.0/3.0 — справочник по XSLT.


XSLT на стороне клиента

Исторически браузеры (IE, ранний Firefox) могли применять XSLT через <?xml-stylesheet type="text/xsl" href="..."?>.

Сегодня:

  • в современных браузерах поддержка XSLT ограничена или отключена;
  • для веб-UI предпочтительны серверное преобразование или сборка на этапе CI;
  • клиентский XSLT иногда встречается во внутренних корпоративных приложениях и legacy.

Практический вывод: не закладывайте XSLT в браузер как единственный способ рендера без проверки целевой среды.


XSLT на стороне сервера

Типичные сценарии:

СредаИнструмент
.NETSystem.Xml.Xsl.XslCompiledTransform
JavaJAXP Transformer, Saxon
PHPXSLTProcessor (libxslt)
CLIxsltproc, Saxon (java -jar saxon.jar)
КонвейерыПреобразование перед публикацией отчёта, EDI, СМЭВ

Преимущества сервера — контроль версий XSLT, кэширование скомпилированных таблиц, единый PDF/HTML для всех клиентов.

Пример запуска Saxon из командной строки:

java -jar saxon-he.jar -s:input.xml -xsl:transform.xsl -o:output.html

Редактирование XML и роль XSLT

Редактирование XML — это изменение исходного файла (IDE, DOM API, сериализация из кода). XSLT исходник не меняет: он создаёт производный документ.

ЗадачаПодход
Правка конфигурацииРедактор + валидация XSD
Массовая смена структурыXSLT или скрипт (Python, C#)
Просмотр для человекаXSLT → HTML или CSS к XML
Обмен между системамиXSLT как "адаптер" между двумя XSD

Связанные темы: XML, XML DOM, справочник XSLT.

Практическое задание

Добавьте в таблицу стилей: (1) именованный шаблон format-price и вызов через call-template; (2) второй проход mode="toc", который выводит только заголовки книг списком. Проверьте в демо выше.