Книга: Технология XSLT

Именованный шаблон как функция

Именованный шаблон как функция

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

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

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

Использование именованных шаблонов как функций обуславливается следующими тезисами.

? Именованный шаблон можно вызывать вне зависимости от того, какая часть документа обрабатывается в данный момент.

? Именованному шаблону можно передавать параметры.

? Результат выполнения именованного шаблона можно присваивать переменной.

Вызов именованного шаблона выполняется элементом xsl:call-template, в атрибуте name которого указывается имя вызываемого шаблона. Такой вызов не зависит от того, какая часть документа обрабатывается в данный момент и может производиться по необходимости.

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

<xsl:call-template name="foo">
 <xsl:with-param name="x" select="1"/>
 <xsl:with-param name="y" select="2"/>
</xsl:call-template>

которая вызывает шаблон с именем foo и передает ему параметр x со значением, равным 1 и параметр y со значением, равным 2.

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

Пример

В качестве примера приведем простой шаблон, который вычисляет квадрат переданного ему параметра x:

<xsl:template name="sqr">
 <xsl:param name="x"/>
 <xsl:value-of select="$x * $x"/>
</xsl:template>

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

<xsl:variable name="y">
 <xsl:call-template name="sqr">
  <xsl:with-param name="x" select="6"/>
 </xsl:call-template>
</xsl:variable>

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

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

выведет строку "36", переменная у содержит не число, а дерево, и 36 лишь является результатом конвертации в строку при выполнении xsl:value-of.

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

Пример

После выполнения действий

<xsl:variable name="result">
 <xsl:call-template name="sqr">
  <xsl:with-param name="x" select="6"/>
 </xsl:call-template>
</xsl:variable>
<xsl:variable name="sqr-string" select="string($result)"/>
<xsl:variable name="sqr-number" select="number($result)"/>

переменные sqr-string и sqr-number будут содержать строковое и численное значение результата вычисления соответственно.

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

Пример

В следующем преобразовании шаблон с именем less-than сравнивает значения параметров x и y. Переменной less-than присваивается булевое значение результата сравнения.

Листинг 11.7. Вычисление булевого значения функции

<xsl:stylesheet
 version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="/">
  <xsl:variable name="result">
   <xsl:call-template name="less-than">
    <xsl:with-param name="x" select="2"/>
    <xsl:with-param name="y" select="1"/>
   </xsl:call-template>
  </xsl:variable>
  <xsl:variable name="less-than" select="boolean(number($result))"/>
  <xsl:value-of select="$less-than"/>
 </xsl:template>
 <xsl:template name="less-than">
  <xsl:param name="x"/>
  <xsl:param name="y"/>
  <xsl:value-of select="number($x &lt; $y)"/>
 </xsl:template>
</xsl:stylesheet>

Пример

Простым примером шаблона-функции может быть шаблон, который форматирует дату в нужном виде, например 7 августа 93 года как "07-Aug-1993".

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

Листинг 11.8. Шаблон, форматирующий дату

<xsl:template name="format-date">
 <xsl:param name="day"/>
 <xsl:param name="month"/>
 <xsl:param name="year"/>
 <xsl:value-of select="format-number($day, '00')"/>
 <xsl:text>-</xsl:text>
 <xsl:choose>
  <xsl:when test="$month = 1">Jan</xsl:when>
  <xsl:when test="$month = 2">Feb</xsl:when>
  <xsl:when test="$month = 3">Mar</xsl:when>
  <xsl:when test="$month = 4">Apr</xsl:when>
  <xsl:when test="$month = 5">May</xsl:when>
  <xsl:when test="$month = 6">Jun</xsl:when>
  <xsl:when test="$month = 7">Jul</xsl:when>
  <xsl:when test="$month = 8">Aug</xsl:when>
  <xsl:when-test="$month = 9">Sen</xsl:when>
  <xsl:when test="$month = 10">Oct</xsl:when>
  <xsl:when test="$month = 11">Nov</xsl:when>
  <xsl:when test="$month = 12">Dec</xsl:when>
 </xsl:choose>
 <xsl:text>-</xsl:text>
 <xsl:choose>
  <xsl:when test="$year &lt;= 25">
   <xsl:value-of select="format-number($year +2000, '0000')"/>
  </xsl:when>
  <xsl:otherwise>
   <xsl:value-of select="format-number($year, '0000')"/>
  </xsl:otherwise>
 </xsl:choose>
</xsl:template>

Оглавление книги


Генерация: 1.170. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз