.. / XSLT- примеры. Вып.2 Подсчет суммы, количества, минимум/максимум

  1. xslt-examples

Пример: есть список книг, с указанием стоимости и дополнительный параметр - тип книги.

<books>
    <book author="Багряк П."  cost="123" type="old"> Синие люди</book>
    <book author="Булгаков М."  cost="34" type="old"> Роковые яйца</book>
    <book author="Чехов А.П."  cost="23" type="old"> Чайка</book>
    <book author="Ленин В.И."  cost="344" type="old"> Апрельские тезисы</book>
    <book author="Бондарев Ю."  cost="23" type="old"> Берег</book>
    <book author="Булгаков М."  cost="34" type="old"> Собачье сердце</book>
    <book author="Донцова Д."  cost="237" type="new"> Кулинар</book>
    <book author="Булгаков М."  cost="34" type="old"> Бег</book>
    <book author="Чехов А.П."  cost="23" type="old"> Палата #6</book>
    <book author="Лесков Н."  cost="744" type="old"> Левша</book>
    <book author="Гаррисон Г."  cost="120" type="new"> Мир Родины</book>
    <book author="Ленин В.И."  cost="344" type="old"> Что делать</book>
</books>

Необходимо посчитать количество и стоимость  старых (old) и новых (new) книг, их общую стоимость, определить самую дорогую и самую дешевую из книг.

Пример.1 Cумма и количество в XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output  indent="yes"/>
    <xsl:template match="books">
        <table>
<tr> <td> Товар</td> <td> Количество</td> <td> Стоимость</td> </tr>
        <tr>
            <td> Старые книги</td>
            <td> <xsl:value-of select="count(book[@type = 'old']/@cost)"/> </td>
            <td> <xsl:value-of select="sum(book[@type = 'old']/@cost)"/> </td>
        </tr>
            <tr>
                <td> Новые книги</td>
                <td> <xsl:value-of select="count(book[@type = 'new']/@cost)"/> </td>
                <td> <xsl:value-of select="sum(book[@type = 'new']/@cost)"/> </td>
            </tr>
            <tr>
                <td> Итого</td>
                <td> <xsl:value-of select="count(book/@cost)"/> </td>
                <td> <xsl:value-of select="sum(book/@cost)"/> </td>
            </tr>            
        </table>
    </xsl:template>
 </xsl:stylesheet>

Пример нуждается в комментариях? Вроде нет. Тогда переходим ко второму примеру, который решим двумя способами:

Пример 2a. XSLT min/max по-тупому

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

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output indent="yes"/>
    <xsl:template match="books">

        <xsl:for-each select="book/@cost">
            <! -- задаем порядок сортировки по убыванию цены -->
            <xsl:sort data-type="number" order="descending"/>
            <! -- первый элемент выбранный в списке  - это максимум -->
            <xsl:if test="position()=1"> MAX:<xsl:value-of select="."/> </xsl:if>
        </xsl:for-each>
        <! -- повторение - мать учения. В принципе MAX можно
        было воткнуть в предыдущий цикл -->
        <xsl:for-each select="book/@cost">
            <xsl:sort data-type="number" />
            <xsl:if test="position()=1"> MIN:<xsl:value-of select="."/> </xsl:if>
        </xsl:for-each>
       
    </xsl:template>
</xsl:stylesheet>

Пример 2b. XSLT min/max вариант без использования for-each

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output indent="yes"/>
   
    <xsl:template match="books">
        <!--   организуем перебор книг без использования
                оператора цикла.
        -->
        <xsl:apply-templates >
            <!--   задаем направление перебора -->
            <xsl:sort data-type="number" order="descending" select="@cost "/>  
        </xsl:apply-templates>
    </xsl:template>

<xsl:template match="book">
    <!--  отлавливаем первый и последний элементы списка book -->
    <xsl:choose>
        <xsl:when test="position()  = 1">
            MIIN:<xsl:value-of select="@cost"/>
        </xsl:when>
        <xsl:when test="position()   =  last() ">
            MAX:<xsl:value-of select="@cost"/>
        </xsl:when>
    </xsl:choose>
    <!--   а остальные элементы просто игнорируем  -->
</xsl:template>

</xsl:stylesheet>

Исходные коды в директории ex1 архива xslt-examples.zip

  1. 2008-10-02
  2. xslt-examples
Go Index Test