Při řešení některých úloh nás XSLT nutí zcela změnit návyky,
které máme z jiných jazyků. I tak triviální úloha jako vypsání čísel
od 1 do 100 se v XSLT může na první pohled jevit jako
netriviální. Samotné XSLT nemá klasický příkaz cyklu, můžeme jen
pomocí xsl:for-each
provést iteraci nad seznamem
uzlů. Máme-li jistotu, že ve vstupním dokumentu je alespoň 100
elementů, lze použít XPath výraz (//*)[position <=
100]
k vybrání prvních 100 elementů. Kompletní použití této
metody demonstruje následující příklad.
Příklad 11.4. Iterace pochybným způsobem – iterace1.xsl
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> Pokus o vypsání čísel od 1 do 100: <xsl:for-each select="(//*)[position()<=100]"> <xsl:value-of select="position()"/>, </xsl:for-each> </xsl:template> </xsl:stylesheet>
Problém je v tom, že pokud bude v dokumentu méně než 100
elementů, nevypíší se všechna čísla až do 100. Správné řešení
problému spočívá v použití rekurze. Vytvoříme si pojmenovanou šablonu,
která v parametrech dostane informace o počátečním a koncovém čísle,
která se mají projít. Šablona zpracuje počáteční číslo, a pokud je
menší než koncové, zavolá sebe sama rekurzivně s počátečním číslem
o jedničku zvýšeným. Toto počáteční číslo tak simuluje řídící
proměnnou v klasických cyklech for
, které známe
z konvenčních jazyků.
Příklad 11.5. Iterace správným způsobem – iterace2.xsl
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> Vypsání čísel od 1 do 100: <xsl:call-template name="iteruj"> <xsl:with-param name="od" select="1"/> <xsl:with-param name="do" select="100"/> </xsl:call-template> </xsl:template> <xsl:template name="iteruj"> <xsl:param name="od"/> <xsl:param name="do"/> <xsl:value-of select="$od"/>, <xsl:if test="$od < $do"> <xsl:call-template name="iteruj"> <xsl:with-param name="od" select="$od + 1"/> <xsl:with-param name="do" select="$do"/> </xsl:call-template> </xsl:if> </xsl:template> </xsl:stylesheet>
Opět tedy využíváme metodu rozděl a panuj a problém dělíme na jednodušší podúlohy.
Jen dodejme, že v nové verzi XSLT 2.0 je řešení problému až směšně jednoduché:
<xsl:value-of select="1 to 100" separator=", "/>