Главная » XSLT » Создание таблиц стилей, управляемых данными

0

Задача

Требует сгенерировать HTML-разметку, стилизованную в соответствии с отображаемыми данными.

Решение XSLT 1.0

Наборы атрибутов в XSLT – отличный механизм для инкапсуляции сложнос­тей, сопутствующих стилизации, которая управляется данными. Рассмотрим сле­дующий XML-документ, описывающий инвестиционный портфель:

<portfolio> <investment>

<symbol>IBM</symbol> <current>72.70</current> <paid>65.00</paid> <qty>1000</qty> </investment> <investment>

<symbol>JMAR</symbol>

<current>1.90</current> <paid>5.10</paid> <qty>5 0 0 0</qty> </investment> <investment>

<symbol>DELL</symbol> <current>24.50</current> <paid>18.00</paid> <qty>10 0000</qty> </investment> <investment>

<symbol>P</symbol> <current>57.33</current> <paid>63</paid> <qty>10 0</qty> </investment>

</portfolio>

Можно вывести этот портфель в виде таблицы, содержащей колонку, где при­быль показана черным цветом, а убытки – красным:

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

<xsl:output method="html"/>

<xsl:attribute-set name="gain-loss-font"> <xsl:attribute name="color"> <xsl:choose>

<xsl:when test="(current – paid) * qty >= 0">black</xsl:when> <xsl:otherwise>red</xsl:otherwise> </xsl:choose>

</xsl:attribute> </xsl:attribute-set>

<xsl:template match="portfolio"> <html> <head>

<title>Mой портфель</title> </head>

<body bgcolor="#FFFFFF" text="#0 0 0 0 0 0"> <h1>Портфель</h1>

<table border="1" cellpadding="2"> <tbody> <tr>

<^>Символ</^> <№>Текущая цена</th> <th>Цена на момент покупки</№> <th>Kоличество</th> <th>Прибыли/Убытки</th> </tr>

<xsl:apply-templates/> </tbody> </table> </body> </html> </xsl:template>

<xsl:template match="investment"> <tr>

<td><xsl:value-of select="symbol"/></td> <td><xsl:value-of select="current"/></td> <td><xsl:value-of select="paid"/></td> <td><xsl:value-of select="qty"/></td> <td>

<font xsl:use-attribute-sets="gain-loss-font"> <xsl:value-of

select="format-number((current – paid) * qty, ‘#,##0.00′)"/> </font> </td> </tr> </xsl:template>

</xsl:stylesheet>

Если совместимость со старыми браузерами вас не волнует, то можно сделать разметку изящнее, воспользовавшись атрибутом style вместо элемента font:

<xsl:attribute-set name="gain-loss-color">

<xsl:attribute name="style">color:<xsl:text/>

<xsl:choose>

<xsl:when test="(current – paid) * qty >= 0">black</xsl:when> <xsl:otherwise>red</xsl:otherwise> </xsl:choose> </xsl:attribute> </xsl:attribute-set>

<xsl:template match="investment">

<tr>

<td><xsl:value-of select="symbol"/></td> <td><xsl:value-of select="current"/></td> <td><xsl:value-of select="paid"/></td> <td><xsl:value-of select="qty"/></td> <td xsl:use-attribute-sets="gain-loss-color"> <xsl:value-of

select="format-number((current – paid) * qty, ‘#,##0.00′)"/>

</td> </tr> </xsl:template>

XSLT 2.0

За счет использования версии 2.0 можно, прежде всего, сократить код, приме­нив выражения XPath вместо команды xsl:choose. Например, переписать фрагмент кода следующим образом:

<xsl:attribute-set name="gain-loss-font"> <xsl:attribute name="color"

select="if ((current – paid) * qty ge 0) then ‘black’ else ‘red’"/>

</xsl:attribute-set>

Обсуждение

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

<xsl:template match="investment"> <tr>

<td><xsl:value-of select="symbol"/></td> <td><xsl:value-of select="current"/></td> <td><xsl:value-of select="paid"/></td> <td><xsl:value-of select="qty"/></td> <td> <font>

<xsl:attribute name="color"> <xsl:choose>

<xsl:when test="(current – paid) * qty >= 0">black</xsl:when> <xsl:otherwise>red</xsl:otherwise> </xsl:choose> </xsl:attribute> <xsl:value-of

select="format-number((current – paid) * qty, ‘#,##0.00′)"/> </font> </td>

</tr>

</xsl:template>

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

Можно, однако, возразить, что «зашивание» ссылок на элементы в наборы ат­рибутов не дает использовать их повторно. Обычно эту проблему можно решить, вынеся логику вычисления атрибутов из самого набора атрибутов за счет исполь­зования шаблонов с разными режимами. Рассмотрим портфель, состоящий из инвестиций, прибыльность которых вычисляется по-разному:

