Ice Bear SoftNástroj pro anotaci schémat Relax NG

Obsah

1. Úvod
2. Terminologie
3. Anotujeme schéma Relax NG
  3.1. Použití transformačního stylu
  3.1.1. Použití z příkazového řádku
  3.1.2. Použití v Antu
  3.2. Elementy jmenného prostoru anotací
  3.2.1. Element <a:title>
  3.2.2. Element <a:annotation>
  3.2.3. Element <a:elem>
  3.2.4. Elementy <a:namespace> a <a:datatype>
  3.2.5. Odkazy na vzory
4. Uživatelské úpravy
  4.1. Úpravy pomocí parametrů
  4.1.1. Změna barev
  4.1.2. Přípona importovaných schémat
  4.1.3. Vytvoření odkazu na původní schéma
  4.1.4. Lokalizace
  4.2. Změna vzhledu s použitím kaskádového stylu
  4.2.1. <xsl:template match='/'>
  4.2.2. <xsl:template match='html'>
  4.2.3. <xsl:template match='pre'>
  4.2.4. <xsl:template match='*'>
  4.2.5. Doplnnění času poslední modifikace
  4.3. Zobrazení v rámech
  4.3.1. <xsl:template match='html'>
  4.3.2. <xsl:template match='*' mode='toc'>
  4.3.3. <xsl:template match='a' mode='toc'>
  4.3.4. <xsl:template match='a'>
  4.4. Dokumentace v několika HTML souborech
  4.4.1. <xsl:template match='html'>
  4.4.2. <xsl:template match='a[@name]'>
  4.4.3. <xsl:template match='a[@href]'>
5. Download

1. Úvod

První verze tohoto nástroje vznikla, když jsem pracoval na schématu Relax NG cstugbulletin.rng.html. Schéma bylo tvořeno z ničeho krok za krokem a od počátku bolo dokumentováno, protože se jednalo o veřejný projekt a schéma mělo být srozumitelné pro kohokoliv. Brzy bylo tak velké, že se nevešlo do okna mého textového editoru a bylo nutné neustálé rolování. Uvědomil jsem si, že je nezbytné mít nějaké krásné zobrazení, pokud možno hypertextové. Později jsem pracoval na jiných schématech Relax NG. Nelíbila se mi nutnost neustálého editování transformačního stylu, abych jej upravil pro konkrétní použití. Proto byl nástroj zevšeobecněn.

První verze využívala výhradně možnosti XSLT 1.0 a mohla být připojena k souboru instrukcí pro zpracování, takže bylo možno zobrazit schéma Relax NG přímo v Mozille. Později se ukázalo, že některé prohlížeče nejsou schopny korektně zobrazit národní znaky v XML souborech transformovanýcy do HTML přímo v prohlížeči. Navíc některé prohlížeče vůbec nepodporují transformaci. Transformační styl je proto určen pro zpracování v procesorech XSLT 2.0, jako je Saxon, ale stále úmyslně využívá většinou jen možnosti XSLT 1.0. Pokud chcete upravit styl pro XSLT 1.0, musíte všechny výskyty element() nahradit výrazem node() a přepsat šablony pro elementy <a:namespace><a:datatype> jednoduššími verzemi implementujícími rozumnou podmnožinu. Takto upravený transformační styl by měl fungovat.

 Začátek stránky 

2. Terminologie

V dokumentu budeme používat následující termíny:

Budeme používat prefix r: pro jmenný prostor RNG a prefix a: pro jmenný prostor anotací.

 Začátek stránky 

3. Anotujeme schéma Relax NG

Obsah

3.1. Použití transformačního stylu
  3.1.1. Použití z příkazového řádku
  3.1.2. Použití v Antu
3.2. Elementy jmenného prostoru anotací
  3.2.1. Element <a:title>
  3.2.2. Element <a:annotation>
  3.2.3. Element <a:elem>
  3.2.4. Elementy <a:namespace> a <a:datatype>
  3.2.5. Odkazy na vzory

