Здравствуйте уважаемые Хабровчане. Недавно встретилась задача вывода постраничной навигации с помощью технологии XSLT. После безрезультатных поисков по интернету типовых решений, было принято решение изобрести свой велосипед.
Дано: Номер текущей страницы получаемой из GET запроса. XML файл, состоящий из корневого элемента, в котором множество вложенных однотипных элементов. Для краткости сократим файл до вот такого вида:
Файл данных nav.xml
Надо: Обеспечить постраничную навигацию. Если страница не первая выводилось назад и в начало. Если страница не последняя выводилось далее и в конец. Число элементов на странице, число страниц до и после текущей страницы можно было изменять.
После нескольких часов работы получилось следующее:
Файл преобразования nav.xsl
Получилось длинновато, но не сложно. Таблица разделена на 2 части. В первой выводиться основная HTML разметка и контент в зависимости от страницы. Во второй непосредственно сама навигация.
Шаблон постраничной навигации вызывается по имени и принимает 4 параметра. Это выводимые элементы, номер текущей страницы, количество выводимых элементов на странице и число предыдущих и следующих страниц навигации.
Теперь напишем обработчик на PHP, хотя здесь может быть и любой другой язык.
Файл обработки nav.php
Тут все просто. Подгружаем данные и таблицу стилей. Создаем процессор XSLT. Если есть номер страницы, передаем его в таблицу. Выводим результат преобразования на экран.
Дано: Номер текущей страницы получаемой из GET запроса. XML файл, состоящий из корневого элемента, в котором множество вложенных однотипных элементов. Для краткости сократим файл до вот такого вида:
Файл данных nav.xml
<?xml version="1.0" encoding="UTF-8"?> <root> <item id="1"/><item id="2"/><item id="3"/><item id="4"/><item id="5"/><item id="6"/><item id="7"/><item id="8"/><item id="9"/><item id="10"/><item id="11"/><item id="12"/><item id="13"/><item id="14"/><item id="15"/><item id="16"/><item id="17"/><item id="18"/><item id="19"/><item id="20"/><item id="21"/><item id="22"/><item id="23"/><item id="24"/><item id="25"/><item id="26"/><item id="27"/><item id="28"/><item id="29"/><item id="30"/><item id="31"/><item id="32"/><item id="33"/> </root>
Надо: Обеспечить постраничную навигацию. Если страница не первая выводилось назад и в начало. Если страница не последняя выводилось далее и в конец. Число элементов на странице, число страниц до и после текущей страницы можно было изменять.
После нескольких часов работы получилось следующее:
Файл преобразования nav.xsl
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- Настройка вывода --> <xsl:output method="html" encoding="utf-8" omit-xml-declaration="yes" indent="no" doctype-system="about:legacy-compat"/> <!-- Номер текущей страницы --> <xsl:param name="page" select="1"/> <!-- Основное преобразование --> <xsl:template match="/"> <!-- Число элементов на странице --> <xsl:variable name="pageItems" select="5"/> <!-- Вычисляем текущую страницу --> <xsl:variable name="pageCurrent"> <xsl:choose> <!-- Если текущая страница меньше одного --> <xsl:when test="number($page) < 1"> <xsl:text>1</xsl:text> </xsl:when> <!-- Если текущая страница больше общего количества --> <xsl:when test="number($page) > ceiling(count(/root/*) div $pageItems)"> <xsl:value-of select="ceiling(count(/root/*) div $pageItems)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="number($page)"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <html lang="ru"> <head> <title><xsl:value-of select="concat('Страница № ',$pageCurrent)"/></title> <!-- Немного стилей для красоты --> <style> #nav li{float:left;list-style:none;} #nav a{text-decoration:none;padding:4px;color:#333} #nav a.on, #nav a:hover{background:#bbb;} </style> </head> <body> <h1><xsl:value-of select="concat('Страница № ',$pageCurrent)"/></h1> <ul> <xsl:for-each select="/root/*[position() > ($pageCurrent * $pageItems - $pageItems) and position() <= ($pageCurrent * $pageItems)]"> <li><xsl:value-of select="@id"/></li> </xsl:for-each> </ul> <hr/> <!-- Вызываем шаблон постраничной навигации --> <xsl:call-template name="pageNav"> <xsl:with-param name="items" select="/root/*"/> <xsl:with-param name="pageCurrent" select="$page"/> <xsl:with-param name="pageItems" select="$pageItems"/> <xsl:with-param name="pageParty" select="4"/> </xsl:call-template> </body> </html> </xsl:template> <!-- Шаблон создания постраничной навигации --> <xsl:template name="pageNav"> <!-- Элементы --> <xsl:param name="items"/> <!-- Текущая страница --> <xsl:param name="pageCurrent"/> <!-- Число элементов на странице --> <xsl:param name="pageItems"/> <!-- Число ссылок назад и вперед --> <xsl:param name="pageParty"/> <!-- Всего страниц --> <xsl:variable name="count" select="ceiling(count($items) div $pageItems)"/> <ul id="nav"> <!-- В начало и назад --> <xsl:if test="$pageCurrent > 1"> <li><a href="?page=1"><<</a></li> <li><a href="?page={$pageCurrent - 1}"><</a></li> </xsl:if> <!-- Центральные --> <xsl:for-each select="$items[(position() - 1) mod $pageItems = 0]"> <xsl:if test="($pageCurrent - $pageParty) <= position() and ($pageCurrent + $pageParty) >= position()"> <li><a href="?page={position()}"> <xsl:if test="$pageCurrent=position()"> <xsl:attribute name="class">on</xsl:attribute> </xsl:if> <xsl:value-of select="position()"/> </a></li> </xsl:if> </xsl:for-each> <!-- Следующая и в конец --> <xsl:if test="$pageCurrent < $count"> <li><a href="?page={$pageCurrent + 1}">></a> </li> <li><a href="?page={$count}">>></a></li> </xsl:if> </ul> </xsl:template> </xsl:stylesheet>
Получилось длинновато, но не сложно. Таблица разделена на 2 части. В первой выводиться основная HTML разметка и контент в зависимости от страницы. Во второй непосредственно сама навигация.
Шаблон постраничной навигации вызывается по имени и принимает 4 параметра. Это выводимые элементы, номер текущей страницы, количество выводимых элементов на странице и число предыдущих и следующих страниц навигации.
Теперь напишем обработчик на PHP, хотя здесь может быть и любой другой язык.
Файл обработки nav.php
<?php // Подготавливаем данные и таблицу стилей $data = new DOMDocument('1.0', 'UTF-8'); $data->load('nav.xml'); $view = new DOMDocument('1.0', 'UTF-8'); $view->load('nav.xsl'); // Создаем XSLT процессор $xsl = new XSLTProcessor(); // Импортируем таблицу стилей $xsl->importStyleSheet($view); // Если в запросе есть номер страницы, то передаем ее шаблону if (isset($_GET['page'])) { $xsl->setParameter('', 'page', $_GET['page']); } // Преобразовываем данные и выводим на экран echo $xsl->transformToXML($data); ?>
Тут все просто. Подгружаем данные и таблицу стилей. Создаем процессор XSLT. Если есть номер страницы, передаем его в таблицу. Выводим результат преобразования на экран.
