новому.
□ Переменной может присваиваться результат преобразования, что позволяет манипулировать уже сгенерированными частями документа.
□ Переменные могут использоваться для более прозрачного доступа к внешним документам.
Первый случай использования совершенно очевиден: если в преобразовании многократно используется какое-либо сложное для вычисления или просто громоздкое для записи выражение, переменная может служить для сохранения единожды вычисленного результата. Например, если мы много раз обращаемся ко множеству ссылок данного документа посредством выражения вида:
//a[@href]
гораздо удобней и экономней с точки зрения вычислительных ресурсов объявить переменную вида
<xsl:variable name='links' select='//a[@href]'/>
и использовать ее в преобразовании как $a. Фильтрующие выражения языка XPath (продукция FilterExpr) позволяют затем обращаться к узлам выбранного множества так же, как если бы мы работали с изначальным выражением. Например, $a[1] будет эквивалентно //a[@href][1], a $a/@href — выражению //a[@href]/@href. При этом при обращении к $a процессор не будет заново искать все элементы a с атрибутом href, что, по всей вероятности, положительно скажется на производительности.
Другой иллюстрацией этому же случаю использования переменной может быть следующая ситуация: в некоторых случаях выражения могут быть просты для вычисления, но слишком громоздки для записи. Гораздо элегантней один раз вычислить это громоздкое выражение, сохранить его в переменной и затем обращаться по короткому имени. Например, следующий элемент xsl:variable вычисляет и сохраняет в переменной gv длинную и громоздкую ссылку:
<xsl:variable name='gv'
select='concat('http://host.com:8080/GeoView/GeoView.jsp?',
'Language=en&',
'SearchText=Select&',
'SearchTarget=mainFrame&',
'SearchURL=http://host.com:8080/servlet/upload')'/>
После такого определения применение этой ссылки в преобразовании становится удобным и лаконичным:
<а href='{$gv}' target='_blank'>Launch GeoBrowser</a>
Второй типовой случай использования переменных также заметно облегчает создание выходящего дерева, делая этот процесс гибким и легко конфигурируемым. Примером формирования HTML-документа при помощи такого подхода может быть следующий шаблон:
<xsl:template match='/'>
<html>
<xsl:copy-of select='$head'/>
<xsl:copy-of select='$body'/>
</html>
</xsl:template>
Достоинство этого подхода в том, что переменные, содержащие фрагменты деревьев как бы становятся модулями, блоками, из которых в итоге собирается результирующий документ.
Более практичным применением возможности переменных содержать фрагменты деревьев является условное присвоение переменной значения. Представим себе следующий алгоритм:
если
то
присвоить
иначе
присвоить
Для процедурного языка с изменяемыми переменными это не проблема. На Java такой код выглядел бы элементарно:
или чуть в более длинном варианте:
if (
else
Однако если бы в XSLT мы написали что-нибудь наподобие:
<xsl:choose>
<xsl:when test='
<xsl:variable name='
</xsl:when>
<xsl:otherwise>
<xsl:variable name='
</xsl:otherwise>
</xsl:choose>
то требуемого результата все равно не достигли бы по той простой причине, что определенные нами переменные были бы доступны только в своей области видимости, которая заканчивается закрывающими тегами элементов xsl:when и xsl:otherwise. Правильный шаблон для решения этой задачи выглядит следующим образом:
<xsl:variable name='
<xsl:choose>
<xsl:when test='
<xsl:copy-of select='
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select='
</xsl:otherwise>
</xsl:choose>
<xsl:variable>
Конечно, это не точно то же самое — на самом деле мы получаем не значение, а дерево, содержащее это значение, но для строковых и численных значений особой разницы нет: дерево будет вести себя точно так же, как число или строка. Для булевых значений и множеств узлов приходится изыскивать другие методы. Булевое значение можно выразить через условие, например:
<xsl:variable name='
select='(
Для множества узлов можно использовать предикаты и операции над множествами:
<xsl:variable name='
select='
Заметим, что шаблон, содержащийся в элементе xsl:variable, может включать в себя