Schéma Relax NG se skládá z elementů ve jmenném prostoru RNG. Elementy v jiných jmenných prostorech validátor ignoruje. Elementy ve jmenném prostoru anotaci budeme používat ke vložení dokumentace do schématu. Tento nástroj je překonvertuje do HTML. Typický vzhled anotovaného schématu, vytvořeného stylem rng.xsl, je na obrázku níže.

3.1. Použití transformačního stylu

Transformační styl rng.xsl byl vyvinut pro použití s procesoren Saxon 8. Bude fungovat i s jinými procesory XSLT 2.0 s výjimkou jedné funkce v elementech <a:namespace><a:datatype>.

3.1.1. Použití z příkazového řádku

Předpokládejme, že saxon8 je váš skript, který nastaví CLASSPATH pro běh procesoru Saxon a spustí Javu tak, jak je v dokumentaci tohoto procesoru popsáno. Ostatní parametry jsou předány procesoru Saxon. Volací sekvence pak je:

saxon8 options -o filename.rng.html filename.rng rng.xsl parameters

Můžete zadat libovolné volby procesoru Saxon, např. -l zapne číslování řádků. Parametry budou popsány později v kapitole Uživatelské úpravy. Pokud před parametrem uvedete vykřičník, můžete nastavit výstupní vlastnosti, např. kódování výstupu můžete změnit na ISO 8859-2 pomocí:

!encoding=iso-8859-2

3.1.2. Použití v Antu

Nejprve musíte vložit saxon8.jar do CLASSPATH a informovat Ant, že má používat Saxon 8. dosáhnete toho definováním následující systémové vlastnosti v ANT_OPTS (nevkládejte ji to ANT_ARGS, nebude to fungovat):

javax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl

Jeden dokument lze transformovat pomocí:

<xslt style="rng.xsl" in="filename.rng" out="filename.rng.html">
  <!-- nested elements -->
</xslt>

Při transformaci několika dokumentů budete potřebovat vnořený mapovač:

<xslt basedir='.'
      destdir='.'
      style='rng.xsl'
      includes='**/*.rng'>
  <mapper type='glob' from='*' to='*.html'/>
  <!-- other nested elements -->
</xslt>

Nepovinné parametry se definují ve vnořených elementech <param>. Výstupní vlastnosti se zadávají v elementech <outputproperty>. Výstupní kódování může být změněno na ISO 8859-2 pomocí:

<outputproperty name='encoding' value='iso-8859-2'/>

Volby Saxonu se zadávají v elementu <factory>, například číslování řádků lze zapnout pomocí:

<factory>
  <attribute name='http://saxon.sf.net/feature/linenumbering' value='true'/>
</factory>
 Začátek stránky 

3.2. Elementy jmenného prostoru anotací

Obsah

3.2.1. Element <a:title>
3.2.2. Element <a:annotation>
3.2.3. Element <a:elem>
3.2.4. Elementy <a:namespace> a <a:datatype>
3.2.5. Odkazy na vzory

Jmenný prostor anotací obsahuje několik speciálních elementů, jež budou popsány v následujících kapitolách. Všechny ostatní elementy ve jmenném prostoru anotací, které zde nebudou zmíněny, budou převedeny na stejnojmenné elementy HTML s kopiemi všech atributů. Je tedy snadné vložit libovolné značky HTML.

Všechny elementy jmenného prostoru anotací musí být dětmi dokumentního elementu <r:grammar>. Relax NG povoluje anotace kdekoliv, ale tento transformační styl by byl zmaten.

3.2.1. Element <a:title>

Tento element musí být prvním dítětem dokumentního elementu <r:grammar>. Vytiskne název stránky a vytvoří obsah.

3.2.2. Element <a:annotation>

Toto je hlavní element anotací. Smí obsahovat jakýkoliv text s libovolnými značkami HTML. Pokud neobsahuje žádný element <a:p>, bude celý obsah umístěn do nově vytvořeného elementu <p>, do něhož budou zkopírovány všechny atributy elementu <a:annotation>. Může to být užitečné pro atribut class.

Existuje vážný důvod pro použití elementu <a:annotation> s volitelnými elementy <a:p> uvnitř. Element <a:annotation> vytváří nadpis s návěštím, pokud je následující sourozenec <r:define> nebo <r:start>. Máte-li několik po sobě jdoucích elementů <a:annotation>, pouze poslední z nich se objeví pod nadpisem. Několik odstavců textu můžete vložit pod nadpis pouze tak, že umístíte <a:annotation> okolo elementů <a:p>. Pokud nepoužijete elementy <a:annotation>, nevytvoří se nadpisy s návěštími a hypertextový obsah nebude fungovat.

3.2.3. Element <a:elem>

Tento element usnadňuje zápis názvů elementů v anotacích, protože úhlové závorky nemusíte přepisovat pomocí &lt;&gt;. Zápisem <a:elem>r:element</a:elem> vytvoříte <r:element>.

3.2.4. Elementy <a:namespace> a <a:datatype>

Tyto elementy vypisují jmenný prostor (hodnotu atributu ns) a knihovnu datových typů pro zvolený kontext. Nabízejí tři možnosti:

  1. Hodnota atributu for není zadána: zobrazí se hodnota /r:grammar/@ns resp. /r:grammar/@datatypeLibrary.
  2. Hodnotou atributu for je tečka: Šablona najde nejbližší následující element ve jmenném prostoru RNG a zobrazí hodnotu atributu ns resp. datatypeLibrary tohoto elementu nebo hodnotu zděděnou z nejbližšího předka. Element <r:attribute> nemůže zdědit jmenný prostor.
  3. Atribut for má jinou hodnotu: je-li dostupná funkce saxon:evaluate, je hodnota považována za výraz XPath, jenž musí identifikovat jediný element. Jmenný prostor resp. knihovna datových typů se určí stejným způsobem jako v předchozím případě. Ujistěte se, že výraz vrací jediný uzel. Například //r:element[1] vrátí sekvenci uzlů (pokud nemáte velmi zvláštní schéma). Musíte použít (//r:element)[1]. Pokud není funkce saxon:evaluate dostupná, šablona vypíše Not implemented!

Tyto elementy můžete otestovat na souboru test.rng obsaženém v distribučním balíčku. Anotace obsahuje <a:namespace/>. Nahraďte jej následujícími kódy:

1.
<a:namespace for='.'/>
2.
<a:namespace for='(//r:element[@name="include"])[1]'/>

3.2.5. Odkazy na vzory

Transformační styl vytváří nadpisy s návěštími pro všechny vzory. Jméno se shoduje s hodnotou atributu name elementu <r:define>, nebo start pro element <r:start>. Chcete-li se odkázat na vzor definovaný pomocí <define name='def.article.contents'>, použijte následující kód:

<a:a title="article contents" href="#def.article.contents">link to article contents</a:a>
 Začátek stránky 

4. Uživatelské úpravy

Obsah

4.1. Úpravy pomocí parametrů
  4.1.1. Změna barev
  4.1.2. Přípona importovaných schémat
  4.1.3. Vytvoření odkazu na původní schéma
  4.1.4. Lokalizace
4.2. Změna vzhledu s použitím kaskádového stylu
  4.2.1. <xsl:template match='/'>
  4.2.2. <xsl:template match='html'>
  4.2.3. <xsl:template match='pre'>
  4.2.4. <xsl:template match='*'>
  4.2.5. Doplnnění času poslední modifikace
4.3. Zobrazení v rámech
  4.3.1. <xsl:template match='html'>
  4.3.2. <xsl:template match='*' mode='toc'>
  4.3.3. <xsl:template match='a' mode='toc'>
  4.3.4. <xsl:template match='a'>
