Язык преобразований XSL

         

Определение правил шаблона


<!-- Category: top-level-element -->
<xsl:template
  match = pattern
  name = qname
  priority = number
  mode = qname>
  <!-- Content: (xsl:param*, template) -->
</xsl:template>

Правило шаблона задается элементом xsl:template. Атрибут match соответствует , который идентифицирует исходные узел или узлы, к которым это правило применяется. Если элемент xsl:template не имеет атрибута name, атрибут match обязателен (см. ). Если в значении атрибута match содержится , фиксируется ошибка. Содержимое элемента xsl:template является шаблоном, который обрабатывается если данное правило шаблона задействовано.

Например, документ XML может содержать:

This is an <emph>important</emph> point.

Приведенное далее правило шаблона соответствует элементам emph и создает объект форматирования fo:inline-sequence, имеющий свойство font-weight со значением bold.

<xsl:template match="emph"> <fo:inline-sequence font-weight="bold"> <xsl:apply-templates/> </fo:inline-sequence> </xsl:template>

Примечание: В примерах этого документа префикс fo: используется для пространства имен http://www.w3.org/1999/XSL/Format (пространства имен объектов форматирования, определенных в ).

Как описано далее, элемент xsl:apply-templates рекурсивно обрабатывает непосредственные потомки данного исходного элемента.



Откат


<!-- Category: instruction -->
<xsl:fallback>
<!-- Content: template -->
</xsl:fallback>

Обычно обработка элемента xsl:fallback ничего не меняет. Однако когда XSLT процессор осуществляет откат для элемента инструкции, а этот элемент инструкции имеет один или несколько непосредственных потомков xsl:fallback, должно быть последовательно обработано содержимое каждого из этих потомков xsl:fallback. В противном случае должна фиксироваться ошибка. Содержимое элемента xsl:fallback является шаблоном.

Приведенные далее функции могут быть использованы с инструкциями xsl:choose и xsl:if чтобы явно задавать поведение стиля в случае, если определенные стили или функции будут недоступны.

Функция: boolean element-available(строка)

Аргумент функции должен обрабатываться как строка, соответствующая . преобразуется в с помощью деклараций пространства имен из области видимости данного выражения. Функция возвращает true тогда и только тогда, когда это расширенное имя является названием инструкции. Если URI пространства имен в расширенном имени равно URI пространства имен XSLT, то это имя относится к элементу, объявленному в XSLT. В противном случае расширенное имя относится к элементу расширения. Если расширенное имя имеет нулевой URI пространства имен, функция будет возвращать false.

Функция: boolean function-available(строка)

Аргумент функции должен обрабатываться как строка, соответствующая . приводится к с помощью деклараций пространства имен в области видимости данного выражения. Функция возвращает true тогда и только тогда, когда расширенное имя является названием некой функции из библиотеки функций. Если расширенное имя имеет ненулевой URI пространства имен, то оно относится к функции расширения. В противном случае имя относится к функции, определенной в XPath или XSLT.



Передача параметров шаблону




<xsl:with-param
name = qname
  select = expression>
  <!-- Content: template -->
</xsl:with-param>

Параметры передаются шаблонам с помощью элемента xsl:with-param. Обязательный атрибут name сообщает название параметра (переменной, значение которой должно быть изменено). Значением атрибута name является , процедура приведения которого к расширенному имени описана в главе . xsl:with-param можно использовать для xsl:call-template и для xsl:apply-templates. Значение параметра задается точно так же, как для xsl:variable или xsl:param. При обработке значения, заданного элементом xsl:with-param, используются те же текущий узел и текущий набор узлов, что и для элементов xsl:apply-templates или xsl:call-template, в которых этот элемент находится. Если параметр x был передан в шаблон, не имеющий соответствующего элемента xsl:param, ошибка фиксироваться не будет, а сам параметр просто игнорируется.

В данном примере определяется именованный шаблон numbered-block с аргументом, задающий формат числа.

<xsl:template name="numbered-block"> <xsl:param name="format">1. </xsl:param> <fo:block> <xsl:number format="{$format}"/> <xsl:apply-templates/> </fo:block> </xsl:template>

<xsl:template match="ol//ol/li"> <xsl:call-template name="numbered-block"> <xsl:with-param name="format">a. </xsl:with-param> </xsl:call-template> </xsl:template>



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


<!-- Category: top-level-element -->

<!-- Category: instruction -->

<xsl:variable
  name = qname

  select = expression>

  <!-- Content: template -->

</xsl:variable>

<!-- Category: top-level-element -->

<xsl:param
  name = qname

  select = expression>

  <!-- Content: template -->

</xsl:param>

Переменная - это имя, которое может быть связано со значением. Значение, к которому привязана переменная, (значение переменной) может быть объектом любого типа, который может быть возвращен выражением. Для привязки переменных могут использоваться два элемента: xsl:variable и xsl:param. Разница между ними заключается в том, что значение, указанное в переменной xsl:param, является лишь значением по умолчанию. Если используется шаблон или стиль, в котором используется элемент xsl:param, то могут быть переданы параметры, которые будут использоваться вместо значений по умолчанию.

И xsl:variable, и xsl:param имеют обязательный атрибут name, задающий имя переменной. Значением атрибута name является , которое приводится к расширенному имени как описано в главе .

Когда используется любой из этих элементов привязки переменных, в дереве стилей всегда есть область, где эта привязка будет видима. В пределах этой области видима любая привязка данной переменной, однако соответствующий элемент привязки переменной остается скрытым. Таким образом, видна только самая внутренняя привязка переменной. Набор привязок переменной в области видимости выражения состоит из тех привязок, которые были видимы в том месте стиля, где это выражение находится.



Переменные и параметры в шаблонах


Помимо верхнего уровня, и xsl:variable, и xsl:param можно использовать также в шаблонах. xsl:variable можно ставить в любом месте шаблона, где допустимо использование инструкций. В этом случае, данная привязка видна для всех последующих узлов, имеющих того же родителя и их потомков. Заметим однако, что привязка для самого элемента xsl:variable не видна. xsl:param можно использовать как непосредственный потомок в начале элемента xsl:template. В данном контексте привязка переменной видна для всех последующих узлов, имеющих того же родителя и их потомков. Заметим, что для самого элемента xsl:param эта привязка не видна.

Одна привязка переменной маскирует другую, если она появляется в точке, где вторая привязка была видна и обе они имеют одно и то же имя. Если привязка переменной, задаваемая в шаблоне элементом xsl:variable или xsl:param, другой привязкой, заданной в том же шаблоне элементом xsl:variable или xsl:param, фиксируется ошибка. Однако если привязка переменной, заданная в шаблоне элементом xsl:variable или xsl:param, другую привязку, заданную элементом xsl:variable или xsl:param, ошибка не фиксируется. Таким образом, в следующем примере содержится ошибка:

<xsl:template name="foo"> <xsl:param name="x" select="1"/> <xsl:variable name="x" select="2"/> </xsl:template>

Однако допустим другой вариант:

<xsl:param name="x" select="1"/> <xsl:template name="foo"> <xsl:variable name="x" select="2"/> </xsl:template>

Замечание: В Java ближайшим эквивалентом элемента xsl:variable в шаблоне является декларация переменной типа final local с инициализацией. Например, <xsl:variable name="x" select="'value'"/>

имеет семантику, похожую на final Object x = "value";

В XSLT нет эквивалента оператору присвоения из Java x = "value";

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



Переменные и параметры верхнего уровня


И xsl:variable, и xsl:param можно использовать в элементах . Элемент привязки переменной на верхнем уровне декларирует глобальную переменную, которая видна отовсюду. Элемент верхнего уровня xsl:param декларирует параметр для стиля, однако XSLT не определяет механизм передачи параметров стилю. Если стиль содержит привязку для нескольких переменных верхнего уровня с одним и тем же именем и одинаковым , фиксируется ошибка. На верхнем уровне выражение или шаблон, указывающие значение переменной, обрабатываются с тем же контекстом, что и при обработке корневого узла в исходном документе: текущим узлом является корневой узел исходного документа, а текущим набором узлов - список, содержащий только корневой узел исходного документа. Если шаблон или выражение, определяющее значение глобальной переменной x, ссылается на глобальную переменную y, то значение y должны быть вычислено прежде значения x. Если это можно сделать не для всех глобальных деклараций переменных, фиксируется ошибка. Иными словами, фиксируется ошибка, если декларации зацикливаются.

