Pro seskupování nám XSLT nenabízí přímou podporu.
Pokud však do sebe vhodně zanoříme dva cykly <xsl:for-each>
, můžeme požadovaného
výsledku dosáhnout.
Některé procesory již dnes nabízejí rozšiřující funkce, které
nám umožňují se s tímto problémem snadněji vypořádat. XSLT 2.0 pak
přináší zcela novou instrukci <xsl:for-each-group>
,
která je velmi mocná.
Dejme tomu, že chceme seřadit citáty opět podle autorů, ale chceme jméno autora vypsat vždy jen jednou. Můžeme k tomu použít zhruba následující postup:
projdeme všechny citáty;
u každého citátu zjistíme, zda se nejedná o první výskyt citátu daného autora, pokud ano zpracujeme všechna autory stejného jména
Člověk nemusí být zrovna Sherlock Holmes, aby odhalil, že tento přístup je poměrně pomalý – má přibližně kvadratickou časovou složitost.
Příklad 6.3. Seskupení citátů podle autorů – citaty-podle-autoru2.xsl
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes" method="html" encoding="utf-8"/> <xsl:template match="citaty"> <html> <head> <title>Citáty podle autorů</title> </head> <body> <xsl:for-each select="//citat"> <xsl:sort select="autor"/> <xsl:variable name="autor" select="autor"/> <xsl:if test="not(preceding-sibling::citat[autor=$autor])"> <h1><xsl:value-of select="$autor"/></h1> <xsl:for-each select="//citat[autor=$autor]"> <xsl:sort select="text"/> <p> <xsl:value-of select="text"/> </p> </xsl:for-each> </xsl:if> </xsl:for-each> </body> </html> </xsl:template> </xsl:stylesheet>
V praxi se většinou podmínka pro unikátní výběr uzlu přidává do predikátu, a dostaneme tak o něco kratší kód.
Příklad 6.4. Seskupení citátů podle autorů – citaty-podle-autoru8.xsl
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes" method="html" encoding="utf-8"/> <xsl:template match="citaty"> <html> <head> <title>Citáty podle autorů</title> </head> <body> <xsl:for-each select="//citat[not(preceding-sibling::citat/autor = autor)]"> <xsl:sort select="autor"/> <h1><xsl:value-of select="autor"/></h1> <xsl:for-each select="//citat[autor=current()/autor]"> <xsl:sort select="text"/> <p> <xsl:value-of select="text"/> </p> </xsl:for-each> </xsl:for-each> </body> </html> </xsl:template> </xsl:stylesheet>
Příklad 6.5. Seskupení citátů podle autorů trošku jinak – citaty-podle-autoru.xsl
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes" method="html" encoding="utf-8"/> <xsl:template match="/citaty"> <html> <head> <title>Citáty podle autorů</title> </head> <body> <xsl:for-each select="citat/autor"> <xsl:sort select="."/> <xsl:if test="count(preceding::citat[autor=current()]) = 0"> <h1><xsl:value-of select="."/></h1> <xsl:for-each select="//citat[autor=current()]"> <xsl:sort select="text"/> <p> <xsl:value-of select="text"/> </p> </xsl:for-each> </xsl:if> </xsl:for-each> </body> </html> </xsl:template> </xsl:stylesheet>
Mnohem efektivnější metoda pro seskupování je založena na použití klíčů (viz 8.1 – „Využití klíčů pro seskupování dat“).