4.4. Dokumentace v několika HTML souborech
  4.4.1. <xsl:template match='html'>
  4.4.2. <xsl:template match='a[@name]'>
  4.4.3. <xsl:template match='a[@href]'>

Jednoduchých úprav lze dosáhnout parametry zadanými při transformaci. Složitější úpravy vyžadují napsání uživatelského transformačního stylu, který bude importovat rng.xsl, a buď předefinuje šablony, nebo vezme NodeSet získaný první transformací a znovu jej zpracuje jinými šablonami. Obě metody budou popsány v následujících kapitolách.

Uživatelské transformační styly do značné míry využívají možností XSLT 2.0, jež umožňují použít výsledek zpracování šablonou jako NodeSet. Doporučuji, abyste je nepřepisovali pro použití s procesory XSLT 1.0, ačkoliv je to možné. Museli byste použít funkci node-set z EXSLT. Implementace této funkce se liší v různých procesorech. Můžete srovnat přístupy v transformačních stylech, které dělají totéž: bibliography2.xsl, jenž využívá možností XSLT 2.0, a bibliography.xsl řešící totéž pouze s využitím XSLT 1.0. Všimněte si způsobu hledání konkrétní implementace funkce node-set.

4.1. Úpravy pomocí parametrů

Parametry transformačního stylu umožňují změny základních vlastností anotovaného schématu Relax NG.

4.1.1. Změna barev

Barvy mohou být změněny pomocí parametrů, jejichž jména se shoduji s příslušnými atributy elementu <body>. Defaultní hodnoty jsou:

<xsl:param name='link'>#900000</xsl:param>
<xsl:param name='vlink'>#d30000</xsl:param>
<xsl:param name='alink'>#c14242</xsl:param>
<xsl:param name='bgcolor'>#ffffff</xsl:param>
<xsl:param name='textcolor'>#000000</xsl:param>

4.1.2. Přípona importovaných schémat

Předpokládá se, že všechny soubory budou transformovány týmž stylem do HTML. Pokud se vzor odkazuje na vložené schéma, musí styl připojit příponu příslušného HTML souboru. Přípona je určena parametrem ext. Defaultní hodnota je zřejmá:

<xsl:param name='ext'>.html</xsl:param>

4.1.3. Vytvoření odkazu na původní schéma

Můžete chtít zveřejnit na webu jak HTML zobrazení, tak původní schéma Relax NG. Je-li parametr rnghref neprázdný a nenulový, odkaz na původní soubor se vytvoří. Předpokládá se, že oba soubory budou ve stejném adresáři. Bude-li původní soubor jinde, musíte zadat prefix v parametru hrefprefix. Defaultní hodnoty jsou prázdné:

<xsl:param name='rnghref'/>
<xsl:param name='hrefprefix'/>

4.1.4. Lokalizace

Transformační styl vkládá anglické texty "Table of contents" a "The pattern is used in:". Můžete dodat XML soubor s jazykovými variantami použitím parametru rngtexts. Pokud soubor obsahuje texty v několika jazycích, vyberete požadovaný jazyk parametrem rnglang. Dokumentní element souboru s jazykovými variantami musí být <rngtexts> a musí obsahovat element <contents-name><used-in>. Oba tyto elementy mohou mít atribut lang. Je-li zadán parametr rnglang, styl vybere elementy s touž hodnotou atributu lang a elementy bez tohoto atributu. Je-li parametr rnglang vynechán, styl vybere elementy bez atributu lang. Defaultní hodnoty obou parametrů jsou prázdné.

<xsl:param name='rngtexts'/>
<xsl:param name='rnglang'/>

Distribuce obsahuje soubor rng-cs.xml s texty v českém jazyce.

<rngtexts>
  <!-- Table of contents -->
  <contents-name>Obsah</contents-name>
  <!-- The pattern is used in: -->
  <used-in>Vzor je použit v:</used-in>
</rngtexts>