Данный пример декларирует глобальную переменную para-font-size, с помощью которой в шаблоне значения атрибута делается ссылка.

<xsl:variable name="para-font-size">12pt</xsl:variable>

<xsl:template match="para"> <fo:block font-size="{$para-font-size}"> <xsl:apply-templates/> </fo:block> </xsl:template>



Переопределение правил шаблона


<!-- Category: instruction -->
<xsl:apply-imports/>

Правило шаблона, которое должно использоваться для переопределения другого правила шаблона в импортированном стиле (см. ), может воспользоваться элементом xsl:apply-imports чтобы вызвать переопределенное правило шаблона.

При обработке стиля в каждой точке имеется некое текущее правило шаблона. Всякий раз, когда по образцу выбирается правило шаблона, для обработки оно становится текущим правилом шаблона. Когда обрабатывается элемент xsl:for-each, то при обработке содержимого этого элемента xsl:for-each текущее правило шаблона становится нулевым.

xsl:apply-imports обрабатывает текущий узел используя лишь те правила шаблона, которые были импортированы в тот элемент стиля, где это текущее правило шаблона находится. Узел обрабатывается в режиме текущего правила шаблона. Если xsl:apply-imports обрабатывается когда текущее правило шаблона нулевое, фиксируется ошибка.

Например, предположим что стиль doc.xsl содержит правило шаблона для элементов example:

<xsl:template match="example"> <pre><xsl:apply-templates/></pre> </xsl:template>

Другой стиль может импортировать doc.xsl и поменять обработку элементов example следующим образом:

<xsl:import href="doc.xsl"/>

<xsl:template match="example"> <div style="border: solid red"> <xsl:apply-imports/> </div> </xsl:template>

В результате суммарного действия example должен преобразовываться в элемент следующего вида:

<div style="border: solid red"><pre>...</pre></div>



Полные имена


Название внутреннего объекта XSLT, а именно: именованного шаблона (см. ), режима (см. ), набора атрибутов (см. ), ключа (см. ), десятичного формата (см. ), переменной или параметра (см. ), задается как . Если название имеет префикс, то этот префикс преобразуется в ссылку URI с помощью деклараций пространства имен, в области действия оказался атрибут с этим названием. В качестве названия указанного объекта используется , состоящее из локальной части и, возможно нулевой, ссылки URI. Для названий без префиксов пространство имен по умолчанию не используется.



Повторение


<!-- Category: instruction -->
<xsl:for-each
select = node-set-expression>
  <!-- Content: (xsl:sort*, template) -->
</xsl:for-each>

Если результат имеет известную регулярную структуру, полезно иметь возможность указать это прямо в шаблоне для собираемых узлов. Инструкция xsl:for-each содержит шаблон, который обрабатывается для каждого узла, отобранного , указанным в атрибуте select. Атрибут select является обязательным. Результатом обработки выражения должен быть набор узлов. При обработке шаблона выбранный узел берется в качестве , а весь список собранных узлов берется в качестве . Узлы обрабатываются в том порядке как они следуют в документе, если нет указаний относительно сортировки (см. ).

Например, дан XML документ со следующей структурой

<customers> <customer> <name>...</name> <order>...</order> <order>...</order> </customer> <customer> <name>...</name> <order>...</order> <order>...</order> </customer> </customers>

Следующий пример должен создать HTML документ, содержащий таблицу, где каждому элементу customer отводится отдельная строка.

<xsl:template match="/"> <html> <head> <title>Customers</title> </head> <body> <table> <tbody> <xsl:for-each select="customers/customer"> <tr> <th> <xsl:apply-templates select="name"/> </th> <xsl:for-each select="order"> <td> <xsl:apply-templates/> </td> </xsl:for-each> </tr> </xsl:for-each> </tbody> </table> </body> </html> </xsl:template>



и семантику XSLT, языка преобразований


Данная спецификация определяет синтаксис и семантику XSLT, языка преобразований XML документов в другие XML документы.
XSLT создавался для применения в XSL, языке стилей для XML. Помимо XSLT, XSL содержит словарь XML для описания форматирования. XSL определяет стиль XML документа, используя XSLT чтобы описать, каким именно образом представленный документ преобразуется в другой XML документ, использующий данный словарь форматирования.
Кроме того, XSLT построен так, чтобы использоваться независимо от XSL. Вместе с тем XSLT не позиционируется как полноценный универсальный язык преобразований XML. Скорее наоборот, прежде всего он предназначен для тех видов преобразований, которые необходимы когда XSLT используется как часть XSL.

Приложения


A

    A.1

    A.2

B

C (пояснения к спецификации)

D (пояснения к спецификации)

    D.1

    D.2

E (пояснения к спецификации)

F (пояснения к спецификации)

G (пояснения к спецификации)

H (пояснения к спецификации)



Пространство имен XSLT


Пространство имен XSLT имеет URI http://www.w3.org/1999/XSL/Transform.

Замечание: Число 1999 в этом URI показывает год, в который этот URI был принят W3C. И это не версия используемого XSLT, которая задается атрибутами (см. главы и ).

Чтобы идентифицировать элементы и атрибуты из указанного пространства, XSLT процессоры должны использовать механизм пространства имен XML . Элементы из пространства имен XSLT распознаются только в стиле, а не в исходном документе. Полный перечень элементов, определенных в XSLT, представлен в Приложении . Разработчики не должны пополнять пространство имен XSLT дополнительными элементами и атрибутами. Вместо этого любое расширение должно быть вынесено в отдельное пространство имен. Какое бы пространство имен не использовалось для дополнительных элементов инструкций, оно должно быть идентифицировано с помощью механизма элементов расширения, описанного в главе .

Для обращения к элементам из пространства имен XSLT в данной спецификации использует префикс xsl:. Однако в XSLT стиле можно свободно использовать любой префикс при условии, что имеется декларация пространства имен, привязывающая этот префикс к тому же URI пространства имен XSLT.

Элемент из пространства имен XSLT может иметь любой атрибут из другого пространства при условии, что этого атрибута имеет ненулевой URI пространства имен. Появление таких атрибутов не должно изменять поведение элементов и функций XSLT, определенных в данном документе. Соответственно, XSLT процессор может всегда свободно игнорировать такие атрибуты и даже обязан это делать, не фиксируя ошибки, если найти соответствующее URI пространства имен не удается. Описанные атрибуты, к примеру, могут содержать уникальные идентификаторы, инструкции по оптимизации или документирование.

Если элемент из пространства имен XSLT имеет атрибут, чье расширенное имя имеет нулевой URI пространства имен (т.е. атрибут с названием без префиксов), и который не входит в число атрибутов, определенных для этого элемента в данном документе, фиксируется ошибка.

Замечание: По соглашению, названия атрибутов и функций для всех элементов XSLT пишутся прописными буквами, для разделения слов используют дефис, а сокращения используются только тогда, если они уже есть в синтаксисе соответствующего языка, такого как XML или HTML.



Расширения


XSLT допускает два типа расширений: элементы расширения и функции расширения.

Данная версия XSLT не дает механизм для создания расширений. Поэтому стиль XSLT, который должен быть переносим между различными реализациями XSLT процессора, не должен быть завязан на доступность определенных расширений. XSLT дает механизмы, позволяющие стилю XSLT определить, доступна ли реализация конкретных расширений в XSLT процессоре, осуществляющем обработку этого стиля, и что должно происходить если указанные расширения недоступны. Если авторы стиля XSLT позаботились об использовании таких механизмов, то можно совместить преимущества расширений и работоспособность с любыми реализациями XSLT.



Различные дополнительные функции


Функция: набор-узлов current()

Функция возвращает набор узлов, состоящий из единственного члена - . Для внешнего выражения (выражения, которое не является частью другого выражения), текущий узел всегда тот же самый, что и узел контекста. Таким образом,

<xsl:value-of select="current()"/>

означает то же самое, что и

<xsl:value-of select="."/>

Однако внутри квадратных скобок текущий узел обычно отличается от узла контекста. Например,

<xsl:apply-templates select="//glossary/item[@name=current()/@ref]"/>

будет обрабатывать все элементы item, которые имеют родителем элемент glossary, а также имеют атрибут name, значение которого равно значению атрибута ref текущего узла. Этот вариант отличается от

