Выбрать главу

</xsclass="underline" stylesheet>                </xsclass="underline" stylesheet>

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

□ Имена двух глобальных переменных могут совпадать в том и только том случае, когда они имеют разный порядок импорта. Например, если переменные с одинаковыми именами определены в разных преобразованиях, одно из них может быть импортировано. В этом случае переменная будет иметь значение, которое задано элементом xsclass="underline" variable со старшим порядком импорта.

□ Допускается совпадение имен локальной и глобальной переменных — в этом случае в области видимости локальной переменной будет использоваться локальное значение, в области видимости глобальной (но не локальной) — глобальное значение. Иными словами, локальные переменные "закрывают" значения глобальных.

□ Две локальные переменные могут иметь совпадающие имена в том и только том случае, если их области видимости не пересекаются.

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

Пример

Предположим, что в следующем преобразовании в шаблоне с именем choice мы генерируем два элемента input.

Листинг 5.24. Преобразование en.xsl

<xsclass="underline" stylesheet

 version="1.0"

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsclass="underline" variable name="submit" select="'Submit'"/>

 <xsclass="underline" variable name="reset" select="'Reset'"/>

 <xsclass="underline" template name="choice">

  <input type="button" value="{$submit}"/>

  <xsclass="underline" text>&#xA;</xsclass="underline" text>

  <input type="reset" value="{$reset}"/>

 </xsclass="underline" template>

 <xsclass="underline" template match="/">

  <xsclass="underline" call-template name="choice"/>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

Результатом этого преобразования будет следующий фрагмент:

<input type="button" value="Submit"/>

<input type="reset" value="Reset"/>

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

Листинг 5.25. Преобразование de.xsl

<xsclass="underline" stylesheet

 version="1.0"

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsclass="underline" import href="en.xsl"/>

 <xsclass="underline" variable name="submit" select="'Senden'"/>

 <xsclass="underline" variable name="reset" select="'Loeschen'"/>

</xsclass="underline" stylesheet>

будет тот же фрагмент, но уже на немецком языке:

<input type="button" value="Senden"/>

<input type="reset" value="Loeschen"/>

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

<xsclass="underline" variable name="app:href" select="..."/>

<xsclass="underline" variable name="db:href" select="..."/>

В том случае, если префиксы app и db (которые, конечно же, должны быть объявлены) будут указывать на разные пространства имен, никакого конфликта между этими двумя переменными не будет.

Возвращаясь к теме совпадений имен переменных, продемонстрируем "скрытие" локальной переменной значения глобальной:

<xsclass="underline" stylesheet

 version="1.0"

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsclass="underline" variable name="i" select="1"/>

 <xsclass="underline" template match="/">

  <xsclass="underline" text>i equals </xsclass="underline" text>

  <xsclass="underline" value-of select="$i"/>

  <xsclass="underline" text>&#xA;</xsclass="underline" text>

  <xsclass="underline" variable name="i" select="$i + 1"/>

  <xsclass="underline" text>i equals </xsclass="underline" text>

  <xsclass="underline" value-of select="$i"/>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

Результатом выполнения этого шаблона будет:

i equals 1

i equals 2

Как можно видеть, объявление локальной переменной i "скрыло" значение глобальной переменной i. Более того, это преобразование любопытно еще и тем, что локальная переменная объявляется через глобальную — такое тоже допускается.

Рассмотрим теперь случай двух локальных переменных. Попробуем объявить две локальные переменные — одну за другой в следующем шаблоне:

<xsclass="underline" stylesheet

 version="1.0"

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsclass="underline" template match="/">

  <xsclass="underline" variable name="i" select="1"/>

  <xsclass="underline" text>i equals </xsclass="underline" text>

  <xsclass="underline" value-of select="$i"/>

  <xsclass="underline" text>&#xA;</xsclass="underline" text>

  <xsclass="underline" variable name="i" select="2"/>

  <xsclass="underline" text>i equals </xsclass="underline" text>

  <xsclass="underline" value-of select="$i"/>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

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

Failed to compile style sheet

At xsclass="underline" variable on line 9 of file stylesheet.xsclass="underline"

Variable is already declared in this template

Приведем теперь другое преобразование, в котором элементы xsclass="underline" variable принадлежат двум братским элементам:

<xsclass="underline" stylesheet

 version="1.0"

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsclass="underline" template match="/">

  <p>

   <xsclass="underline" variable name="i" select="1"/>

   <xsclass="underline" text>i equals </xsclass="underline" text>

   <xsclass="underline" value-of select="$i"/>

  </p>

  <p>

   <xsclass="underline" variable name="i" select="2"/>

   <xsclass="underline" text>i equals </xsclass="underline" text>

   <xsclass="underline" value-of select="$i"/>

  </p>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

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