Potěší mě, když mi pošlete překlady do dalších jazyků a dovolíte, abych je směl distribuovat jako součást tohoto balíčku.

 Začátek stránky 

4.2. Změna vzhledu s použitím kaskádového stylu

Obsah

4.2.1. <xsl:template match='/'>
4.2.2. <xsl:template match='html'>
4.2.3. <xsl:template match='pre'>
4.2.4. <xsl:template match='*'>
4.2.5. Doplnnění času poslední modifikace

Předpokládejme, že chceme definovat vzhled pomocí kaskádového stylu podobného tomu, jenž je používán pro zobrazení této stránky. Stránka by měla vypadat tak jako na obrázku níže.

Vyřešíme to pomocí stylu rng-css.xsl, který vezme NodeSet z importovaného stylu rng.xsl a znovu jej zpracuje:

<xsl:import href='rng.xsl'/>

Styl má navíc parametr, jímž určíme URL kaskádového stylu, jenž se má použít.

<xsl:param name='css'>rng.css</xsl:param>

4.2.1. <xsl:template match='/'>

Tato šablona pouze uloží výsledek transformace importovaným stylem a na něj aplikuje jiné šablony.

<xsl:template match='/'>
  <xsl:variable as='item()*' name='node'>
    <xsl:next-match/>
  </xsl:variable>
  <xsl:apply-templates select='$node'/>
</xsl:template>

4.2.2. <xsl:template match='html'>

Dokumentní element z importovaného stylu je <html>. Opětovně jej zpracujeme šablonou, která nejprve zkopíruje obsah elementu <head> a přidá odkaz na kaskádový styl. Pak odstraníme atributy z elementu <body> a zpracujeme jeho obsah.

<xsl:template match='html'>
  <html>
    <head>
      <xsl:apply-templates select='head/*'/>
      <link rel="STYLESHEET" href="{$css}" type="text/css"/>
    </head>
    <body>
      <xsl:apply-templates select='body/*'/>
    </body>
  </html>
</xsl:template>

4.2.3. <xsl:template match='pre'>

Element <pre> vložíme do jednobuňkové tabulky.

<xsl:template match='pre'>
  <table border="2" frame="box" rules="rows" cellpadding="5" class="pre">
    <tr><td><pre>
      <xsl:apply-templates/>
    </pre></td></tr>
  </table>
</xsl:template>

4.2.4. <xsl:template match='*'>

Zbývající elementy pouze zkopírujeme s jejich atributy. Nemůžeme však prostě předefinovat šablonu pro všechny elementy, protože by ji použil importovaný styl. Víme, že elementy HTML mají prázdné URI jmenného prostoru. Budeme jej tedy testovat a pokud je URI jmenného prostoru neprázdné, zpracujeme element šablonou importovaného stylu.

<xsl:template match='*'>
  <xsl:choose>
    <xsl:when test='not(namespace-uri(.))'>
      <xsl:copy>
        <xsl:copy-of select='@*'/>
        <xsl:apply-templates/>
      </xsl:copy>
    </xsl:when>
    <xsl:otherwise>
      <xsl:next-match/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

4.2.5. Doplnnění času poslední modifikace

Odkaz na původní soubor je zobrazen v elementu <p> bezprostředně následujícím element <h1> s hlavním nadpisem a předcházejícím element <h2> s nadpisem obsahu. Napíšeme šablonu pro právě tento element. Pro přidání data a času modifikace souboru potřebujeme rozšiřující funkci. Atribut use-when testuje dostupnost funkce zw:last-modified. Není-li funkce dostupná, šablona nebude zkompilována a element nebude modifikován.

<xsl:template match='p[name(preceding-sibling::element()[1])="h1" and
                       name(following-sibling::element()[1])="h2"]'
     xmlns:zw='java:cz.euweb.icebearsoft.saxon.ExtUtils'
     use-when='function-available("zw:last-modified")'>
  <p>Original file:
    <xsl:apply-templates/>, last modified:
    <xsl:value-of select='zw:last-modified($root)'/>
  </p>