<xsl:apply-templates select="//glossary/item[@name=./@ref]"/>

который означает то же самое, что

<xsl:apply-templates select="//glossary/item[@name=@ref]"/>

а потому будет обрабатывать все элементы item, которые имеют родителем элемент glossary, а также имеют атрибуты name и ref с одинаковыми значениями.

Если в использовать функцию , фиксируется ошибка.

Функция: строка unparsed-entity-uri(строка)

возвращает URI неразобранной сущности с заданным именем, находящейся в том же документе, что и узел контекста (см. ). Если такой сущности нет, функция возвращает пустую строку.

Функция: строка generate-id(список-узлов?)

Функция возвращает строку, уникальным образом идентифицирующую тот узел из набора узлов, представленного в аргументе, который первым встретится в документе. Уникальный идентификатор должен состоять из алфавитно-цифровых символов ASCII и должен начинаться с буквы. Таким образом, данная строка синтаксическим соответствует имени XML. Разработчик волен генерировать идентификатор любым удобным ему способом при условии, что для одного и того же узла всегда генерируется один и тот же идентификатор, а для разных узлов всегда генерируются разные идентификаторы. Процессор не обязан генерировать одни и те же идентификаторы при каждом преобразовании документа.
Нет гарантий, что сгенерированный уникальный идентификатор не совпадет с каким-либо уникальным ID, указанным у исходном документе. Если в аргументе был дан пустой набор узлов, функция возвращает пустую строку. Если аргумент отсутствует, то по умолчанию используется узел контекста.

Функция: object system-property(строка)

Аргумент функции должен обрабатываться как строка . приводится к расширенному имени с помощью деклараций пространства имен в области видимости данного выражения. Функция возвращает объект, представляющий значение системного параметра, идентифицируемого этим именем. Если такого системного свойства нет, должна возвращаться пустая строка.

Реализации процессора должны представлять следующие системные свойства, относящиеся к пространству имен XSLT:

xsl:version, число, указывающее версию XSLT, реализуемую данным процессором. Для XSLT процессоров, реализующих версию XSLT, описываемую данным документом, таким числом является 1.0 xsl:vendor, строка, идентифицирующая разработчика XSLT процессора xsl:vendor-url, строка, содержащая URL, идентифицирующий разработчика данного XSLT процессора. Как правило, это страница хоста (домашняя страница) Web-сайта разработчика.


Разрешение конфликтов в правилах шаблона


Может оказаться, что исходный узел соответствует сразу нескольким правилам шаблона. Правило шаблона, которое должно использоваться, определяется следующим образом:

Во-первых, из рассмотрения исключаются все соответствующие узлу правила шаблона, которые имеют более низкий , чем проверяемое правило шаблона и правила с наивысшим приоритетом импорта.

Затем из рассмотрения исключаются все соответствующие узлу правила шаблона, которые имеют более низкий приоритет чем данное соответствующее правило шаблона и правила с наивысшим приоритетом. Приоритет правила шаблона задается атрибутом priority. Значением этого атрибута должно быть реальное число (положительное или отрицательное), соответствующее сценарию с необязательным начальным символом минус (-). Приоритет по умолчанию вычисляется следующим образом:

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

Если образец имеет вид , которому предшествует , или имеет вид processing-instruction(), которому предшествует , то приоритет считается равным 0.

Если образец имеет вид :*, которому предшествует , то его приоритет равен -0.25.

В противном случае, если образец состоит только из , которому предшествует , то его приоритет равен -0.5.

В остальных случаях приоритет равен 0.5.

Таким образом, самый общий тип образцов (образец, проверяющий узел определенного типа и с определенным расширенным именем) имеет приоритет 0. Следующий, более общий тип образца (образец, проверяющий узел определенного типа и с расширенным именем и определенным URI пространства имен) имеет приоритет -0.25. Еще более общие образцы (образцы, проверяющие лишь узлы определенных типов) имеют приоритет -0.5. Образцы, еще более специальные, чем самый общий тип образца, имеют приоритет 0.5.

Если и после этого останется более одного правила шаблона, соответствующего узлу, фиксируется ошибка. XSLT процессор может сигнализировать о такой ошибке, если же он этого не делает, то должен ее обработать, выбрав среди оставшихся соответствующих узлу правил шаблона то, которое в стиле было указано последним.



Данный документ представляет собой перевод


Данный документ представляет собой перевод спецификации XSL Transformations (XSLT) Version 1.0 (W3C Recommendation) на русский язык. При этом нормативным документом считается оригинальная спецификация на английском языке, которую можно найти по адресу

.

Перевод спецификации на русский язык представлен на страницах портала "Россия-Он-Лайн":

Перевод выполнен , ()

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

(доступна в форматах и ) Последняя версия:

Предыдущие версии:

Редактор: James Clark

Copyright ©  1999 ® (MIT, INRIA, Keio), Все права защищены. Обязательства W3C, правила, касающиеся , и .


Режимы


Режимы позволяют обрабатывать элемент несколько раз, получая каждый раз другой результат.

Оба элемента xsl:template и xsl:apply-templates имеют необязательный атрибут mode. Значением атрибута mode является название , которое приводится к расширенному имени как было описано в главе . Если xsl:template не имеет атрибута match, то он не должен иметь и атрибута mode. Если элемент xsl:apply-templates имеет атрибут mode, то он применяется только к тем правилам шаблона из элементов xsl:template, которые имеют атрибут mode с тем же значением. Если элемент xsl:apply-templates атрибута mode не имеет, то он применяется только к тем правилам шаблона из элементов xsl:template, которые также не имеют атрибута mode.



Шаблоны значений атрибутов


В значении атрибута, которое интерпретируется как шаблон значения атрибута, например, в атрибуте в фиксированном конечном элементе, можно использовать , окружив его фигурными скобками ({}). При обработке шаблона значения атрибута данное выражение с окружающими его фигурными скобками заменяется результатом обработки этого выражения, а полученный объект преобразуется в строку как при вызове функции . В стиле XSLT в значении атрибута фигурные скобки не распознаются, если не было специально указано, что этот атрибут обрабатывается как шаблон значения атрибута. В сводном синтаксисе элемента значение таких атрибутов ставится в фигурные скобки.

Замечание: Не все атрибуты интерпретируются как шаблоны значений атрибутов. Атрибуты, значением которых является выражение или образец, атрибуты элементов , а также атрибуты, ссылающиеся на именованные объекты XSLT, не интерпретируются. Кроме того, в качестве шаблонов значений атрибутов не интерпретируются атрибуты xmlns, иначе это не согласовалось бы с соответствующими рекомендациями спецификации XML Namespaces.

В следующем примере из исходного элемента photograph создается конечный элемент img, значение атрибута src в элементе img вычисляется по значению переменной image-dir и строковому значению непосредственного потомка href элемента photograph, значение атрибута width в элементе img вычисляется по значению атрибута width непосредственного потомка size элемента photograph:

<xsl:variable name="image-dir">/images</xsl:variable>

<xsl:template match="photograph"> <img src="{$image-dir}/{href}" width="{size/@width}"/> </xsl:template>

Из исходного кода

<photograph> <href>headquarters.jpg</href> <size width="300"/> </photograph>

будет получено

<img src="/images/headquarters.jpg" width="300"/>

При обработке шаблона значения атрибута двойная левая или правая фигурные скобки за пределами выражения будут заменены на одинарную фигурную скобку. Если в шаблоне значения атрибута за пределами выражения обнаружена правая фигурная скобка, но за ней нет второй правой фигурной скобки, фиксируется ошибка. В выражении внутри правая фигурная скобка не воспринимается как завершающая это выражение.

В выражении фигурные скобки рекурсивно не обрабатываются. Например, использовать:

<a href="#{id({@ref})/title}">

не разрешается. Вместо этого воспользуйтесь просто:

<a href="#{id(@ref)/title}">



Схема обработки


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

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



Сообщения


<!-- Category: instruction -->
<xsl:message
terminate = "yes" | "no">
  <!-- Content: template -->
</xsl:message>

Инструкция xsl:message посылает сообщение, причем способ отправки зависит от XSLT процессора. Содержимое инструкции xsl:message является шаблоном. xsl:message обрабатывается путем подстановки его содержимого в создаваемый XML фрагмент. Этот XML фрагмент является содержимым посылаемого сообщения.

