Kompletní průvodce XSLT – šablony

11. května 2004

V tomto článku se nejdříve podíváme na strukturu XSLT stylu a hned se vrhneme na zřejmě nejdůležitější prvek jazyka XSLT, kterým jsou šablony (templates). Zjistíme, k čemu jsou dobré, jak je psát, a pak si ukážeme vytváření strukturovaného dokumentu vzájemným provázáním několika šablon.

Jak psát XSLT styl

Jak již bylo řečeno v předchozím článku, XSLT styl je opět postaven na značkovacím jazyce XML. Jedná se tedy o čistý text a k jeho psaní lze použít jakýkoli textový editor, stejně jako u většiny jiných jazyků. Lepší ale bude využít některého chytřejšího editoru, nejen kvůli zvýrazňování syntaxe, ale i kvůli jiným funkcím, jako je například automatické doplňování koncových značek. Programátoři jsou obvykle na podobné vymoženosti zvyklí, takže si jistě vhodný editor pořídí. Existují dokonce vizuální návrháře, díky kterým je pak ruční psaní kódu omezeno na minimum.

XSLT styl obsahuje data, která se využívají při sestavování cílového dokumentu, což mohou být XML elementy, texty a jiné, a hlavně řídící příkazy pro XSL procesor. Tyto příkazy náleží jmennému prostoru http://www.w3.org/1999/XSL/Transform, podle kterého XSLT procesor pozná, že element má zpracovat. Proto si pro tento jmenný prostor deklarujeme prefix xsl a budeme jej používat pro všechny XSLT elementy. Kořenovým elementem je xsl:stylesheet, do něj uvedeme deklaraci jmenného prostoru. Můžeme uvést také verzi XSLT, kterou styl využívá.

<?xml version=’1.0′?>
<xsl:stylesheet
  xmlns:xsl=’http://www.w3.org/1999/XSL/Transform‘
  version=’1.0′>
  <!– definice stylu –>
</xsl:stylesheet>

Šablony (templates)

Základním prvkem XSL transformace jsou šablony. Jak se s nimi tedy pracuje? Velice jednoduše. Prostě vybereme XPath výrazem nějaký element ze zdrojového dokumentu a nahradíme jej šablonou. Zápis se prování takto:

<xsl:template match=’výraz‘>
  <!– obsah šablony –>
</xsl:template>

Do atributu samp zapisujeme výraz, kterým budou v dokumentu nalezeny XML uzly k nahrazení. Nahrazují se samozřejmě obsahem šablony. V ukázce z předchozího článku byl jako vyhledávací XPath výraz použit a, tedy všechny elementy s názvem a. Pokud bychom nechtěli v dokumentu pouze upravovat vybrané elementy, ale rádi bychom změnili nebo nahradili celou jeho strukturu, bude nejlepším řešením zapsat výraz / (lomítko). Tím vlastně dojde k výběru celého dokumentu, přesněji řečeno jeho kořenového elementu.

Vkládání dat

Pokud vstupní data pouze nahradíme jinými, která jsme si původně zadali, asi nám to nebude stačit. Proto můžeme na vybraná místa do šablony opět vložit nějaká data z původního dokumentu. Budeme je vybírat opět XPath výrazem, přičemž výchozím bodem bude element, který byl nahrazen šablonou. K tomu slouží příkaz value-of, do jehož atributu select zapíšeme výraz k vyhledání dat ke vložení. V příkladu v předchozím článku jsme tímto příkazem do šablony vložili hodnotu atributu href odkazu pomocí XPath výrazu @href, a textový obsah odkazu výrazem . (tečka). Vkládání dat ze vstupního dokumentu je mnohem mocnější než tato jediná instrukce, tím se však budu zabývat až v některém dalším článku.

Popis práce XSL procesoru

