О рассылке |
Сайт рассылки: http://www.frnet.narod.ru/. На нем вы найдете все выпуски рассылки, а также полезную информацию по web-дизайну и web-программированию. |
Выпуск №5: Группировки в XSLT |
Исаак Тынгылчав Типовая задача XSLT- группировка элементов по одному из параметров. Например, есть список сотрудников с указанием подразделений, в которых они работают.
<items>
<item dep="отдел 301">Иванов И.И.</item> <item dep="отдел 302">Петрова П.П.</item> <item dep="АХО">Тынгылчав И.И.</item> <item dep="ВОХР">Рабинович П.Е.</item> <item dep="отдел 301">Вышку Н.Н.</item> <item dep="ВОХР">Штырц-Кобер С.С.</item> <item dep="АХО">Хидияттулин Г.Г.</item> <item dep="отдел 302">Непийпиво С.С.</item> <item dep="ВОХР">Говорухо-Отрок С.П.</item> </items> Необходимо сгруппировать всех сотрудников по подразделениям в следующем виде:
<h1>отдел 301</h1>
<ul> <li>Иванов И.И.</li> <li>Вышку Н.Н.</li> </ul> <h1>отдел 302</h1> <ul> <li>Петрова П.П.</li> <li>Непийпиво С.С.</li> </ul> Ниже рассмотрим вариант решения задачи:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output indent="yes" /> <xsl:template match="*"> <-- ПЕРВЫЙ ЦИКЛ - отбор подразделений -- > <xsl:for-each select="item[not(@dep=preceding-sibling::item/@dep)]" > <xsl:variable name="dep" select="@dep" /> <h1> <xsl:value-of select="$dep"/> </h1> <ul> <-- ВТОРОЙ ЦИКЛ - отбор сотрудников -- > <xsl:for-each select="../item[@dep = $dep]"> <li> <xsl:value-of select="."/> </li> </xsl:for-each> <-- ВТОРОЙ ЦИКЛ - отбор сотрудников -- > </ul> </xsl:for-each> <-- / ПЕРВЫЙ ЦИКЛ - отбор подразделений -- > </xsl:template> </xsl:stylesheet> Пример лаконичен и прост для понимания тех, кто привык к обычным языкам программирования. Первый цикл (см. комментарии в листинге) формирует список отделов из общего списка сотрудников. Если бы у каждого сотрудника был параметр, указывающий на должность, можно было бы отобрать по этому параметру начальников, а по параметру @dep отобрать название подразделений. Но такого параметра нет. Поэтому для составления списка отделов используется фильтр, отбирающий предшествующих в списке соседей (ось preceding-sibling): item[not(@dep=preceding-sibling::item/@dep)] Этот фильтр определяет тех сотрудников, для которых нет предшествующих в списке (preceding-sibling::item) коллег из такого же отдела, т.е. не выполняется условие: @dep=preceding-sibling::item/@dep. Вложенный цикл xsl:for-each повторно проходит по всему списку сотрудников, и выводит только тех сотрудников, которые принадлежат отделу отобранному в первом цикле. |
Архив |
Архив рассылок сайта: http://www.frnet.narod.ru/subscribe.html. Спасибо за внимание. С уважением, Алексей Голубев. |