Potřebujete pomoci s XSLT?
Nabízím školení, konzultace, vývoj XSLT kódu na zakázku. Nevájte a kontaktujte mne.

Podpořte provoz stránek
Platba probíhá pomocí služby PayPal a je možné platit kartou nebo převodem z vašeho PayPal účtu.

6.2 Seskupování

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.

Poznámka

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:

Č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“).

© Jiří Kosek 2014

Tento dokument je určen výhradně pro osobní potřebu seznámení s jazykem XSLT. Jakékoliv jiné použití, včetně dalšího šíření, pořizování kopií, použití při školeních a výuce apod. je výslovně zakázáno a bude považováno za porušení autorských práv.


Copyright © 2000-2014 Jiří Kosek