Книга: XSLT
Элементы , и
Разделы на этой странице:
Элементы <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>
.
- 4.4. Логические элементы и синтез логических схем
- 4.7 Структурные элементы SAN
- 6.4. Рабочий лист Excel и его структурные элементы
- Вложение файлов в элементы списков
- Логические элементы
- 5.2. Основные приемы работы, элементы текстового редактора
- Правило 16. Группируйте связанные между собой элементы
- Элементы и
- Основные элементы меню Пуск
- Элементы xsl:choose, xsl:when, xsl:otherwise
- 4.3. Элементы управления MultiPage, ScrollBar, SpinButton
- Контекст и основные элементы бизнес-архитектуры