Замечание: XSLT процессор может реализовывать элемент xsl:message, открывая окно с предупреждением, либо делая запись в log-файле.

Если атрибут terminate имеет значение yes, то после посылки сообщения XSLT процессор должен завершить обработку. Значением по умолчанию является no.

Одним из удобных способов локализации состоит в том, чтобы поместить локализованную информацию (текст сообщения и прочего) в некий XML документ, который станет для стиля дополнительным входным файлом. Предположим к примеру что сообщение для языка L помещено в XML-файл resources/L.xml в следующем формате:

<messages> <message name="problem">A problem was detected.</message> <message name="error">An error was detected.</message> </messages>

В этом случае для локализации сообщений стиль может использовать следующий прием:

<xsl:param name="lang" select="en"/> <xsl:variable name="messages"

select="document(concat('resources/', $lang, '.xml'))/messages"/>

<xsl:template name="localized-message">

<xsl:param name="name"/> <xsl:message> <xsl:value-of select="$messages/message[@name=$name]"/> </xsl:message> </xsl:template>

<xsl:template name="problem"> <xsl:call-template name="localized-message"/> <xsl:with-param name="name">problem</xsl:with-param> </xsl:call-template> </xsl:template>



Соответствие спецификации


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

Замечание: Разработчикам XSLT процессоров настоятельно рекомендуется обеспечить возможность проверить, что их процессор работает согласно требованиям спецификации. Для этого необходимо разрешить вывод конечного дерева в виде XML или предоставить доступ к конечному дереву через стандартный API, такой как DOM или SAX.

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

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



Сортировка


<xsl:sort
select = string-expression
  lang = { nmtoken }
  data-type = { "text" | "number" | qname-but-not-ncname }
  order = { "ascending" | "descending" }
  case-order = { "upper-first" | "lower-first" } />

Сортировка задается с помощью элементов xsl:sort, данных как непосредственный потомок элемента xsl:apply-templates или xsl:for-each. Первый непосредственный потомок xsl:sort задает первичный ключ сортировки, второй непосредственный потомок xsl:sort задает вторичный ключ сортировки, и так далее. Если элемент xsl:apply-templates или xsl:for-each имеет одного или несколько непосредственных потомков xsl:sort, то вместо того чтобы обрабатывать выбранные узлы в том порядке как они следуют в документе, сперва производится их упорядочение в соответствии с заданными ключами сортировки, и лишь затем они обрабатываются в полученном порядке. При использовании в xsl:for-each элементы xsl:sort должны ставиться в начале. Если обрабатывается шаблон из xsl:apply-templates и xsl:for-each, то в качестве берется полный отсортированный список обрабатываемых узлов.

xsl:sort имеет атрибут select, значением которого является . Указанное выражение вычисляется для каждого узла, подлежащего обработке. При этом данный узел используется в качестве текущего узла, а полный неупорядоченный список узлов, подлежащих обработке, выступает в роли текущего набора узлов. Полученный после вычисления объект преобразуется в строку как при вызове функции . Данная строка используется как ключ сортировки для этого узла. По умолчанию атрибут select имеет значение ., которое приводит к тому, что в качестве ключа сортировки используется строковое значение текущего узла.

Полученная строка используется как ключ сортировки для данного узла. Ниже приведены необязательные атрибуты элемента xsl:sort, управляющие упорядочением списка ключей сортировки, значения всех этих атрибутов рассматриваются как .


order определяет, следует ли сортировать строки в направлении к предкам или потомкам. ascending определяет порядок в направлении к предкам. descending определяет порядок сортировки в направлении к потомкам. По умолчанию подразумевается ascending

lang задает язык для ключей сортировки. Атрибут имеет тот же самый диапазон значений, что и xml:lang . Если значение lang не указано, язык должен определяться из системного окружения.

data-type определяет тип данных для данных строк, разрешены следующие значения:



text указывает, что ключи сортировки должны быть упорядочены лексически в соответствии с культурными особенностями языка, указанного в атрибуте lang

number указывает что ключи сортировки должны быть преобразованы в числа, а затем упорядочены в соответствии со своим числовым значением, ключ сортировки преобразуется в число как при вызове функции , атрибут lang игнорируется

с префиксом преобразуется в как описано в главе . Расширенное имя идентифицирует тип данных. Данный документ не конкретизирует действия, предпринимаемые в этом случае.

Значение по умолчанию - text.

Замечание: Рабочая группа XSL планирует, что будущие версии XSLT будут использовать схемы XML для определения других значений для этого атрибута.

case-order имеет значение upper-first или lower-first. Данный атрибут используется когда есть data-type="text" и указано что заглавные буквы должны ставиться прежде прописных, либо, соответственно, наоборот. Например, если есть lang="en", то последовательность A a B b получается после сортировки с case-order="upper-first", а a A b B - после case-order="lower-first". Значение по умолчанию зависит от языка.

Замечание: Два разных XSLT процессора, соответствующих спецификации, могут выполнять сортировку не совсем одинаково. Некоторые из XSLT процессоров могут не поддерживать некоторые языки. Более того, для любого конкретного языка может варьироваться сортировка, которая не была задана атрибутом xsl:sort. Например, делается ли в японском языке сперва сортировка Hiragana или Katakana.


В будущих версиях XSLT могут появиться дополнительные атрибуты, дающие контроль над такими вариациями. Для этой цели реализация в xsl:sort может использовать атрибуты, привязанные к специальным пространствам имен.

Замечание: Рекомендуется чтобы разработчики обращались к за информацией по интернациональной сортировке.

Сортировка должна быть постоянной: в отсортированном списке узлов любое подмножество, имеющее ключи сортировки, дающие при сравнении равенство, должно быть выстроено в том же порядке, как и в исходном документе.

К примеру, предположим, что база данных служащих имеет формат

<employees> <employee> <name> <given>James</given> <family>Clark</family> </name> ...

</employee> </employees>

в таком случае список служащих можно отсортировать по имени с помощью:

<xsl:template match="employees"> <ul> <xsl:apply-templates select="employee"> <xsl:sort select="name/family"/> <xsl:sort select="name/given"/> </xsl:apply-templates> </ul> </xsl:template>

<xsl:template match="employee"> <li> <xsl:value-of select="name/given"/> <xsl:text> </xsl:text> <xsl:value-of select="name/family"/> </li> </xsl:template>


Создание атрибутов с помощью xsl:attribute


<!-- Category: instruction -->
<xsl:attribute
name = { qname }
  namespace = { uri-reference }>
  <!-- Content: template -->
</xsl:attribute>

Чтобы к конечным элементам добавить атрибуты, можно использовать элемент xsl:attribute независимо от того, созданы ли первые фиксированными конечными элементами или такими инструкциями, как xsl:element. для создаваемого атрибута задается обязательным атрибутом name и необязательным атрибутом namespace. Обработка элемента xsl:attribute добавляет к узлу, содержащему конечный элемент, узел атрибута. Содержимое элемента xsl:attribute является шаблоном для значения создаваемого атрибута.

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

Если имеется атрибут namespace, он тоже интерпретируется как . Строка, которая получается после его обработки, должна быть ссылкой URI. Однако если эта строка не является синтаксически корректной ссылкой URI, ошибка фиксироваться не будет. Если строка пуста, расширенное имя этого атрибута имеет пустой URI пространства имен. В противном случае, эта строка используется как URI пространства имен для расширенного имени создаваемого атрибута. Локальная часть , задаваемая атрибутом name, используется как локальная часть расширенного имени создаваемого атрибута.

При выборе префикса для вывода созданного атрибута в виде XML XSLT процессоры могут воспользоваться префиксом , указанным в атрибуте name. Однако процессоры не обязаны делать именно так, а если префиксом является xmlns, то им так делать и не разрешается.
Таким образом, хотя следующая инструкция ошибки не вызовет <xsl:attribute name="xmlns:xsl" namespace="whatever">http://www.w3.org/1999/XSL/Transform</xsl:attribute>

она не приведет к появлению декларации пространства имен.

Добавленный к элементу атрибут заменяет любой из уже имевшихся атрибутов этого элемента с таким же расширенным именем.

Возможные ошибки:

Добавление атрибута к элементу после того как к нему добавлен непосредственный потомок. Реализации процессора могут либо сигнализировать об этой ошибке, либо игнорировать этот атрибут.

Добавление атрибута к узлу, не являющемуся элементом. Реализации процессора должны либо сигнализировать об этой ошибке, либо игнорировать такой атрибут.

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

Замечание: Если xsl:attribute содержит текстовый узел с символом перехода на новую строку (newline), то выводимый XML должен содержать ссылку на символ. Например, <xsl:attribute name="a">x

y</xsl:attribute>

будет давать на выходе a="x&#xA;y"

(или любую эквивалентную этому ссылку на символ). На выходе XML не может появиться a="x y"

Это сделано потому, что XML 1.0 требует, чтобы символы newline в значениях атрибутов были преобразованы в пробелы (нормализованы), тогда как ссылки на символ newline нормализации не подлежат. Значения атрибута в рассматриваемой модели данных представляют собой значение атрибута после нормализации. Если символ newline, появившийся в значении атрибута в дереве, был представлен символом newline, а не ссылкой на символ, то в дереве после повторной обработки XML значение этого атрибута будет содержать уже не newline, а пробел, т.е. такое дерево будет показано неправильно.


Создание инструкций обработки


<!--

Category: instruction -->
<xsl:processing-instruction
  name = { ncname }>
  <!-- Content: template -->
</xsl:processing-instruction>

Для создания узла инструкции обработки используется элемент xsl:processing-instruction. Содержимое элемента xsl:processing-instruction является шаблоном для строкового значения узла инструкции обработки. Элемент xsl:processing-instruction имеет обязательный атрибут name, который определяет название данного узла инструкции обработки. Значение атрибута name интерпретируется как .

Например,

<xsl:processing-instruction name="xml-stylesheet">href="book.css" type="text/css"</xsl:processing-instruction>

создаст инструкцию обработки

<?xml-stylesheet href="book.css" type="text/css"?>

Если строка, полученная после обработки атрибута name, не является ни , ни , фиксируется ошибка. XSLT процессор может сигнализировать о такой ошибке. Если он этого не делает, то должен обработать ее сам, отказавшись поместить в конечное дерево соответствующую инструкцию обработки.

Замечание: Это означает что xsl:processing-instruction нельзя использовать для вывода XML декларации. Вместо нее должен использоваться элемент xsl:output (см. ).

Если при обработке содержимого xsl:processing-instruction создаются узлы, не являющиеся текстовыми, фиксируется ошибка. XSLT процессор может сигнализировать о такой ошибке. Если он этого не делает, то должен обработать ее сам, игнорируя неправильные узлы вместе с их содержимым.

Если результат обработки xsl:processing-instruction содержит строку ?>, фиксируется ошибка. XSLT процессор может сигнализировать об этой ошибке. Если он этого не делает, то должен обработать ее сам, поставив пробел после всех символов of ?, за которыми следовал символ >.



Создание элементов с помощью xsl:element


<!-- Category: instruction -->
<xsl:element
  name = { qname }
  namespace = { uri-reference }
  use-attribute-sets = qnames>
  <!-- Content: template -->
</xsl:element>

Элемент xsl:element позволяет создавать элемент с вычисляемым названием. создаваемого элемента определяется обязательным атрибутом name и необязательным атрибутом namespace. Содержимое элемента xsl:element является шаблоном для атрибутов и непосредственного потомка создаваемого элемента.

Атрибут name интерпретируется как . Если строка, получающаяся после обработки шаблона значения атрибута, не является , фиксируется ошибка. XSLT процессор может сигнализировать об этой ошибке, если он этого не делает, то должен обработать ошибку сам, представив результат обработки элемента xsl:element последовательностью узлов, созданных обработкой содержимого элемента xsl:element и исключением всех исходных узлов атрибутов. Если атрибут namespace не был предоставлен, приводится к расширенному имени с помощью деклараций пространства имен, в области действия которых находится данный элемент xsl:element, включая все декларации пространства имен по умолчанию.

Если атрибут namespace присутствует, также обрабатывается как . Строка, полученная после обработки шаблона значения атрибута, должна являться ссылкой URI. Если эта строка не будет синтаксически правильной ссылкой URI, ошибка фиксироваться не будет. Если строка пустая, то расширенное имя данного элемента имеет нулевой URI пространство имен. В противном случае, эта строка используется как URI пространства имен для расширенного имени создаваемого элемента. Локальная часть , задаваемая атрибутом name, используется как локальная часть в расширенном имени создаваемого элемента.

При отборе префикса для вывода созданного элемента в виде XML XSLT процессоры могут воспользоваться префиксом , задаваемым атрибутом name, однако они вовсе не обязаны поступать именно так.



Создание комментариев


<!-- Category: instruction -->
<xsl:comment>
<!-- Content: template -->
</xsl:comment>

Для создания в конечном дереве узла комментариев используется элемент xsl:comment. Содержимое элемента xsl:comment является шаблоном для строкового значения данного узла комментария.

Например,

<xsl:comment>This file is automatically generated. Do not edit!</xsl:comment>

создаст следующий комментарий

<!--This file is automatically generated. Do not edit!-->

Если при обработке содержимого xsl:comment создаются узлы, не являющиеся строковыми, фиксируется ошибка. XSLT процессор может сигнализировать о такой ошибке. Если он этого не делает, то должен обработать ее сам, игнорируя неправильные узлы вместе с их содержимым.

Если результат обработки содержимого xsl:comment содержит строку -- или заканчивается символом -, фиксируется ошибка. XSLT процессор может сигнализировать о такой ошибке. Если он этого не делает, он должен сам обработать ошибку, поставив пробел после всех символов -, за которыми следует либо другой символ -, либо конец строки.



Создание конечного дерева


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



Создание текста


Шаблон также может содержать текстовые узлы. Каждый текстовый узел в шаблоне, оставшийся после удаления пробельных символов, описанного в главе , создаст в конечном дереве текстовый узел с тем же самым строковым значением. Смежные текстовые узлы в конечном дереве автоматически объединяются.

Заметим, что текст обрабатывается на уровне дерева. Таким образом, разметка &lt; в шаблоне будет представлена в дереве стиля текстовым узлом, содержащим символ <. В результате в конечном дереве будет создан текстовый узел, содержащий символ <. Если конечное дерево представляется в виде XML документа, последний будет представлен разметкой &lt; или эквивалентной ссылкой на символ (при условии, что маскирование вывода не было блокировано, как описано в ).

<!-- Category: instruction -->
<xsl:text
disable-output-escaping = "yes" | "no">
  <!-- Content: #PCDATA -->
</xsl:text>

Символы фиксированных данных также могут быть помещены в элемент xsl:text. Такое окружение может отменить режим удаления пробельных символов (см. ), но не влияет на то, как эти символы впоследствии будут обрабатываться XSLT процессором.

Замечание: Атрибуты xml:lang и xml:space не обрабатываются в XSLT как-либо особо. Например,

автор стиля непосредственно отвечает за генерацию всех атрибутов xml:lang и xml:space, которые необходимы в результате;

появление атрибута xml:lang или xml:space в элементе из пространства имен XSLT не приводит к появлению атрибутов xml:lang или xml:space в конечном материале.



Создание текста с помощью xsl:value-of


<!-- Category: instruction -->
<xsl:value-of
select = string-expression
  disable-output-escaping = "yes" | "no" />

Для создания текстового узла в конечном дереве используется элемент xsl:value-of. Обязательный атрибут select является . Это выражение обрабатывается, а полученный объект преобразуется в строку как при вызове функции . Эта строка задает строковое значение создаваемого текстового узла. Если строка пустая, текстовый узел создаваться не будет. Созданный текстовый узел будет объединен с любыми соседствующими с ним текстовыми узлами.

Чтобы скопировать набор узлов в конечное дерево, не преобразуя его в строку, можно использовать элемент xsl:copy-of. См. .

Например, в следующем примере из элемента person с атрибутами given-name и family-name создается параграф HTML. Этот параграф будет содержать значение атрибута given-name из текущего узла, за которым следуют пробел и значение атрибута family-name того же текущего узла.

<xsl:template match="person"> <p> <xsl:value-of select="@given-name"/> <xsl:text> </xsl:text> <xsl:value-of select="@family-name"/> </p> </xsl:template>

В другом примере параграф HTML создается из элемента person, имеющего непосредственными потомками элементы given-name и family-name. Полученный параграф будет содержать строковое значение первого элемента given-name - непосредственного потомка текущего узла, затем последует пробел и строковое значение первого встретившегося элемента family-name, являющегося непосредственным потомком текущего узла.

<xsl:template match="person"> <p> <xsl:value-of select="given-name"/> <xsl:text> </xsl:text> <xsl:value-of select="family-name"/> </p>

</xsl:template>

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

<xsl:template match="procedure"> <fo:block> <xsl:value-of select="ancestor-or-self::*[@security][1]/@security"/> </fo:block> <xsl:apply-templates/> </xsl:template>



Статус документа


Данный документ был рассмотрен членами W3C, другими заинтересованными сторонами и одобрен Директором в качестве W3C. Это окончательный документ, который можно использовать как материал для ссылки или цитирования в других документах в качестве нормативного материала. Участие W3C в разработке данной Рекомендации заключается в привлечении внимания к представленной спецификации и способствовании ее всеобщему распространению. Тем самым повышается функциональность и универсальность Сети.

Перечень ошибок, выявленных в этой спецификации, доступен по адресу .

Комментарии к данной спецификации можно выслать по адресу , доступен также комментариев. Открытое обсуждение XSL, включая XSL Transformations, происходит в почтовом списке рассылки .

Нормативной силой наделен лишь английский вариант этой спецификации. Однако по адресу можно найти перевод этого документа на другие языки.

Перечень текущих Рекомендаций W3C, а также другие технические документы можно найти по адресу .

Данная спецификация была разработана в рамках .



Удаление пробельных символов


После построения дерева исходного документа или документа стиля, но перед какой-либо его обработкой XSLT процессором, выполняется очистка (stripping) некоторых текстовых узлов. Текстовый узел вычищается только тогда, когда он содержит одни пробельные символы. При очистке текстовый узел удаляется из дерева документа. На вход процедура очистки получает перечень названий элементов, для которых следует сохранить пробельные символы. Процедура очистки применяется как для стилей, так и для исходных документов, однако перечень названий элементов, сохраняющих пробельные символы, для стилей и исходных документов определяется отдельно.

Текстовый узел сохраняется если имеет место какое-либо из следующих условий:

Название элемента, являющегося родителем данного текстового узла, находится в перечне названий элементов, сохраняющих пробельные символы.

Текстовый узел содержит хотя бы один непробельный символ. Как и в XML, пробельным символом считаются #x20, #x9, #xD и #xA.

Элемент, являющийся предком этого текстового узла, имеет атрибут xml:space со значением preserve и нет более близких элементов-предков, имеющих xml:space со значением default.

В остальных случаях текстовый узел вычищается.

Атрибуты xml:space из дерева не вычищаются.

Замечание: Это подразумевает, что если для фиксированного конечного элемента был указан атрибут xml:space, то он будет включен в результат.

В случае со стилями перечень названий элементов, сохраняющих пробельные символы, состоит лишь из xsl:text.

<!-- Category: top-level-element -->
<xsl:strip-space
elements = tokens />

<!-- Category: top-level-element -->
<xsl:preserve-space
  elements = tokens />

Для исходных документов перечень названий элементов, сохраняющих пробельные символы, задается элементами xsl:strip-space и xsl:preserve-space. Каждый из этих элементов имеет атрибут elements, значением которого является перечень -ов (через пробельный символ). Изначально набор названий элементов, сохраняющих пробельные символы, содержит названия всех элементов.
Если название элемента совпадает с в элементе xsl:strip-space, то он удаляется из перечня названий элементов, сохраняющих пробельные символы. Если название элемента совпадает с в элементе xsl:preserve-space, то оно добавляется к перечню названий элементов, сохраняющих пробельные символы. Элемент соответствует тогда и только тогда, когда для и этого узла дает результат true. Конфликты между соответствием элементам xsl:strip-space и xsl:preserve-space разрешаются так же как конфликты между правилами шаблона (см. ). Таким образом, образец, соответствующий заданному названию элемента, определяется следующим образом:

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

Далее, любой образец с , который имеет более низкий , чем у для другого образца, игнорируется.

Если и после этого остается более одного образца, соответствующего названию элемента, фиксируется ошибка. XSLT процессор может фиксировать ошибку. Если он этого не делает, то должен обработать ее сам, выбрав среди оставшихся соответствующих названию элемента образцов тот, который в этом стиле был найден последним.


Включение стилей


<!-- Category: top-level-element -->
<xsl:include
href = uri-reference />

С помощью элемента xsl:include один стиль XSLT может включить в себя другой стиль XSLT. Элемент xsl:include имеет атрибут href, значением которого является ссылка URI, идентифицирующая включаемый стиль. Относительная ссылка URI обрабатывается относительно базового URI элемента xsl:include (см. ).

Элемент xsl:include можно использовать лишь в качестве элемента .

Включение оперирует деревьями XML. Ресурс, на который указывает атрибут href, обрабатывается как документ XML и обнаруженные в нем непосредственные потомки элемента xsl:stylesheet замещают элемент xsl:include во включающем документе. Тот факт, что те или иные правила шаблона или определения были получены включением, на то как они затем обрабатываются не влияет.

Во включаемом стиле может использоваться упрощенный синтаксис, описанный в главе . Включаемый стиль обрабатывается точно так же как эквивалентный ему элемент xsl:stylesheet.

Если стиль прямо или опосредовано включает сам себя, фиксируется ошибка.

Замечание: Многократное включение стиля может привести к ошибкам вследствие дублирования деклараций. Такие множественные включения не столь очевидны, если являются косвенными. Например, если стиль B включает стиль A, стиль C включает стиль A, а стиль D включает оба стиля B и C, то A опосредованно включено в D дважды. Если все указанные стили B, C и D являются независимыми, то ошибки можно избежать, если в B выделить все, что не относится к включенному A, в отдельный стиль B' и поменять B так чтобы он просто включал эти B' и A, затем аналогично поступить с C, и, наконец, переписать D так чтобы он включал A, B' и C'.



Встроенные правила шаблона


Имеется встроенное правило шаблона, позволяющее рекурсивно продолжать обработку в отсутствии успешного сравнения с явным правилом шаблона в стиле. Это правило шаблона используется как для узлов элементов, так и для корневого узла. Далее приведен эквивалент встроенного правила шаблона:

<xsl:template match="*|/"> <xsl:apply-templates/> </xsl:template>

Для каждого метода также есть встроенное правило шаблона, позволяющее рекурсивно продолжать обработку в том же самом режиме, в отсутствии успешного сравнения с образцом из явного правила шаблона в этом стиле. Это правило шаблона применяется как для узлов элементов, так и для корневого узла. Далее приведен эквивалент встроенного правила шаблона для режима m.

<xsl:template match="*|/" mode="m"> <xsl:apply-templates mode="m"/> </xsl:template>

Также есть встроенное правило шаблона для текстовых узлов и узлов атрибутов, которое просто копирует текст:

<xsl:template match="text()|@*"> <xsl:value-of select="."/> </xsl:template>

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

<xsl:template match="processing-instruction()|comment()"/>

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

Встроенные правила шаблона обрабатываются так, как будто они были неявно импортированы прежде стиля, а потому имеют меньший , чем все остальные правила шаблона. Таким образом, автор может переопределить встроенное правило шаблона, явно включив новое правило шаблона.



Встроенные стили


Обычно стиль XSLT является полноценным XML документом с элементом xsl:stylesheet в качестве элемента документа. Однако стиль XSLT может вынесен и в другой источник. Возможны два варианта размещения:

стиль XSLT может быть помещен как текст в источник, имеющий формат, отличный от XML, либо элемент xsl:stylesheet может появиться в XML документе, но не в качестве элемента документа.

Чтобы содействовать второму варианту размещения, элемент xsl:stylesheet может иметь атрибут ID, который задает уникальный идентификатор.

Замечание: Чтобы такой атрибут можно было использовать с функцией из XPath, он реально должен быть декларирован в DTD как ID.

Следующий пример показывает, каким образом можно использовать инструкцию обработки xml-stylesheet чтобы позволить документу содержать свой собственный стиль. Чтобы найти элемент xsl:stylesheet, ссылка URI использует относительный URI с идентификатором фрагмента:

<?xml-stylesheet type="text/xml" href="#style1"?> <!DOCTYPE doc SYSTEM "doc.dtd"> <doc> <head> <xsl:stylesheet id="style1" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> <xsl:import href="doc.xsl"/> <xsl:template match="id('foo')"> <fo:block font-weight="bold"><xsl:apply-templates/></fo:block> </xsl:template> <xsl:template match="xsl:stylesheet"> <!-- игнорируется --> </xsl:template> </xsl:stylesheet> </head> <body> <para id="foo"> ... </para> </body> </doc>

Замечание: Стиль, который вложен в документ, к которому должен быть применен, либо стиль, включенный или импортированный в такой стиль, как правило, должен иметь правило шаблона, сообщающее, что элементы xsl:stylesheet должны быть проигнорированы.



В данной спецификации определяется синтаксис


В данной спецификации определяется синтаксис и семантика языка XSLT. Преобразование в языке XSLT предстает в виде корректного (well-formed) XML документа , соответствующего требованиям для пространств имен из Рекомендации XML . Оно может содержать как элементы, определяемые в XSLT, так и элементы, которые в XSLT не определены. Элементы, определяемые в XSLT, отличаются принадлежностью определенному пространству имен XML (см. главу ), которое в данной спецификации мы называем пространством имен XSLT. Таким образом, данная спецификация - это определение синтаксиса и семантики пространства имен XSLT.
Преобразование, выраженное через XSLT, описывает правила преобразования исходного дерева документа в конечное дерево. Преобразование строится путем сопоставления образцов и шаблонов. Образец сравнивается с элементами исходного дерева, а шаблон используется для создания частей конечного дерева. Конечное дерево отделено от исходного дерева. Структура конечного дерева может полностью отличаться от структуры исходного дерева. В ходе построения конечного дерева элементы исходного дерева могут подвергаться фильтрации и переупорядочению, также может добавлена новая структура.
Преобразование, выраженное через XSLT, называется стилем (stylesheet). Так сделано потому, что в случае, когда XSLT приводится к словарю форматирования XSL, данное преобразование выполняет функции стиля.
Данный документ не конкретизирует, каким образом стиль XSLT привязывается к документу XML. Рекомендуется чтобы процессоры XSL поддерживали механизм, описанный в документе . Когда этот или какой-либо другой механизм дает последовательность из нескольких стилей XSLT, которые должны быть применены к XML-документу одновременно, это будет то же самое, как если бы использовался один стиль, поочередно импортирующий все члены этой последовательности стилей (см. ).
Стиль содержит набор правил шаблона. Правило шаблона состоит из двух частей: это образец, который сопоставляется с узлами в исходном дереве, и шаблон, который может быть обработан для формирования фрагмента в конечном дереве.
Такая схема позволяет использовать один стиль для большого класса документов, имеющих одинаковую структуру исходного дерева.
Чтобы получить фрагмент в конечном дереве, шаблон обрабатывается для определенного элемента в исходном документе. Шаблон может содержать элементы, определяющие фиксированную структуру конечного элемента. Шаблон может также содержать элементы из пространства имен XSLT, дающие инструкции по созданию фрагментов конечного дерева. При обработке шаблона каждая инструкция обрабатывается и заменяется на полученный фрагмент конечного дерева. Инструкции могут находить в исходном дереве и обрабатывать элементы-потомки. При обработке элемента-потомка в конечном дереве создается фрагмент путем нахождения соответствующего правила шаблона и обработки его шаблона. Заметим, что элементы обрабатываются только если они были выбраны в ходе выполнения инструкции. Конечное дерево строится после нахождения правила шаблона для корневого узла и обработки в нем шаблона.
В ходе поиска соответствующего правила шаблона может выясниться, что данному элементу соответствует не одно, а сразу несколько правил. Однако использоваться будет только одно правило шаблона. Методика для определения, какое из правил шаблона должно использоваться, описывается в разделе .
Шаблон даже сам по себе наделен значительной мощностью: он может создавать структуры произвольной сложности, извлекать строковые значения из любых мест исходного дерева, создавать структуры, повторяющие появление элементов в исходном дереве. Для простых преобразований, когда структура конечного дерева не связана со структурой исходного дерева, стиль часто образуется одним шаблоном, который используется как шаблон для всего конечного дерева. К этому типу часто относится преобразование XML документов, которые содержат некие данные (см. ). Для таких стилей в XSLT предусмотрен упрощенный синтаксис (см. ).
Если обрабатывается шаблон, то это всегда делается отталкиваясь от текущего узла и текущего набора узлов. Текущий узел всегда является членом текущего набора узлов.


В XSLT многие операции привязаны к текущему узлу. И лишь несколько инструкций меняют текущий набор узлов или текущий узел (см. и ). При обработке любой из этих инструкций текущий набор узлов заменяется новым набором узлов, а каждый член этого нового набора по очереди становится текущим узлом. После того как обработка инструкции завершена, текущий узел и текущий набор узлов становится такими, каким они были до обработки этой инструкции.
Для выбора элементов для обработки, обработки при условии и генерации текста XSLT использует язык выражений, сформулированный в .
XSLT оставляет две "зацепки" для дальнейших расширений языка. Первая связана с расширением набора элементов инструкций, используемых в шаблонах, а вторая - с расширением набора функций, используемых в выражениях XPath. Обе эти зацепки основаны на использовании пространства имен XML. Механизм их реализации в данной версии XSLT не конкретизируется. См. главу .
Замечание: Указанный механизм рабочая группа XSL должна определить в следующем варианте спецификации, либо в отдельной спецификации.
Для описания синтаксиса элементов, определенных в XSLT, используется общая нотация синтаксиса элементов, описаная в главе .
Для стилей XSLT должен использоваться тип среды MIME text/xml или application/xml . Возможно, специально для работы со стилями XSLT будет зарегистрирован еще один тип среды. Если это произойдет, то он тоже может быть использован.

Вычисление подставляемого текста


В шаблоне для вычисления генерируемого текста, например, при выделении текста из исходного дерева или подстановке значения переменной может использоваться элемент xsl:value-of. Делается это в элементе xsl:value-of с помощью , представленного как значение атрибута select. Заключив в фигурные скобки ({}), выражения можно также использовать в значении атрибутов фиксированных конечных элементов.



Выражения


XSLT использует язык выражений, сформулированный в XPath . Выражения в XSLT используются для таких целей, как:

выбор узлов для обработки; формулирование условий для разных вариантов обработки узла; генерация текста для подстановки в конечное дерево.

Выражение должно соответствовать сценарию из XPath.

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

Внешнее выражение в XSLT (т.е. выражение, не являющееся частью какого-либо другого выражения) получает свой контекст следующим образом:

узел контекста получается из

положение в контексте определяется положением в , первая позиция имеет индекс 1

размер контекста определяется размером

привязка переменных контекста - это привязка в пределах видимости того элемента, которому принадлежит атрибут с рассматриваемым выражением (см. )

набор деклараций пространства имен - это те декларации, в области видимости которых находится элемент, содержащий атрибут с рассматриваемым выражением. Сюда относится также неявная декларация префикса xml, обязательная согласно W3C Namespaces Recommendation . Пространство имен по умолчанию (декларируемое в xmlns) к этому набору деклараций не относится

используемая библиотека функций формируется из основной библиотеки функций, дополнительных функций, описанных в главе , а также функций расширения, описанных в главе . Если в выражении появится вызов какой-либо другой функции, зафиксируется ошибка.



XSLT процессор может выводить конечное


<!-- Category: top-level-element -->
<xsl:output
  method = "xml" | "html" | "text" | qname-but-not-ncname
  version = nmtoken
  encoding = string
  omit-xml-declaration = "yes" | "no"
  standalone = "yes" | "no"
  doctype-public = string
  doctype-system = string
  cdata-section-elements = qnames
  indent = "yes" | "no"
  media-type = string />
XSLT процессор может выводить конечное дерево в виде последовательности байтов, хотя и не обязан иметь такую возможность (см. ). Элемент xsl:output позволяет авторам стилей указывать, каким они хотят видеть конечное дерево при выводе. Если XSLT процессор выводит на печать конечное дерево, он должен делать это так, как задано элементом xsl:output, однако сам вывод процессор выполнять не обязан.
Элемент xsl:output можно использовать только как элемент .
Атрибут method в xsl:output идентифицирует общий метод, который должен использоваться для вывода конечного дерева. Значением атрибута должно быть . Если не имеет префикса, то оно идентифицирует метод, описываемый данным документом, и должно соответствовать одному из трех названий: xml, html или text. Если имеет префикс, то такое приводится к , как описано в главе . Расширенное имя идентифицирует метод вывода. Поведение в этом случае данный документ не описывает.
По умолчанию атрибут method выбирается следующим образом. Если
корневой узел конечного дерева имеет элемент непосредственным потомком,
расширенное имя первого элемента в конечном дереве, который является непосредственным потомком корневого узла (например, элемент документа) имеет локальную часть html (в любом сочетании верхних и нижних регистров) и нулевой URI пространства имен,
все текстовые узлы, предшествующие первому элементу в конечном дереве, являющемуся непосредственным потомком корневого узла, содержат только пробельные символы,



