=> Главная База Знаний Xslt Элементы <xsl:choose>, <xsl:when> и <xsl:otherwise>


Элементы <xsl:choose>, <xsl:when> и <xsl:otherwise>

Элементы <xsl:choose>, <xsl:when> и <xsl:otherwise>

Элемент

<xsl:choose>
похож на оператор Java
switch
, который позволяет сравнивать значение условия с несколькими возможными вариантами.

У элемента

<xsl:choose>
нет атрибутов. Он содержит один или более элементов
<xsl:when>
и (не обязательно) один элемент
<xsl:otherwise>
, который в случае применения должен стоять последним.

Вот как это работает: в элемент

<xsl:choose>
заключаются элементы
<xsl:when>
, каждый с условием
true/false
. Применяется тело шаблона в первом элементе
<xsl:when>
, чье условие имеет значение
true
, все остальные не применяются. Последним элементом внутри элемента
<xsl:choose>
может быть элемент
<xsl:otherwise>
тело шаблона внутри этого элемента применяется, если ни одно из предыдущих условий
<xsl:when>
не имело значения
true
:

<xsl:choose>

 <xsl:when test="expression1">

  <!--template-body 1-->

 </xsl:when>

 <xsl:when test="expression">

  <!-- template-body 2-->

 </xsl:when>

 <xsl:when test="expression3">

  <!--template-body 3-->

 </xsl:when>

 <xsl:otherwise>

  <!--template body 4-->

 </xsl:otherwise>

</xsl:choose>

В предыдущем разделе для осуществления этого преобразования нам потребовалось три элемента

<xsl:if>
:

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

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

 <xsl:output method="xml"/>

 <xsl:template match="PLANETS">

  <DOCUMENT>

   <TITLE>

    The Planets

   </TITLE>

   <PLANETS>

    The first three planets are: <xsl:apply-templates select="PLANET"/>

   </PLANETS>

  </DOCUMENT>

 </xsl:template>


 <xsl:template match="PLANET">

  <xsl:if test="NAME[not(text())]">

   <xsl:message terminate="yes">

    Each planet must have a name!

   </xsl:message>

  </xsl:if>

  <xsl:value-of select="NAME"/>

  <xsl:if test="position()!=last()">, </xsl:if>

  <xsl:if test="position()=last()-1>and </xsl:if>

  <xsl:if test="position()=last()">.</xsl:if>

 </xsl:template>

</xsl:stylesheet>

Теперь то же самое можно сделать при помощи единственного элемента

<xsl:choose>
:

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

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

 <xml:output method="xml"/>

 <xsl:template match="PLANETS">

  <DOCUMENT>

   <TITLE>

    The Planets

   </TITLE>

   <PLANETS>

    The first three planets are: <xsl:apply-templates select="PLANET"/>

   </PLANETS>

  </DOCUMENT>

 </xsl:template>


 <xsl:template match="PLANET">

  <xsl:if test="NAME[not(text())]">

   <xsl:message terminate="yes">

    Each planet must have a name!

   </xsl:message>

  </xsl:if>

  <xsl:value-of select="NAME"/>

  <xsl:choose>

   .

   .

   .

  </xsl:choose>

 </xsl:template>

</xsl:stylesheet>

Нам нужно проверить, в каком месте документа мы находимся, при помощи включения нескольких элементов

<xsl:when>
. У этого элемента только один атрибут:

• 

test
(обязательный). Принимает логическое (
Boolean
) значение (
true/false
) проверяемого условия.

Элемент

<xsl:when>
содержит тело шаблона.

Атрибут проверки принимает значение true/false выражения, определяющего, будет ли применяться заключенное в элементе

<xsl:when>
тело шаблона или нет. Например, вот как я добавил элементы
<xsl:when>
с соответствующими знаками пунктуации для всех планет, кроме последней:

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

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

 <xsl:output method="xml"/>

 <xsl:template match="PLANETS">

  <DOCUMENT>

   <TITLE>

    The Planets

   </TITLE>

   <PLANETS>

    The first three planets are: <xsl:apply-templates select="PLANET"/>

   </PLANETS>

  </DOCUMENT>

 </xsl:template>


 <xsl:template match="PLANET">

  <xsl:if test="NAME[not(text())]">

   <xsl:message terminate="yes">

    Each planet must have a name!

   </xsl:message>

  </xsl:if>

  <xsl:value-of select="NAME"/>

  <xsl:choose>

   <xsl:when test="position()!=last()">, </xsl:when>

   <xsl:when test="position()=last()-1">and </xsl:when>

   .

   .

   .

  </xsl:choose>

 </xsl:template>

</xsl:stylesheet>

Эти два элемента <xsl:when> выбирают все элементы

<PLANET>
за исключением последнего, поэтому элемент
<xsl:otherwise>
можно применить для последнего элемента
<PLANET>
. Тело шаблона в этом элементе будет применено, если ни в одном элементе
<xsl:when>
в элементе
<xsl:choose>
условие не примет значение
true
.

У элемента

<xsl:otherwise>
нет атрибутов, и он содержит тело шаблона. Вот как это выглядит в листинге 5.4.

