Kompletní průvodce XSLT – proměnné a parametry

8. července 2004

V tomto článku si probereme další prvky jazyka XSLT, které vycházejí z běžných programovacích jazyků. Jak asi víte, proměnné umožňují dočasně uchovat nějaká data a přes parametry je lze předat do jiných bloků kódu. Podívejme se, jak se s nimi pracuje v XSLT.

Proměnné

Proměnná je paměťové místo označené názvem a nesoucí nějakou hodnotu. Datový typ může být libovolný typ, který v XSLT existuje (logická hodnota, číslo, řetězec, seznam uzlů, strom výsledků). Proměnnou vytvoříme instrukcí xsl:variable, přičemž název proměnné zapíšeme (nečekaně) do atributu name a hodnotu do atributu select (který může obsahovat, jako obvykle, libovolný XPath výraz) a nebo jako tělo instrukce mezi její tagy. Ve druhém případě lze opět zapsat libovolný fragment XSLT kódu a výsledným datovým typem je takzvaný result tree (strom výsledku). Pokud není přítomna hodnota proměnné vůbec, přiřadí se prázdný řetězec ('').

Když máme proměnnou deklarovánu, můžeme ji používat ve všech XPath výrazech, kam ji zapisujeme zvoleným názvem se znakem „$“ jako prefixem. Způsob použití již vyplývá z příslušného datového typu, ukážeme si to na několika příkladech.

