📜 ⬆️ ⬇️

Paged navigation in XSLT

Hello dear Habrovchane. Recently, the task of displaying page navigation using XSLT technology was met. After unsuccessful searches on the Internet of standard solutions, it was decided to invent his bicycle.

Given: Number of the current page received from the GET request. An XML file consisting of a root element in which there are many nested elements of the same type. For brevity, we will reduce the file to this form:

Data file 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> 

Necessary: ​​Provide page navigation. If the page is not the first to be displayed back and in the beginning. If the page is not the last displayed further and to the end. The number of elements on the page, the number of pages before and after the current page could be changed.
')
After several hours of work, the following happened:

Conversion file 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> 

It turned out long, but not difficult. The table is divided into 2 parts. The first one displays the main HTML markup and content depending on the page. In the second one, navigation itself.

The page navigation template is called by name and takes 4 parameters. These are output items, the current page number, the number of output items on a page, and the number of previous and next navigation pages.

Now let's write a PHP handler, although there can be any other language here.

File processing 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); ?> 

It's simple. We load the data and the style sheet. We create the XSLT processor. If there is a page number, pass it to the table. We display the result of the conversion on the screen.

Source: https://habr.com/ru/post/138740/


All Articles