</xsl:template>

Funkci zw:last-modified můžeme volat bez parametru, abychom získali datum a čas modifikace souboru obsahujícího kontextový uzel. Kontextový uzel v této šabloně však již nepatří původnímu dokumentu. Jeho původem je NodeSet vytvořený importovaným stylem. Pokud použijete <xsl:value-of select='zw:last-modified()'/>, získáte datum a čas modifikace importovaného stylu (vyzkoušejte). Musíme tedy použít kořenový uzel původního dokumentu uschovaný v globální proměnné transformačního stylu:

<xsl:variable name='root' select='/' />

Nezapomeňte uvést parametr rnghref=1, jinak se odkaz na původní soubor nevytvoří.

 Začátek stránky 

4.3. Zobrazení v rámech

Obsah

4.3.1. <xsl:template match='html'>
4.3.2. <xsl:template match='*' mode='toc'>
4.3.3. <xsl:template match='a' mode='toc'>
4.3.4. <xsl:template match='a'>

Tato kapitola ukáže, jak lze transformovat dokument do zobrazení v rámech, kde v levém rámu bude obsah a v pravém rámu bude celý dokument s odstraněným obsahem.

Použijeme stejný přístup jako v kapitole Změna vzhledu s použitím kaskádového stylu. V následujícím textu proto popíšeme jenom nové šablony.

Styl má další parametry definující jména souborů s obsahem rámů a šířku levého rámu.

<xsl:param name='left' select='concat(document-uri(/), "-", "left.html")'/>
<xsl:param name='right' select='concat(document-uri(/), "-", "right.html")'/>
<xsl:param name='width'>30%</xsl:param>

Pamatujte si, že se transformace zhroutí, pokud nepoužijete element <a:title>. Test korektnosti není těžký, udělejte si jej za domácí úkol.

4.3.1. <xsl:template match='html'>

Šablona pro opětovné zpracování elementu <html> musi vytvořit tři soubory. První z nich obsahuje kopii elementu <head> a definuje sadu rámů. V druhém souboru se bude nacházet obsah. První element <ul> bude zpracován v režimu toc. Poslední soubor bude obsahovat zbytek s výjimkou elementů, z nichž jsme vytvořili obsah. Pamatujte si, že importovaný styl obsahuje své vlastní šablony pro zpracování atributů. Proto je raději vkládáme pomocí <xsl:copy-of select='body/@*'/>

<xsl:template match='html'>
  <html>
    <xsl:copy-of select='head'/>
    <frameset cols='{concat($width, ",*" )}'>
      <frame name='left' src='{$left}'/>
      <frame name='right' src='{$right}'/>
    </frameset>
  </html>
  <xsl:result-document href='{$left}'>
    <html>
      <head>
        <title><xsl:value-of select='body/h2[1]'/></title>
      </head>
      <body>
        <xsl:copy-of select='body/@*'/>
        <p><b><xsl:copy-of select='body/h2[1]'/></b></p>
        <xsl:apply-templates select='body/ul[1]' mode='toc'/>
      </body>
    </html>
  </xsl:result-document>
  <xsl:result-document href='{$right}'>
    <html>
      <xsl:copy-of select='head'/>
      <body>
        <xsl:copy-of select='body/@*'/>
        <xsl:apply-templates select='body/* except (body/h2[1], body/ul[1])'/>
      </body>
    </html>
  </xsl:result-document>
</xsl:template>

4.3.2. <xsl:template match='*' mode='toc'>

Elementy zpracovávané v režimu toc budou pouze zkopírovány se svými atributy. Speciální šablonu potřebujeme pouze pro element <a>. Ukážeme si ji v následující kapitole.

<xsl:template match='*' mode='toc'>
  <xsl:copy>
    <xsl:copy-of select='@*'/>
    <xsl:apply-templates mode='toc'/>
  </xsl:copy>