Procesor prochází celý strom všech uzlů vstupního dokumentu a pro každý uzel hledá šablonu ke zpracování tohoto uzlu. Pokud není žádná šablona nalezena, použije se interní šablona procesoru, která obsahuje zkopírování uzlu do výstupního dokumentu a spustí zpracování podřízených uzlů. Takto vlastně dochází rekurzivně k onomu hierarchickému zpracování. Pokud ale definujete vlastní šablony, v podstatě převezmete nad danými uzly řízení a můžete je zpracovat jak se vám zlíbí. V případě, kdy nějakému uzlu odpovídá více šablon, je vybrána šablona s nejvyšší prioritou, což je obyčejné desetinné číslo. Ta je ovlivněna buď vaším vlastním nastavením, k čemuž slouží atribut priority instrukce xsl:template, nebo je vypočítaná vlastní logikou procesoru – ten šablonám přiřazuje hodnoty od -0,5 do +0,5. Přitom jsou upřednostňovány šablony s přesnější specifikací.

Vnořené zpracování šablon

Uvnitř šablony můžeme explicitně nařídit procesoru, že pro další zpracování vstupních dat chceme opět ponechat na něm, ať v dané větvi vstupních dat nadále pokračuje hledáním šablon. K tomu slouží instrukce xsl:apply-templates. Nepovinný atribut select nám umožňuje opět XPath výrazem specifikovat větev dokumentu ke zpracování. Můžeme dokonce uniknout někam o úroveň výše a třeba vyvolat nekonečnou rekurzi, která pravděpodobně skončí přetečením zásobníku procesoru. Taková šablona může vypadat nějak takto:

<xsl:template match=’*‘>
  <xsl:apply-templates select=“/“ />
</xsl:template>

Jistě budete souhlasit, že to není zvlášť přínosné využití volání šablon. Pojďme si tedy ukázat něco praktičtějšího. Ve zdrojovém dokumentu obvykle používáme svou vlastní sadu názvů elementů, kterou pak potřebujeme nahradit při exportu do HTML. Ukažme si jednoduchý příklad s využitím vnořených šablon.

Zdrojový dokument obsahuje jednu sekci katalogu. Ta je strukturována ve dvou vnořených úrovních – obsahuje jednotlivé položky a každá může obsahovat různé varianty. S tímto dokumentem budeme pracovat také v dalších přkladech, budeme obměňovat pouze transformační stylový předpis.

<katalog sekce=“Periferie“>
  <polozka nazev=“Klávesnice“>
    <varianta barva=“bílá“ />
    <varianta barva=“šedá“ />
    <varianta barva=“černá“ />
  </polozka>
  <polozka nazev=“Myš“>
    <varianta typ=“optická“ />
    <varianta typ=“kuličková“ />
  </polozka>
</katalog>

Na první pohled to tak nevypadá, ale je tu docela dost názvů XML uzlů ke zpracování. Spočítejme si je: katalog, sekce, polozka, nazev, varianta, barva a typ. Naším úkolem je připravit XSLT styl, který všechny tyto druhy uzlů správně zpracuje a vytvoří z nich HTML výstup.

<xsl:stylesheet
  xmlns:xsl=’http://www.w3.org/1999/XSL/Transform‘
  version=’1.0′>
  <xsl:template match=’/katalog‘>
    <html>
    <head>
      <title><xsl:value-of select=“@sekce“ /></title>
    </head>
    <body>
      <xsl:apply-templates select=“polozka“ />
    </body>
    </html>
  </xsl:template>
  <xsl:template match=’polozka‘>
    <h3><xsl:value-of select=“@nazev“ /></h3>
    <ul>
      <xsl:apply-templates select=“varianta/@barva“ />
      <xsl:apply-templates select=“varianta/@typ“ />
    </ul>
  </xsl:template>
  <xsl:template match=’@barva | @typ‘>
    <li><xsl:value-of select=“.“ /></li>
  </xsl:template>
</xsl:stylesheet>

Jak vidíte, jsou zde definovány celkem tři šablony. Každá slouží ke zpracování určité úrovně XML dokumentu. Poslední šablona je volána pro dva druhy uzlů. Tomu odpovídá jak dvojí volání xsl:apply-templates, tak příslušný atribut match dané šablony. Pokud máte vhodný prohlížeč, můžete si ukázku ihned vyzkoušet nebo si alespoň stáhnout archiv všech ukázek.

