</p>
Элемент para
, который во входящем документе включен в другой элемент para
, не будет обработан по той простой причине, что он не вошел во множество, выбранное XPath-выражением 'bold
'. В то же время, если мы запишем
<xsl:template match='para'>
<p><xsl:apply-templates select='bold|para'/></p>
</xsl:template>
то результат будет таким же, как и прежде:
<p>
<b>text1</b>
<p>
<b>text2</b>
</p>
</p>
Следует хорошо понимать разницу между атрибутом select
элемента xsl:apply- templates
и атрибутом match
элемента xsl:template
. Атрибут match
содержит не XPath-выражение, а паттерн XSLT; в отличие от атрибута select в xsl:apply-templates
он не выбирает никакого множества узлов, он используется только для того, чтобы проверить, может ли данный узел обрабатываться этим шаблоном или нет.
Атрибут select
элемента xsl:apply-templates
наоборот, содержит не паттерн, а выражение, единственным требованием к которому является то, что оно должно возвращать множество узлов. Например, некорректным будет определение вида
<xsl:apply-templates select='para+1'/>
поскольку выражение para+1
не может возвратить множество узлов.
Кроме этого требования, никаких других ограничений на выражения в этом атрибуте нет. В нем можно использовать переменные, содержащие множества узлов, функции, возвращающие множества узлов (например, такие, как id
или key
), выражения с операциями над множествами (именно таким выражением — выражением объединения было выражение bold|para
), пути выборки, фильтрующие выражения, в общем, любые выражения, которые только могут возвращать множества. Например, для того, чтобы обработать содержимое произвольного внешнего XML-документа, в атрибуте select
элемента xsl:apply-template
следует использовать функцию document
.
Объявление вида
<xsl:apply-templates select='document('a.xml')//para'/>
применит шаблоны ко всем элементам para
документа a.xml
.
Режимы
Очень часто в преобразованиях требуется обрабатывать одни и те же узлы, но
Эта проблема решается в XSLT просто и элегантно. Атрибут mode
элемента xsl:template задает xsl:apply-templates
: в этом элементе он устанавливает xsl:apply-templates
процессор будет применять только те шаблоны преобразования, режим которых совпадает с выбранным режимом обработки.
В качестве примера приведем преобразование, которое добавляет в XHTML-файл перечень текстовых ссылок, обнаруженных в этом документе. Грубо говоря, XHTML — это XML-версия языка HTML, а значит XSLT вполне подходит для обработки XHTML-документов.
URI пространства имен языка XHTML — 'http://www.w3.org/1999/xhtml'
; этому языку мы назначим префикс 'xhtml
' и, кроме того, сделаем это пространство пространством имен по умолчанию:
<xsl:stylesheet
version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns:xhtml='http://www.w3.org/1999/xhtml'
xmlns='http://www.w3.org/1999/xhtml'>
...
</xsl:stylesheet>
Начнем с шаблона, который будет выводить каждую из ссылок. В каждой ссылке мы будем выводить только ее атрибут href
и текст, который она содержит. Для удобочитаемости мы также добавим элемент br
и символ переноса строки 

.
<xsl:template match='xhtml:a'>
<xsl:copy>
<xsl:copy-of select='@href|text()'/>
</xsl:copy>
<br/>
<xsl:text>
</xsl:text>
</xsl:template>
Мы чуть позже познакомимся с элементами xsl:copy
, xsl:copy-of
и xsl:text
, пока же скажем, что
<xsl:copy>
<xsl:copy-of select='@href|text()'/>
</xsl:copy>
копирует в выходящий документ текущий узел, его атрибут href
(@href
) и дочерние текстовые узлы (text()
).
Элемент <xsl:text>
</xsl:text>
выводит символ переноса строки. Элемент <br/>
является литеральным элементом результата — он никак не обрабатывается, а просто выводится в результирующий документ.
Следующее преобразование называется идентичным преобразованием — оно просто копирует все узлы один в один:
<xsl:template match='@*|node()'>
<xsl:copy>
<xsl:apply-templates select='@*|node()'/>
</xsl:copy>
</xsl:template>
И, наконец, нам понадобится преобразование для элемента body
— в него мы включим копию содержимого, а также ссылки, отсортированные в алфавитном порядке:
<xsl:template match='xhtml:body'>
<xsl:copy>
<xsl:apply-templates select='@*|node()'/>
<h1>Links found on this page:<h1>