</xsl:template>

4.3.3. <xsl:template match='a' mode='toc'>

Režim toc se používá při zpracování obsahu v levém rámu. Odkazy je proto nutno upravit tak, aby obsahovaly správný cíl. Je též nutné přidat jméno souboru zobrazeného v pravém rámu.

<xsl:template match='a' mode='toc'>
  <a>
    <xsl:copy-of select='@*'/>
    <xsl:attribute name='target'>right</xsl:attribute>
    <xsl:attribute name='href'>
      <xsl:value-of select='concat($right, @href)'/>
    </xsl:attribute>
    <xsl:apply-templates mode='toc'/>
  </a>
</xsl:template>

Nyní se může zdát, že element <a> obsahuje dva atributy href, což není v XML povoleno. Specifikace XSLT však říká, že v případě, kdy vytvoříte více atributů téhož jména, bude použit pouze poslední z nich. Lze tedy přepsat původní atribut href novým obsahem.

4.3.4. <xsl:template match='a'>

Elementy <a> v pravém rámu také vyžadují zvláštní zpracování. V témže okně by měly být zobrazeny pouze lokální odkazy. Pokud se odkazujeme na jiný soubor, měli bychom jej zobrazit v okně, jež nahradí celou sadu rámů.

<xsl:template match='a'>
  <a>
    <xsl:copy-of select='@*'/>
    <xsl:attribute name='target'>
      <xsl:value-of
           select='if (starts-with(@href, "#")) then "_self" else "_top"'/>
    </xsl:attribute>
    <xsl:apply-templates/>
  </a>
</xsl:template>
 Začátek stránky 

4.4. Dokumentace v několika HTML souborech

Obsah

4.4.1. <xsl:template match='html'>
4.4.2. <xsl:template match='a[@name]'>
4.4.3. <xsl:template match='a[@href]'>

Styl převede dokument do sady souborů. Každý z nich bude zobrazovat v levém sloupci obsah a jeden vzor v pravém sloupci. text před prvním elementem <h2> bude vložen na úvodní stránku. Typický vzhled je ukázán níže.

Budeme opět zpracovávat výsledek získaný z importovaného stylu, jak bylo popsáno v kapitole Změna vzhledu s použitím kaskádového stylu. Podobně jako v kapitole Zobrazení v rámech se i zde transformace zhroutí, pokud bude chybět element <a:title>.

Styl požaduje dva dodatečné parametry určující jméno úvodního souboru a příponu:

<xsl:param name='main' as='xs:string' select='document-uri(/)'/>
<xsl:param name='ext'>.html</xsl:param>

Zde se objevuje potenciální problém. Úvodní dokument musí mít stejné jméno jako soubor se schématem a s přidanou příponou, jinak nebudou fungovat odkazy na vložená schémata. Defaultní hodnoty jsou ve shodě s tímto požadavkem.

4.4.1. <xsl:template match='html'>

Téměř všechny činnosti se provádějí v šabloně pro zpracování elementu <html>. Šablona je proto docela dlouhá. Rozdělíme ji na menší části (nejsou well-formed) a budeme je vysvětlovat dodatečně.

<xsl:template match='html'>
  <!-- ***** Storing information ***** -->
  <xsl:variable name='head' select='head'/>
  <xsl:variable name='tocname' select='body/h2[1]'/>
  <xsl:variable name='toc' select='body/ul[1]/*'/>
  <xsl:variable name='body-attributes' select='body/@*'/>

Na začátku šablony si uschováme následující informace:

  <!-- ***** Grouping the contents except table of contents by <h2> ***** -->
  <xsl:for-each-group select='body/* except (body/h2[1], body/ul[1])' group-starting-with='h2'>