Листинг 5.4. Применение <xsl:choose>

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

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

 <xsl:output method="xml"/>

 <xsl:template match="PLANETS">

  <DOCUMENT>

   <TITLE>

    The Planets

   </TITLE>

   <PLANETS>

    The first three planets are: <xsl:apply-templates select="PLANET"/>

   </PLANETS>

  </DOCUMENT>

 </xsl:template>


 <xsl:template match="PLANET">

  <xsl:if test="NAME[not(text())]">

   <xsl:message terminate="yes">

    Each planet must have a name!

   </xsl:message>

  </xsl:if>

  <xsl:value-of select="NAME"/>

  <xsl:choose>

   <xsl:when test="position()!=last()">, </xsl:when>

   <xsl:when test="position()=last()-1">and </xsl:when>

   <xsl:otherwise>.</xsl:otherwise>

  </xsl:choose>

 </xsl:template>

</xsl:stylesheet>

Вот как это работает; этот код дает тот же результат, что и код, проверяющий позицию элементов

<PLANET>
при помощи
<xsl:if>
:

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

<DOCUMENT>

 <TITLE>

  The Planets

 </TITLE>

 <PLANETS>

  The first three planets are: Mercury, Venus, and Earth.

 </PLANETS>

</DOCUMENT>

Вот еще один пример преобразования XML-XML. В этом случае я преобразую

planets.xml
в новый XML-документ, сохраняя только название каждой планеты и добавляя описание:

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

<DOCUMENT>

 <TITLE>

  The Planets

 </TITLE>

 <PLANETS>

  <PLANET>

   <NAME>Mercury</NAME>

   <DESCRIPTION>Hottest</DESCRIPTION>

  </PLANET>

  <PLANET>

   <NAME>Venus</NAME>

   <DESCRIPTION>Hot</DESCRIPTION>

  </PLANET>

  <PLANET>

   <NAME>Earth</NAME>

   <DESCRIPTION>OK</DESCRIPTION>

  </PLANET>

 </PLANETS>

</DOCUMENT>

Это преобразование можно реализовать, выбирая значение каждого элемента

<NAME>
, то есть заключенный в нем текст (заметьте, что такого рода строки в XSLT учитывают регистр) (листинг 5.5).

Листинг 5.5. Второй пример <xsl:choose>

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

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

 <xsl:output method="xml"/>

 <xsl:template match="PLANETS">

  <DOCUMENT>

   <TITLE>

    The Planets

   </TITLE>

   <PLANETS>

    <xsl:apply-templates select="PLANET"/>

   </PLANETS>

  </DOCUMENT>

 </xsl:template>


 <xsl:template match="PLANET">

  <xsl:if test="NAME[not(text())]">

   <xsl:message terminate="yes">

    Each planet must have a name!

   </xsl:message>

  </xsl:if>

  <PLANET>

   <NAME>

    <xsl:value-of select="NAME"/>

   </NAME>

   <DESCRIPTION>

    <xsl:choose>

     <xsl:when test="NAME='Mercury'">Hottest</xsl:when>

     <xsl:when test="NAME='Venus'">Hot</xsl:when>

     <xsl:when test="NAME='Earth'">OK</xsl:when>

    </xsl:choose>

   </DESCRIPTION>

  </PLANET>

 </xsl:template>

</xsl:stylesheet>

Вот и все.

Предположим теперь, что нам нужно добавить в каждый элемент

<PLANET>
атрибут
COLOR
:

<?xml version="1.0"?>

<?xml-stylesheet type="text/xml" href="/planets.xsl"?>

<PLANETS>

 <PLANET COLOR="RED">

  <NAME>Mercury</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>

 <PLANET COLOR="WHITE">

  <NAME>Venus</NAME>

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

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

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

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

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

 </PLANET>

 <PLANET COLOR="BLUE">

  <NAME>Earth</NAME>

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

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

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

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

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

 </PLANET>

</PLANETS>

Отобразить названия различных планет при помощи элемента

<xsl:choose>
, отформатированные по-разному при помощи тегов HTML
<В>
,
<I>
и
<U>
в зависимости от значения атрибута
COLOR
, можно следующим образом (листинг 5.6).

Листинг 5.6. Форматирование при помощи <xsl:choose>

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

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

 <xsl:template match="PLANETS">

  <HTML>

   <HEAD>

    <TITLE>

     Planets

    </TITLE>

   </HEAD>

   <BODY>

    <xsl:apply-templates select="PLANET"/>

   </BODY>

  </HTML>

 </xsl:template>


 <xsl:template match="PLANET">

  <xsl:choose>

   <xsl:when test="@COLOR = 'RED'">

    <В>

     <xsl:value-of select="NAME"/>

    </B>

   </xsl:when>

   <xsl:when test="@COLOR = 'WHITE'">

    <I>

     <xsl:value-of select="NAME"/>

    </I>

   </xsl:when>

   <xsl:when test="@COLOR = 'BLUE'">

    <U>

     <xsl:value-of select="NAME"/>

    </U>

   </xsl:when>

   <xsl:otherwise>

   <PRE>

    <xsl:value-of select="."/>

   </PRE>

  </xsl:otherwise>

 </xsl:choose>

</xsl:template>

</xsl:stylesheet>

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

<HTML>

 <HEAD>

  <TITLE>

   Planets

  </TITLE>

 </HEAD>

 <BODY>

  <B>Mercury</B>

  <I>Venus</I>

  <U>Earth</U>

 </BODY>

</HTML>

Как вы видели, при помощи

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