<?xml version=“1.0″?>
<xsl:template match=“/“>
  <!– logická hodnota (boolean) –>
  <xsl:variable name=“enabled“ select=“enabled = ‚yes'“ />
  <xsl:if test=’$enabled‘> povoleno </xsl:if>
  <!– číslo (numeric) –>
  <xsl:variable name=“numMax“ select=’number(max)‘ />
  <xsl:if test=’current/value &gt; $numMax‘>
    to je moc!
  </xsl:if>
  <!– řetězec (string) –>
  <xsl:variable name=“name“ select=“‚Pierre'“ />
  <h2><xsl:value-of select=“concat(‚Hi, ‚, $name)“ /></h2>
  <!– seznam uzlů (node-set) –>
  <xsl:variable name=“items“ select=“/items/*“ />
  <ul>
    <xsl:for-each select=“$items/*“>
      <li><xsl:apply-templates select=“.“ /></li>
    </xsl:for-each>
  </ul>
</xsl:template>

V každém pořádném jazyce mají proměnné svůj rozsah platnosti, je tak tomu i zde. Proměnná je viditelná a použitelná v aktuální větvi XSLT kódu, konkrétně ve všech následujících uzlech a ve všech jejich poduzlech. Už se ale nedostane ven při volání jiných šablon. K tomu slouží parametry. V jedné větvi nesmí existovat více proměnných pod stejným jménem.

Hodnotu proměnné můžete přiřadit pouze jednou, pak už nelze změnit. Jistě budete souhlasit, že je výraz proměnná (variable) pro tento prvek XSLT mírně zavádějící. Hodnota může být jiná nejdříve až při dalším zpracování šablony. Pokud se vám to nelíbí, uvědomte si, že se nacházíme v úplně jiném prostředí, kde nefunguje logika běžného programování. Pracovními nástroji zde nejsou příkazy, procedury a stavové proměnné, ale šablony a XPath výrazy. A věřte tomu, že si s nimi v mnohém vystačíte.

Strom výsledku

Při generování výstupu v XSLT mohou vznikat opět XML uzly, textové uzly s atributy, komentáře a podobně, zkrátka všechny prvky XML dokumentu. Pomocí proměnných můžeme výsledek šablony uschovat a dále s ním pracovat. Jaký bude mít tato proměnná datový typ? Nebude to node-set, jak je pro XML fragmenty běžné, ale takzvaný result tree, jak jej nazývá specifikace. Při práci s tímto typem ovšem narazíme na podstatnou odlišnost od node-setu – lze s ním pracovat pouze jako z celkem (například kopírovat na výstup pomocí xsl:copy-of), nelze z něj vytahovat data pomocí XPath výrazů, ani je zpracovávat dalšími šablonami.

Naštěstí v XML procesorech společnosti Microsoft existuje řešení, kterým je nadstandardní funkce node-set, která umí převést libovolný result tree zpět na node-set. Tato funkce se nachází ve speciálním jmenném prostoru, vše bude jasné z příkladu. Vstupní dokument…

<price-list>
  <variant>
    <code>UF-1</code>
    <price>399</price>
  </variant>
  <variant>
    <code>UF-1a</code>
    <price>499</price>
  </variant>
</price-list>

…a styl, který jej přetransformuje do seznamu:

<?xml version=“1.0″ encoding=“UTF-8″ ?>
<xsl:stylesheet version=“1.0″
    xmlns:xsl=“http://www.w3.org/1999/XSL/Transform“
    xmlns:msxsl=“urn:schemas-microsoft-com:xslt“
    >
  <xsl:template match=“/“>
    <xsl:variable name=“items“>
      <xsl:for-each select=“price-list/variant“>
        <item code=“{code}“>
          <xsl:value-of select=“price“/>
        </item>
      </xsl:for-each>
    </xsl:variable>
    <ul>
      <xsl:apply-templates
          select=“msxsl:node-set($items)/item“/>
    </ul>
  </xsl:template>
  <xsl:template match=’item‘>
    <li>
      <xsl:value-of select=“concat(@code, ‚: ‚, .)“/>
    </li>
  </xsl:template>
</xsl:stylesheet>

Jak vidíte, můžeme nad stejnými daty postupně provádět více transformací v jednom stylu. Výsledek první transformace se uloží do proměnné, převede na node-set a předá se ke zpracování další šabloně, která se postará o zobrazení jednotlivých položek. Proč to dělat tak složitě? Například můžeme mít připraveny nějaké šablony pro generování určitého výstupu, ale máme různé formáty vstupních dat. Můžeme tedy vstupní data přetransformovat do nějakého jednoduchého formátu, se kterým pak budou pracovat naše výstupní šablony. Celou aplikaci pak lze více vrstvit, škálovat, může být přehlednější, rozšířitelnější (a bohužel i pomalejší).

Parametry

Nyní si trochu rozšíříme své znalosti o šablonách, respektive o jejich volání. Lze přitom totiž také předávat různé parametry. Týká se to konkrétně instrukcí xsl:apply-templates a xsl:call-template. Děje se tak pomocí značek xsl:with-param, které uvedeme do těla volající instrukce. V atributu name uvedeme název parametru a hodnota je zapsána (jako obvykle) v atributu select nebo v těle této instrukce. S volajícím parametrem koresponduje vstupní parametr šablony, který je v ní popsán instrukcí param. Ta může opět obsahovat nějakou hodnotu, která bude využita, pokud tento parametr nebude předán, je to tedy výchozí (default) hodnota. Pokud není definována ani ona, použije se prázdný řetězec. Za chybu se nepovažuje ani případ, kdy je předán nějaký parametr navíc. Takový parametr by měl být ignorován.

S hodnotou parametru se pracuje stejně, jako s hodnotou proměnné. V XPath opět zapisujeme znak „$“ jako prefix. Názvy parametrů nesmí kolidovat s názvy proměnných. Následuje další jednoduchá ukázka:

<xsl:template match=’/‘>
  …
  <xsl:call-template name=“heading“>
    <xsl:with-param name=“Caption“
          select=“‚Kontaktní formulář'“ />
  </xsl:call-template>
  …
  <xsl:call-template name=“heading“ />
  …
</xsl:template>
<xsl:template name=“heading“>
  <xsl:param name=“Caption“ select=“‚—‚“ />
  <h2><xsl:value-of select=“$Caption“ /></h2>
</xsl:template>

Myslím, že příklad snad ani nepotřebuje další komentář. Pouze si všimněte, že šablona je volána dvakrát, jednou s parametrem a podruhé bez něj, přičemž při volání bez parametru bude použita výchozí hodnota tohoto parametru ("---").

Proměnné a parametry s globální platností

Proměnné ani parametry nemusí být definovány pouze uvnitř šablon, ale mohou se vyskytnout také na nejvyšší úrovni, tedy pod značkou xsl:stylesheet. Taková šablona pak je viditelná ve všech šablonách ve stylu, může v nich být však také překryta jinými proměnnými nebo parametry se stejným jménem. Globální parametr je vlastně parametr celé transformace a hodnota se předává procesoru při jejím volání. Je to další cesta, jak dostat do transformace nějaká vstupní data (mimo vstupní XML dokument).

Při inicializaci těchto výrazů je aktuálním kontextem kořen dokumentu, tedy výchozím elementem XPath výrazů je kořenový element vstupního dokumentu. Při definici mohou globální proměnné (a parametry) na sebe vzájemně odkazovat, avšak jejich vyhodnocení se nesmí dostat do bludného kruhu (circular definition).

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 *