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

    </I>

   </xsclass="underline" when>

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

    <U>

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

    </U>

   </xsclass="underline" when>

   <xsclass="underline" otherwise>

   <PRE>

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

   </PRE>

  </xsclass="underline" otherwise>

 </xsclass="underline" choose>

</xsclass="underline" template>

</xsclass="underline" stylesheet>

Вот результирующий документ:

<HTML>

 <HEAD>

  <TITLE>

   Planets

  </TITLE>

 </HEAD>

 <BODY>

  <B>Mercury</B>

  <I>Venus</I>

  <U>Earth</U>

 </BODY>

</HTML>

Как вы видели, при помощи <xsclass="underline" if> можно проверять единственное условие, а при помощи <xsclass="underline" choose> — несколько; аналогичные конструкции присутствуют в большинстве языков программирования. Кроме подобных этим условных операторов, в большей части языков программирования существуют также операторы цикла, и в XSLT содержится нечто похожее — элемент <xsclass="underline" for-each>.

Элемент <xsclass="underline" for-each>

Элемент <xsclass="underline" for-each> позволяет применять тело шаблона в цикле снова и снова для всех элементов набора узлов. С технической точки зрения, он работает с набором узлов, который возвращает выражение XPath и выполняет одно и то же действие с каждым узлом в наборе. При каждом шаге цикла тело шаблона применяется к следующему узлу из набора узлов, что дает возможность легко обрабатывать несколько узлов.

<XSL:FOR-EACH> ПРОТИВ <XSL:APPLY-TEMPLATES>

Вы могли заметить, что это описание практически такое же, как и у элемента <xsclass="underline" apply-templates>, и я сравню элементы <xsclass="underline" for-each> и <xsclass="underline" apply-templates> через несколько страниц.

У элемента <xsclass="underline" for-each> один атрибут:

• select (обязательный). Принимает значение выражения XPath, возвращающее набор узлов, который нужно обработать в цикле.

Элемент может содержать ноль или более элементов <xsclass="underline" sort>, за которыми следует тело шаблона. Работу с элементом <xsclass="underline" sort> мы изучим позже в этой главе.

В теле шаблона функция position возвращает позицию текущего узла в наборе узлов, a last возвращает число узлов в наборе. Если <xsclass="underline" sort> не используется, узлы обрабатываются в порядке документа (в порядке, в котором они перечислены в документе); если же используется элемент <xsclass="underline" sort>, набор узлов будет сначала отсортирован в порядке, заданном этим элементом.

Предположим, нам нужно отформатировать все названия планет, заключив их в элементы HTML <Р>, — это можно сделать следующим образом:

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

 <Р>

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

 </P>

</xsclass="underline" template>

Но что делать, если у некоторых планет по два названия, как, например:

<PLANET>

 <NAME>Mercury</NAME>

 <NAME>Closest planet to the sun</NAME>

 <MASS UNITS="(Earth = 1)">.0553</MASS>

 <DAY UNITS="days">58.65</DAY>

 <RADIUS UNITS="miles">1516</RADIUS>

 <DENSITY UNITS="(Earth = 1)">.983</DENSITY>

 <DISTANCE UNITS="million miles">43.4</DISTANCE><!--B перигелии-->

</PLANET>

Это проблема, поскольку атрибут select элемента <xsclass="underline" value-of> сам по себе выберет только первый элемент <NAME>. Чтобы пройти в цикле все возможные варианты, вместо него следует применить элемент <xsclass="underline" for-each> (листинг 5.7).

Листинг 5.7. Применение <xsclass="underline" for-each>

<?xml version="1.0"?>

<xsclass="underline" stylesheet version="1.0"

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

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

  <HTML>

   <xsclass="underline" apply-templates/>

  </HTML>

 </xsclass="underline" template>

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

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

   <P>

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

   </P>

  </xsclass="underline" for-each>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

Эта таблица стилей охватывает все элементы <NAME>, помещает их значения в элемент <Р> и добавляет их в выходной документ следующим образом:

<HTML>

 <P>Mercury</P>

 <P>Closest planet to the sun</P>

 <P>Venus</P>

 <P>Earth</P>

</HTML>

Вот еще один пример, впервые появившийся в главе 3, «Создание и применение шаблонов», где при помощи элемента <xsclass="underline" for-each> в цикле перебирались все атрибуты элемента:

<?xml version="1.0"?>

<xsclass="underline" stylesheet version="1.0"

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

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

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

  <xsclass="underline" copy>

   <xsclass="underline" for-each select="@*">

    <xsclass="underline" copy/>

   </xsclass="underline" for-each>

   <xsclass="underline" apply-templates/>

  </xsclass="underline" copy>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

Следующий пример появился в главе 2, «Создание и применение таблиц стилей». Это упрощенная таблица стилей, в которой нельзя использовать какие-либо элементы высокого уровня, то есть нельзя использовать <xsclass="underline" template> или <xsclass="underline" apply-templates>, однако можно пройти по узлам в цикле при помощи <xsclass="underline" for-each>:

<HTML xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xsclass="underline" version="1.0">

 <HEAD>

  <TITLE>

   The Planets Table

  </TITLE>