<portfolio>

<stock>

<symbol>IBM</symbol> <current>72.70</current> <paid>65.00</paid> <qty>1000</qty> </stock>

<stock>

<symbol>JMAR</symbol> <current>1.90</current> <paid>5.10</paid> <qty>5 0 0 0</qty> </stock>

<stock>

<symbol>DELL</symbol> <current>24.50</current> <paid>18.00</paid> <qty>10 0 0 0 0</qty> </stock>

<stock>

<symbol>P</symbol> <current>57.33</current> <paid>63.00</paid> <qty>10 0</qty> </stock>

<property>

<address>12 3 Main St. Anytown NY</address> <paid>100000</paid> <appriasal>25 0 0 0 0</appriasal> </property>

<property>

<address>13 Skunks Misery Dr. Stinksville NJ</address> <paid>200000</paid> <appriasal>5 0 0 0 0</appriasal> </property>

</portfolio>

Можно избежать определения двух наборов атрибутов, выполняющих одну и ту же функцию, вынеся логику в шаблоны:

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

<xsl:output method="html"/>

<xsl:attribute-set name="gain-loss-font"> <xsl:attribute name="color">

<xsl:apply-templates select="." mode="gain-loss-font-color"/> </xsl:attribute> </xsl:attribute-set>

<xsl:template match="stock" mode="gain-loss-font-color"> <xsl:choose>

<xsl:when test="(current – paid) * qty >= 0">black</xsl:when> <xsl:otherwise>red</xsl:otherwise> </xsl:choose>

</xsl:template>

<xsl:template match="property" mode="gain-loss-font-color"> <xsl:choose>

<xsl:when test="appriasal – paid >= 0">black</xsl:when> <xsl:otherwise>red</xsl:otherwise> </xsl:choose>

</xsl:template>

</xsl:stylesheet>

Возможно, вам не очень нравится вставлять число стилистические атрибуты – цвета, шрифты и т.п. – в XSLT-преобразование. Быть может, это вообще не ваша работа решать, как отображать прибыли и убытки; на то есть дизайнеры. В таком

случае снабдите элементы классами и перенесите решение о стилизации на уро­вень таблицы CSS-стилей:

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

<xsl:output method="html"/>

<xsl:attribute-set name="gain-loss"> <xsl:attribute name="class">

<xsl:apply-templates select="." mode="gain-loss"/> </xsl:attribute> </xsl:attribute-set>

<xsl:template match="stock" mode="gain-loss"> <xsl:choose>

<xsl:when test="(current – paid) * qty >= 0">gain</xsl:when> <xsl:otherwise>loss</xsl:otherwise> </xsl:choose>

</xsl:template>

<xsl:template match="property" mode="gain-loss"> <xsl:choose>

<xsl:when test="appriasal – paid >= 0">gain</xsl:when> <xsl:otherwise>loss</xsl:otherwise> </xsl:choose>

</xsl:template>

<xsl:template match="portfolio"> <html> <head>

<title>Mой портфель</title>

<link rel="stylesheet" type="text/css" href="portfolio.css"/>

</head>

</xsl:template>

<xsl:template match="stock"> <tr>

<td><xsl:value-of select="symbol"/></td> <td align="right"><xsl:value-of select="current"/></td> <td align="right"><xsl:value-of select="paid"/></td> <td align="right"><xsl:value-of select="qty"/></td> <td align="right" xsl:use-attribute-sets="gain-loss"> <xsl:value-of

select="format-number((current – paid) * qty, ‘#,##0.00′)"/>

</td> </tr> </xsl:template>

<xsl:template match="property"> <tr>

<td><xsl:value-of select="address"/></td> <td align="right"><xsl:value-of select="paid"/></td> <td align="right"><xsl:value-of select="appriasal"/></td> <td align="right" xsl:use-attribute-sets="gain-loss">

<xsl:value-of

select="format-number(appriasal – paid, ‘#,##0.00′)"/>

</td> </tr> </xsl:template>

</xsl:stylesheet>

Позже главный по стилизации решит, как отображать данные в ячейках <td class="gain"> и <td class= " loss " >, подготовив файлportfolio.css, как пока­зано в примере 10.1.

Пример 10.1. portfolio.css

td.gain {

color:black;

}

td.loss {

color:red; font-weight:700;

}

Мангано Сэл  XSLT. Сборник рецептов. – М.: ДМК Пресс, СПБ.: БХВ-Петербург, 2008. – 864 с.: ил.

По теме:

  • Комментарии