Druhá část uvozuje smyčku přes všechny děti elementu <body> s výjimkou těch, v nichž je uložen obsah. Popis každého vzoru začíná nadpisem <h2>, proto jej použijeme jako zahajovací element supiny.

    <!-- ***** Preparing the file name ***** -->
    <xsl:variable name='fn' as='xs:string'
         select='if (name() = "h1") then $main else concat($main, "-", a/@name)'/>

Nyní musíme připravit jméno souboru. Kontextovým prvkem je první element skupiny. Uvědomte si, že dokument začíná hlavním nadpisem. Jestliže se tedy kontextový element jmenuje h1, znamená to, že právě vytváříme soubor s úvodní stránkou, jehož jméno získáme z parametru $main. Jména ostatních souborů budou odvozena z hodnoty atributu name elementu <a>, jenž je vždy dítětem elementu <h2>. Nezapomeňte, že do schématu může být vloženo jiné schéma. Pokud by jména souborů vycházela pouze ze jmen vzorů, nemusela by být jednoznačná. Vložíme tedy na začátek hlavní jméno a spojovník.

    <!-- ***** Opening the result document ***** -->
    <xsl:result-document href='{concat($fn, $ext)}'>
      <html>
        <xsl:copy-of select='$head'/>
        <body>
          <xsl:copy-of select='$body-attributes'/>
          <table cellspacing='25' width='100%'>
            <tr valign='top'>

Při otvírání souboru připojíme příponu. Zkopírujeme obsah proměnné $head a vložíme atributy do elementu <body>.

              <!-- ***** Left column with table of contents ***** -->
              <td>
                <p><b><font size='+2'>
                  <xsl:copy-of select='$tocname/*|$tocname/text()'/>
                </font></b></p>
                <ul>
                  <xsl:choose>
                    <xsl:when test='$fn = $main'>
                      <xsl:apply-templates select='$toc'/>
                    </xsl:when>
                    <xsl:otherwise>
                      <li>
                        <a href='{concat($main, $ext)}' title='Introduction'>Introduction</a>
                      </li>
                      <xsl:apply-templates select='$toc except $toc/li[a/@href = $fn]'/>
                    </xsl:otherwise>
                  </xsl:choose>
                </ul>
              </td>

V nadpisu obsahu nechceme použít element <h2>, pouze jej zobrazíme tučně poněkud větším písmem. Na hlavní stránce má být zobrazen kompletní obsah, na ostatních stránkách je nutno přidat odkaz na úvodní stránku a vynechat odkaz na vlastní stránku.

              <!-- ***** Right column with the contents ***** -->
              <td width='100%'>
                <xsl:apply-templates select='current-group()'/>
              </td>
            </tr>
          </table>
        </body>
      </html>
    </xsl:result-document>
  </xsl:for-each-group>
</xsl:template>

V pravém sloupci zpracujeme celý obsah aktuální skupiny.

4.4.2. <xsl:template match='a[@name]'>

Návěští již nejsou nutná. Vynecháme je a vložíme pouze jejich obsah.

<xsl:template match='a[@name]'>
  <xsl:apply-templates/>
</xsl:template>

4.4.3. <xsl:template match='a[@href]'>

Z odkazů na vzory musíme vytvořit odkazy na odpovídající soubory. Pokud atribut href začíná znakem #, přidáme na začátek jméno hlavního souboru a odstraníme znak #.

<xsl:template match='a[@href]'>
  <a>
    <xsl:copy-of select='@*'/>
    <xsl:attribute name='href'>
      <xsl:value-of
           select='if (starts-with(@href, "#"))
           then concat($main, "-", substring-after(@href, "#"), $ext) else @href'/>
    </xsl:attribute>
    <xsl:apply-templates/>
  </a>
</xsl:template>
 Začátek stránky 

5. Download

Distribuční balíček obsahuje všechny výše zmíněné soubory společně s testovacím souborem test.rng. Tento soubor je odvozen ze schématu cstugbulletin.rng, ale neměl by být používán k validaci Zpravodajů. Je určen pouze k testování.

Download rngdoc.zip,.197  KB

 Začátek stránky