Teď už vidíme skutečný potenciál XSLT. Protože tvorba dynamických stránek je z velké většiny pouze transformace dat z jedné fotmy do jiné (například z SQL databáze do HTML), proč bychom si neměli tuto práci co nejvíce zjednodušit a zpříjemnit? Tato ukázka je snadno pochopitelná i pro laika. Jednotlivé úrovně jsou od sebe vzájemně odděleny podle sémantického významu. Související párové tagy jsou blízko sebe, i ty, které jsou ve výsledném dokumentu velmi vzdálené, například <html> a </html>. Je tedy poměrně snadné se v dané struktuře orientovat. Pokud bychom tyto transformace řešili dříve běžným způsobem, tedy naprogramováním iterací a slepováním HTML kódu po kouscích, bylo by to mnohem složitější, náročnější a nepřehlednější. V případě nepředpokládané chyby ve vstupním dokumentu by pravděpodobně došlo k výjimce a zpracování by bylo náročně ukončeno. V XSLT transformaci ale chyby ve vstupním dokumentu nepředstavují žádný větší problém, prostě se nenalezené části nepřenesou na výstup.

Módy šablon

Představme si situaci, kdy potřebujeme určitou část vstupního dokumentu zpracovat vícekrát, pokaždé ale jinou šablonou. To by však znamenalo vytvořit více šablon, které mají stejný parametr match. Jak ale procesoru řekneme, kdy se má použít která šablona? K tomu slouží nepovinný parametr mode. Libovolnou šablonu si můžeme označit určitým názvem módu, přičemž takto pojmenovaná šablona nebude použita, pokud nebude uveden stejný název módu také v příkazu xsl:apply-templates. Upravme si tedy předchozí příklad. Nejdříve doplníme nové volání šablony pro vstupní element polozka:

  <xsl:template match=’/katalog‘>
    …
    <body>
      <ul>
        <xsl:apply-templates
            select=“polozka“ mode=“LI“ />
      </ul>
      <hr/>
      <xsl:apply-templates select=“polozka“ />
    </body>
    …
  </xsl:template>

V tomto příkladu jsme dvakrát použili instrukci xsl:apply-templates, jednou se specifikací módu LI a podruhé bez ní. Název módu LI pro nás bude znamenat, že název každé položky katalogu bude pouze obalen do HTML elementu <li>. Nyní tedy si napíšeme šablonu, která právě tuto činnost vykonává:

  <xsl:template match=’polozka‘ mode=“LI“>
    <li><xsl:value-of select=“@nazev“ /></li>
  </xsl:template>

Nová šablona bude použita pouze v módu LI, jinak bude vyvolána šablona původní. Opět si můžete ukázku vyzkoušet.

Pojmenované šablony

Každá šablona může být pojmenována atributem name a následně může být tímto jménem vyvolána pomocí instrukce call-template. Na rozdíl od ostatních způsobů volání šablon se zde nemění kontext, tedy pozice ve vstupním dokumentu. Pokud je u pojmenované šablony uveden také atribut match, mode nebo priority, nebude na něj brán ohled. Takto si lze často používaný fragment stylesheetu přenést na jedno místo do vhodně pojmenované šablony a pak tuto šablonu volat kdekoli je třeba. Výskyt více šablon se stejným názvem je považován za chybu. Pojmenovaným šablonám se často předávají parametry, nabízí se tedy srovnání s procedurami, funkcemi nebo metodami v běžných programovacích jazycích, o tom ale až v některém dalším článku.

Jde to i bez šablon

Existuje také možnost napsat XSLT styl bez šablon, dokonce i bez značky xsl:stylesheet. XSLT procesor se bude chovat, jako by byl obsah stylu celý zapsán uvnitř šablony s atributem match="/", tedy jako šablona pracující nad celým vstupním dokumentem. Nejdříve v nejvyšším elementu stylu deklarujeme prefix jmenného prostoru xsl a nesmíme zapomenout připsat verzi XSLT. Není nic názornějšího, než ukázka:

<?xml version=“1.0″ encoding=“windows-1250″ ?>
<html
  xmlns:xsl=“http://www.w3.org/1999/XSL/Transform“
  xsl:version=“1.0″>
  <body>
    název sekce:
    <b><xsl:value-of select=“//@sekce“ /></b>
  </body>
</html>

Odkazy, zdroje

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *