Чтение онлайн

ЖАНРЫ

Технология XSLT

Валиков Алексей Н.

Шрифт:

<xsl:with-param name="n" select="10"/>

</xsl:call-template>

 </xsl:template>

 <xsl:template name="for">

<xsl:param name="i" select="0"/>

<xsl:param name="n"/>

<xsl:if test="$i &lt; $n">

<option>

<xsl:value-of select="$i"/>

</option>

<xsl:call-template name="for">

<xsl:with-param name="i" select="$i + 1"/>

<xsl:with-param name="n" select="$n"/>

</xsl:call-template>

</xsl:if>

 </xsl:template>

</xsl:stylesheet>

Листинг 11.15
Выходящий документ

<option>0</option>

<option>1</option>

<option>2</option>

<option>3</option>

<option>4</option>

<option>5</option>

<option>6</option>

<option>7</option>

<option>8</option>

<option>9</option>

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

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

Метод Пиза для for-цикла

Для простых

for
– циклов, которые должны выполниться строго определенное число раз, вместо рекурсии можно использовать весьма остроумный метод, предложенный Венделлом Пизом (Wendell Piez, Mullberry Technologies, Inc). Суть метода состоит в том, что хоть мы и не можем сгенерировать множество узлов, выбрать множество с определенным количеством узлов нам вполне по силам.

Для начала выберем какое-нибудь множество узлов документа преобразования:

<xsl:variable name="set" select="document('')//node"/>

Затем для повторения определенных действий несколько раз используем конструкцию вида

<xsl:for-each select="$set[position &lt;= $number]">

 <!-- Действия -->

</xsl:for-each>

где

number
указывает требуемое число итераций.

При использовании метода Пиза следует учитывать следующие особенности.

□ Множество узлов

set
не должно быть слишком большим — иначе его выбор будет неэффективным.

□ Множество узлов

set
обязательно должно содержать число итераций (
number
) узлов.

В целом же метод Пиза — классический пример эффективного применения инструментов не по назначению.

Операции над множествами

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

деле реализуют далеко не математические операции над множествами.

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

node
принадлежит множеству
nodeset
тогда и только тогда, когда выполняется равенство

count($nodeset) = count($node | $nodeset)

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

Таблица 11.1. Операции над множествами

Операция Графическое представление XPath-выражение
Объединение
$A | $B
Пересечение
$А[count(.|$B)=count($B)]
Разность
$A[count(.|$B)!=count($B)]
Симметрическая разность
$A[count(.|$B)!=count($B)] | $B[count(.|$A)!=count($A)]

Приведенные выше методы были разработаны Майклом Кеем (Michael Kay, Software AG), Оливером Беккером (Oliver Becker, Humboldt-Universitat zu Berlin), Кеном Холманом (Ken Holman, Crane Softwrights Ltd.) и публикуются с любезного разрешения авторов.

Перенос строк и элементы BR

Большинству читателей, скорее всего, хорошо знаком такой элемент языка HTML, как

BR
, который используется для обозначения разрыва строки. В обычных текстовых файлах для той же самой цели используются символы с кодами
#xA
,
#xD
или их комбинации в зависимости от платформы. При совместном использовании неразмеченного текста и HTML часто возникает задача преобразования символов перевода строки в элементы
BR
и наоборот.

Замену элемента

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

Листинг 11.16. Шаблон замены элементов BR на перенос строки

<xsl:template match="BR">

 <xsl:text>&#xA;</xsl:text>

</xsl:template>

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

Для этой цели мы можем воспользоваться функциями

substring-before
и
substring-after
. Функция
substring-before($str, $search-for)
возвратит часть строки
str
, которая предшествует первому вхождению в нее подстроки
search-for
, а функция
substring-after($str, $search-for)
— последующую часть. То есть заменить первое вхождение можно шаблоном вида

<!-- ...
– ->

<xsl:value-of select = "substring-before($str, $search-for)"/>

Поделиться с друзьями: