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

<?xml version="1.0" encoding="utf-8"?>

<Mercury>

 <SIBLINGPLANET>

  Venus

 </SIBLINGPLANET>

 <SIBLINGPLANET>

  Earth

 </SIBLINGPLANET>

</Mercury>

<Venus>

 <SIBLINGPLANET>

  Mercury

 </SIBLINGPLANET>

 <SIBLINGPLANET>

  Earth

 </SIBLINGPLANET>

</Venus>

<Earth>

 <SIBLINGPLANET>

  Mercury

 </SIBLINGPLANET>

 <SIBLINGPLANET>

  Venus

 </SIBLINGPLANET>

</Earth>

Для примера я поочередно выбираю каждый элемент <PLANET> и прохожу в цикле <xsclass="underline" for-each> по всем планетам, создавая элементы <SIBLINGPLANET> для всех планет, не являющихся контекстным узлом. Однако откуда мне известно внутри элемента <xsclass="underline" for-each>, какая из планет является контекстным узлом, выбранным шаблоном? Внутри элемента <xsclass="underline" for-each> «.» ссылается на текущий узел, с которым работает <xsclass="underline" for-each>, но не на контекстный узел шаблона. Проблему можно решить, если сохранить контекстный узел в переменной, которую я назвал contextnode:

<?xml version="1.0"?>

<xsclass="underline" stylesheet version="1.1"

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

 <xsclass="underline" output method="xml"/>

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

  <xsclass="underline" for-each select="PLANET">

   <xsclass="underline" element name="{NAME}">

    <xsclass="underline" variable name="contextnode" select="."/>

    .

    .

    .

Теперь для проверки в цикле <xsclass="underline" for-each> того, что текущий элемент не является контекстным узлом, я могу обратиться к контекстному узлу шаблона как $contextnode (листинг 9.2).

Листинг 9.2. Хранение в переменной информации, зависимой от контекста

<?xml version="1.0"?>

<xsclass="underline" stylesheet version="1.1"

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

<xsclass="underline" output method="xml"/>

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

  <xsclass="underline" for-each select="PLANET">

   <xsclass="underline" element name="{NAME}">

    <xsclass="underline" variable name="contextnode" select="."/>

    <xsclass="underline" for-each select="//PLANET">

     <xsclass="underline" if test=". != $contextnode">

      <xsclass="underline" element name="SIBLINGPLANET">

       <xsclass="underline" value-of select="NAME"/>

      </xsclass="underline" element>

     </xsclass="underline" if>

    </xsclass="underline" for-each>

   </xsclass="underline" element>

  </xsclass="underline" for-each>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

Теперь наша проблема решена.

Если у элемента <xsclass="underline" variable> есть тело, он создает переменную, чье значение является фрагментом результирующего дерева. В следующем примере при помощи фрагмента результирующего дерева я задаю значение по умолчанию для атрибута COLOR (цвет), если значение для него уже не задано. Значение по умолчанию я устанавливаю в «blue» (голубой):

<xsclass="underline" variable name="COLOR">

 <xsclass="underline" choose>

  <xsclass="underline" when test="@COLOR">

   <xsclass="underline" value-of select="@COLOR"/>

  </xsclass="underline" when>

  <xsclass="underline" otherwise>blue</xsclass="underline" otherwise>

 </xsclass="underline" choose>

</xsclass="underline" variable>

Строковое значение фрагмента результирующего дерева (то есть либо значение атрибута COLOR, либо значение по умолчанию, «blue») присваивается переменной COLOR. Теперь в выражениях XPath можно обращаться к значению этой переменной, $COLOR, а не к значению атрибута (@COLOR, гарантированно получая при этом значение цвета, даже если у соответствующего элемента отсутствует атрибут COLOR.

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

<?xml version="1.0"?>

<xsclass="underline" stylesheet version="1.1"

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

 <xsclass="underline" output method="html"/>

 <xsclass="underline" variable name="START_HTML">

  <HEAD>

   <TITLE>

    My page

   </TITLE>

  </HEAD>

 </xsclass="underline" variable>

 .

 .

 .

Теперь я могу использовать этот элемент буквального результата где угодно:

<?xml version="1.0"?>

<xsclass="underline" stylesheet version="1.1"

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

 <xsclass="underline" output method="html"/>

 <xsclass="underline" variable name="START_HTML">

  <HEAD>

   <TITLE>

    My page

   </TITLE>

  </HEAD>

 </xsclass="underline" variable>

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

  <HTML>

   <xsclass="underline" copy-of select="$START HTML"/>

   <BODY>

    <H1>Welcome to my page</H1>

   </BODY>

  </HTML>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

И вот результат:

<HTML>

 <HEAD>

  <TITLE>

   My page

  </TITLE>

 </HEAD>

 <BODY>

  <H1>Welcome to my page</H1>

 </BODY>

</HTML>

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