то тогда методом вывода по умолчанию является html. В противном случае таковым является xml. Метод вывода по умолчанию должен быть использован если нет элементов xsl:output, либо ни один элемент xsl:output не определяет значения атрибута method.
Остальные атрибуты в xsl:output определяют параметры для метода вывода. Разрешается использовать следующие атрибуты:
version указывает версию метода вывода
indent указывает, может ли XSLT процессор ставить дополнительные пробелы при выводе конечного дерева, атрибут должен иметь значение yes или no
encoding указывает предпочтительную кодировку символов, которую XSLT процессор должен использовать чтобы представить последовательность символов в виде последовательности байтов. Значение атрибута должно обрабатываться независимо от используемого регистра. Значение атрибута должно состоять из символов из диапазона от #x21 до #x7E (т.е. печатных ASCII символов). Значением должно быть либо charset, зарегистрированный Internet Assigned Numbers Authority , , либо строка начинающаяся с X-
media-type определяет тип среды (тип контента MIME) для данных, полученных при выводе конечного дерева. Параметр charset не должен указываться явно. Наоборот, параметр charset должен добавляется когда типом среды на верхнем уровне является text, причем в соответствии с той кодировкой символов, которая реально используется данным методом вывода
doctype-system указывает системный идентификатор, который должен использоваться в декларации типа документа
doctype-public указывает публичный идентификатор, который должен использоваться в декларации типа документа
omit-xml-declaration указывает, должен ли XSLT процессор выводить декларацию XML, значением атрибута должно быть yes или no
standalone указывает, должен ли XSLT процессор выводить декларацию одиночного документа. Значением атрибута должно быть yes или no
cdata-section-elements определяет перечень названий элементов, чьи непосредственные потомки, являющиеся текстовыми узлами, должны печататься с помощью блоков CDATA


Детальная семантика каждого атрибута будет описана отдельно для каждого метода вывода, в котором он используется. Если семантика атрибута для метода вывода не описана, использовать ее для этого метода нельзя.
Стиль может содержать несколько элементов xsl:output, а также может включить или импортировать другие стили, также содержащие элементы xsl:output. Все элементы xsl:output, обнаруженные в стиле, объединяются в один эффективный элемент xsl:output. Для атрибута cdata-section-elements эффективное значение является объединением всех указанных значений. Для остальных атрибутов эффективным является значение, указанное с наивысшим . Если таких значений для атрибута было несколько, фиксируется ошибка. XSLT процессор может фиксировать такую ошибку. Если он этого не делает, то должен обрабатывать ошибку сам, используя то значение, которое в стиле было обнаружено последним. Значения атрибутов берутся по умолчанию после того, как были объединены элементы xsl:output, разные методы вывода по умолчанию могут иметь различные значения атрибута.

Запрет маскирования при выводе


Обычно метод вывода xml, представляя текстовые узлы, маскирует & и < (а также, возможно, и другие символы). Тем самым обеспечивается вывод корректного XML документа. Иногда однако бывает удобно иметь возможность показывать почти, но не совсем корректный документ XML. Например, вывод может содержать некорректные разделы, которые будут преобразованы в корректный XML последующей процедурой, не связанной с XML. По этой причине XSLT предоставляет механизм запрета маскирования при выводе. Элементы xsl:value-of или xsl:text могут содержать атрибут disable-output-escaping, который может иметь значения yes или no. По умолчанию подразумевается значение no. Если значение атрибута yes, текстовый узел, полученный обработкой элемента xsl:value-of или xsl:text, должен быть представлен без маскирования. Например,

<xsl:text disable-output-escaping="yes">&lt;</xsl:text>

должен сгенерировать единственный символ <.

Если маскирование при выводе было запрещено для текстового узла, который используется где-либо еще кроме текстового узла в конечном дереве, фиксируется ошибка. Таким образом, будет ошибкой запретить маскирование для элемента xsl:value-of или xsl:text, который используется для получения строкового значения к комментарию, инструкции обработки или узлу атрибута. Ошибкой будет также преобразование в число или строку, если в этом фрагменте содержится текстовый узел, для которого было запрещено маскирование. В обоих случаях XSLT процессор может фиксировать ошибку. Если он этого не делает, то должен обработать ошибку сам, игнорируя атрибут disable-output-escaping.

Атрибут disable-output-escaping можно использовать и для метода вывода html, и для метода вывода xml. Метод вывода text игнорирует атрибут disable-output-escaping, поскольку при выводе не делает какого-либо маскирования.

XSLT процессор сможет запретить маскирование только если он контролирует, как будет представлено конечное дерево. А так может быть не всегда. Например, вместо показа конечное дерево может быть использовано как исходное дерево для другой XSLT трансформации. Маскирование при выводе XSLT процессор поддерживать не обязан. Если xsl:value-of или xsl:text указывают, что маскирование при выводе должно быть запрещено, а XSLT процессор такого режима не поддерживает, то процессор может фиксировать ошибку. Если же он этого не делает, то должен обработать ошибку сам, не отменяя маскирование при выводе.

Если маскирование запрещено для символа, который невозможно представить в той кодировке, которую для вывода использует XSLT процессор, то процессор может фиксировать ошибку. Если он этого не делает, то должен обработать ошибку сам, отменив запрет на маскирование при выводе.

Поскольку запрет на маскирование при выводе может работать не на всех XSLT процессорах и может создавать XML документы, которые будут некорректны, то этот режим должен использоваться только тогда, когда нет других альтернатив.



Значения переменных и параметров


Элемент привязки переменной может указывать значение переменной тремя разными способами.

Если элемент привязки переменной имеет атрибут select, то значением этого атрибута должно быть , а значением самой переменной является объект, полученный в результате обработки этого выражения. Содержимое элемента в этом случае должно быть пустым.

Если элемент привязки переменной не имеет атрибута select, но имеет непустое содержание (иначе говоря, элемент привязки переменной имеет один или несколько узлов - непосредственных потомков), тогда требуемое значение задается содержимым элемента привязки переменной. Содержимое элемента привязки переменной является шаблоном, который обрабатывается для получения значения данной переменной. Этим значением является фрагмент конечного дерева, эквивалентный набору узлов, состоящему из одного корневого узла, который в качестве непосредственных потомков имеет последовательность узлов, полученных при обработке представленного шаблона. Базовым URI для узлов в рассматриваемом фрагменте конечного дерева является базовый URI элемента привязки переменной.

Если в последовательности узлов, полученной при обработке шаблона, появится узел атрибута или узел пространства имен, фиксируется ошибка, поскольку корневой узел не может иметь непосредственным потомком ни узел атрибута, ни узел пространства имен. XSLT процессор может сигнализировать о такой ошибке. Если он этого не делает, то должен обработать ее сам, не добавляя соответствующий узел атрибутов или пространства имен.

Если элемент привязки переменной имеет пустое содержание и не имеет атрибута select, значением переменной является пустая строка. Таким образом

<xsl:variable name="x"/>

равнозначно

<xsl:variable name="x" select="''"/>

Замечание: Если переменная используется для нахождения узла по номеру позиции, то не следует делать следующего: <xsl:variable name="n">2</xsl:variable> ... <xsl:value-of select="item[$n]"/>

Результатом будет значение первого элемента item, поскольку переменная n будет привязана к фрагменту конечного дерева, а не к числу. Вместо этого делайте либо <xsl:variable name="n" select="2"/> ... <xsl:value-of select="item[$n]"/>

либо <xsl:variable name="n">2</xsl:variable> ... <xsl:value-of select="item[position()=$n]"/>

Замечание: Удобный прием, позволяющий задать пустой набор узлов в качестве значение по умолчанию для параметра: <xsl:param name="x" select="/.."/>