</head>
<body><xsl:value-of select='content'/></body>
</html>
</xsl:template>
В принципе именованные шаблоны не обязаны иметь атрибут match
, но он все же может быть определен. В этом случае шаблон можно будет применять как для обработки частей документов элементом xsl:apply-templates
, так и вызывая его по имени элементом xsl:call- template
.
Изменим объявление нашего шаблона head следующим образом:
<xsl:template name='head' match='head'>
...
</xsl:template>
Теперь, если входящий документ будет иметь вид
<page>
<head/>
<content>Just a few words...</content>
</page>
то результат выполнения следующих двух шаблонов будет одинаков.
<xsl:template match='page'>
<html>
<xsl:apply-templates select='head'/>
<body><xsl:copy-of select='content/node()/></body>
</html>
</xsl:template>
<xsl:template match='page'>
<html>
<xsl:call-template name='head'/>
<body><xsl:copy-of select='content/node()/></body>
</html>
</xsl:template>
В чем же состоит разница вызова шаблона элементами xsl:apply-templates
и xsl:call-template
? Перечислим несколько отличий.
□ Элемент xsl:apply-templates
применяет подходящие шаблоны к узлам определенного множества; xsl:call-template
просто выполняет тело фиксированного именованного шаблона.
□ При вызове шаблона инструкцией xsl:apply-templates
происходит изменение контекста — обрабатываемое множество узлов становится текущим списком узлов преобразования, а обрабатываемый узел — текущим узлом; xsl:call-template
не изменяет контекст преобразования.
□ Инструкция xsl:apply-templates
позволяет использовать различные режимы — применяются только те шаблоны, значение атрибута mode
которых равно значению этого атрибута у вызывающей инструкции; xsl:call-template
выполняет шаблон с заданным именем вне зависимости от того, в каком режиме происходит обработка и каково значение атрибута mode
этого шаблона.
□ Если для обработки определенного узла подходит несколько шаблонов, то при выполнении xsl:apply-templates
процессор будет выбирать наиболее подходящий из них; xsl:call- template
всегда будет выполнять тот единственный шаблон преобразования, который имеет указанное имя.
□ Если в преобразовании не определен шаблон для обработки некоторого узла, но к нему элементом xsl:apply-templates
все же применяются шаблоны, процессор будет использовать шаблон обработки по умолчанию; если элемент xsl:call-template
вызывает отсутствующий шаблон, процессор выдаст сообщение об ошибке, потому что не сможет найти шаблон с заданным именем.
□ При использовании xsl:apply-templates
процессор игнорирует значения атрибутов name
элементов xsl:template
; точно так же xsl:call- template
принимает во внимание только значение атрибута name
, игнорируя атрибуты match
, mode
и priority
.
При желании можно найти еще с десяток отличий, но и этих положений вполне достаточно для того, чтобы понять разницу. Главным выводом из этого сравнения является то, что xsl:apply- templates
демонстрирует декларативный, а xsl:call-template
процедурный стиль программирования В первом случае мы используем объявленные (или задекларированные) правила преобразования, во втором — используем шаблон просто как процедуру.
Встроенные шаблоны
Для того чтобы обеспечить рекурсивную обработку документа при преобразовании, в XSLT существуют так называемые встроенные шаблоны. Несмотря на то, что они не описываются в преобразованиях явным образом, встроенные шаблоны применяются процессорами по умолчанию в случаях, когда более подходящих шаблонов нет.
Существуют пять основных шаблонных правил, которые применяются процессорами по умолчанию.
Первое из них обеспечивает рекурсивную обработку дочерних элементов документа, которые находятся как в корне, так и в других элементах. Это правило эквивалентно следующему шаблону:
<xsl:template match='*|/'>
<xsl:apply-templates/>
</xsl:template>
Второе встроенное правило преобразования аналогично первому, с той лишь особенностью, что для каждого режима преобразования рекурсивная обработка происходит в том же самом режиме. В XSLT это правило выглядело бы следующим образом:
<xsl:template match='*|/' mode='режим'>
<xsl:apply-templates mode='режим'/>
</xsl:template>
В XSLT также определяется встроенное правило для обработки текстовых узлов и атрибутов — это правило просто выводит их текстовые значения. Шаблон такого преобразования может быть записан в виде:
<xsl:template match='text()|@*'>
<xsl:value-of select='.'/>
</xsl:template>
Четвертое правило касается обработки инструкций по обработке и комментариев. Это правило не делает ничего, то есть инструкции и комментарии просто опускаются в выходящем документе. Шаблон такого преобразования будет иметь вид
<xsl:template match='processing-instruction()|comment()'/>
Последнее, пятое правило определяет обработку узлов пространств имен. Аналогично инструкциям и