DocBook a generování rejstříkůObsah této stránky: Tento článek byl poprvé vydán ve sborníku konference SLT 2004. Abstrakt DocBook je dnes již považován za zcela standardní formát dokumentace. Dobrá dokumentace se ovšem neobejde bez dobrého rejstříku. Příspěvek posluchače seznámí s možnostmi DocBooku a XSL stylů pro generování rejstříku. Pozornost bude věnována i dodržování českých specifik při řazení a seskupování rejstříkových hesel. Budou ukázány techniky, jak s využitím standardních nástrojů generovat několik rejstříků v dokumentu a jak rejstříky automaticky vytvářet na základě sémantického značkování. DocBook se stává stále populárnějším formátem pro vytváření dokumentace k mnoha softwarovým projektům, psaní článků, knih, učebních textů, skript apod. Obliba roste zejména díky aplikacím podporujícím DocBook. Editory XML dokumentů jsou stále pohodlnější a dokonce již existují WYSIWYG editory, které jsou zdarma. Nástroje pro zpracování DocBooku a zejména nejpoužívanější XSL styly umožňují dokument převádět do mnoha výstupních formátů a podobu výstupu přitom ovlivnit řadou parametrů. Užitnou hodnotu dokumentů, zvláště tištěných, výrazně zvyšuje kvalitní rejstřík. Vytvoření dobrého rejstříku je velmi pracné a zodpovědné, a proto bývá často svěřeno do rukou specialisty. Bohužel v podmínkách dokumentace k open-source projektům, samizdatových publikací a dokonce i knih určených pro malý český trh se finanční a časové zdroje na práci rejstříkového specialisty většinou nedostávají. Proto se v tomto příspěvku podíváme na možnosti tvorby rejstříků v DocBooku tak, aby si každý autor dokumentu mohl sestavit rejstřík sám. Ukážeme si i pokročilejší možnosti, jako více rejstříků k jednomu dokumentu. Nakonec si ukážeme, jak snadno a automaticky doplnit rejstřík do dokumentů, které používají sémantické značkování k vyznačení objektů jako jsou názvy funkcí, jména souborů apod. Rejstříková hesla se zapisují přímo do dokumentu pomocí elementu
<para>Bohatství moderních společností je založeno na informacích<indexterm><primary>informace</primary></indexterm>.</para> Do elementu <indexterm> <primary>informace</primary> </indexterm> <indexterm> <primary>informace</primary> <secondary>získání</secondary> </indexterm> <indexterm> <primary>informace</primary> <secondary>šíření</secondary> </indexterm> <indexterm> <primary>informace</primary> <secondary>šíření</secondary> <tertiary>ústní</tertiary> </indexterm> V rejstříku se pak takto definovaná hesla objeví například jako: informace, 13 Pokud nějakému termínu odpovídá větší úsek dokumentu, můžeme ho
celý pokrýt jako rozsah. Použijí se dva elementy
<indexterm class="startofrange" id="ix.xml.historie"> <primary>XML</primary> <secondary>historie</secondary> </indexterm> ... <indexterm class="endofrange" startref="ix.xml.historie"/> Ve vygenerovaném rejstříku pak dostaneme interval: XML Pokud chceme, aby se položka řadila nestandardním způsobem,
použijeme atribut <indexterm> <primary sortas="Omega">Ω</primary> </indexterm> Chceme-li některé výskyty hesla v rejstříku zvýraznit (například mít stránku s primární definicí hesla tučně), můžeme u hesla nastavit jeho důležitost. <indexterm significance="preferred"> <primary>informace</primary> </indexterm> Nechceme-li, aby rejstříkové heslo obsahovalo odkaz na konkrétní
číslo strany, ale odkaz na jiné heslo, můžeme k tomu využít
elementy <indexterm> <primary>DTD</primary> </indexterm> <indexterm> <primary>definice typu dokumentu</primary> <see>DTD</see> </indexterm> <indexterm> <primary>XML schéma</primary> <seealso>DTD</seealso> </indexterm> Ve výsledném rejstříku bychom dostali: - D - Tímto jsme se seznámili skoro se všemi možnostmi zápisu
rejstříkových hesel v DocBooku. Nezmínili jsme pouze možnost
uložit definici rejstříkových hesel zcela mimo místo jejich výskytu
s využitím atributu XSL styly pro DocBook generují rejstřík zcela automaticky. Na
místě, kde chceme mít rejstřík, stačí uvést element
Při generování rejstříku se přitom samozřejmě respektují možnosti použitého výstupního formátu. Rejstřík v HTML stránce tak neobsahuje čísla stran, ale názvy sekcí či kapitol, ve kterých se heslo vyskytuje. Názvy zároveň slouží jako hypertextové odkazy, které dokáží skočit na místo výskytu rejstříkového hesla. Při výstupu do HTML Helpu se z rejstříkových hesel vytvoří přímo rejstřík na úrovni HTML Helpu. Lehce problematický je však tištěný výstup prováděný přes formátovací objekty do PDF. Princip generování rejstříku dokumentu XML v XSL je dvoufázový proces [2]. V první fázi se pomocí XSLT dokument přetransformuje na formátovací objekty, které abstraktním způsobem popisují vzhled tištěného dokumentu. Čísla stran v rejstříku v tuto chvíli nejsou a nemohou být vyhodnocena. K samotnému zalomení textu do stránek a vyhodnocení čísel stránek dojde až během následující fáze formátování. Stane-li se však, že jedno rejstříkové heslo se vyskytuje na jedné stránce dvakrát, objeví se číslo této stránky ve výstupu duplicitně. Tento velmi nepříjemný nedostatek lze naštěstí řešit několika způsoby, o kterých se zmíníme v další části článku. Dalším problémem je generování rejstříků pro jiné jazyky, než je angličtina. Generování rejstříku odpovídá seskupení všech rejstříkových hesel do skupin podle jejich prvního písmena, seřazení skupin podle abecedy a seřazení hesel v jedné skupině podle abecedy. Přesně tento algoritmus implementují i XSL styly. Pro češtinu je však nedostatečný. Písmeno „ch“ je složeno ze dvou znaků, ale přitom tvoří samostatnou skupinu. Slova začínající na „u“ a „ú“ patří do jedné skupiny, kdežto slova začínající na „c“ a „č“ patří do dvou různých skupin. Implementace korektního českého rejstříku není jednoduchá. Nástroje nabízené standardem XSLT pro seskupování jsou velmi slabé, a i řazení pro jednoduché jazyky jako angličtina je výzva. Navíc jsou styly pro DocBook psány tak, aby podporovaly dokumenty v různých jazycích. Každý jazyk má odlišná pravidla pro řazení a seskupování rejstříkových hesel. Jazyk XSLT však nenabízí dostatečné možnosti pro parametrizaci seskupovacího kódu na základě jazyka. Lze však využít rozšíření, které některé implementace XSLT nabízejí a dosáhnout tak požadovaného výsledku. K problematice generování rejstříku podle českých zvyklostí se také ještě vrátíme. Jak jsme již zmínili, současné verze jazyků XSLT a XSL-FO nenabízejí podporu pro eliminování duplicitních čísel stran v rejstříku. Problém jde obejít dvěma způsoby. Prvním z nich je využití procesoru FO, které implementuje rozšíření XSL-FO pro generování rejstříků. Druhá možnost spočívá ve víceprůchodovém zpracování dokumentu, během kterého se detekují a následně odstraní duplicity. Rozšíření pro generování rejstříků obsahují dva nejpoužívanější a nejlepší komerční procesory FO – XEP a XSL Formatter. Styly pro DocBook tato rozšíření podporují, stačí pomocí parametru říci, že se mají použít. Např. XEP by se pak spouštěl pomocí parametrů: xep -xml dokument.xml -xsl .../fo/docbook.xsl -param xep.extensions=1
V praxi však většinou parametrů nastavujeme více, a proto je praktické vytvořit si styl s úpravami (podrobněji viz např. [3] a [1]). Tento styl nejprve naimportuje standardní styly a pak provede potřebné změny v nastavení parametrů. <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:import href="http://docbook.sourceforge.net/release/xsl/current/fo/docbook.xsl"/> <xsl:param name="paper.type" select="'A4'"/> <xsl:param name="xep.extensions" select="1"/> </xsl:stylesheet> Pro XSL Formatter se odpovídající parametr jmenuje
5, 5, 8, 9, 10, 37 dostaneme na výstupu mnohem lepší podobu 5, 8–10, 37 V budoucnu nebude nutné přizpůsobovat výstup stylů použitému procesoru, protože příští verze XSL-FO 1.1 bude již přímo obsahovat podporu pro generování rejstříků. Používáme-li jiný procesor než XEP nebo XSL Formatter, musíme
pro odstranění duplicit podstoupit mnohem složitější proces. Tento
postup je nutné využít například společně s procesorem FOP, který je jednou
z mála alespoň částečně použitelných open-source implementací
XSL-FO. Nejprve dokument zpracujeme se zapnutým parametrem
DocBookové styly přizpůsobují svůj výstup jazyku, ve kterém je
dokument napsán. Aktivní jazyk je přitom možné určit pomocí atributu
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE book PUBLIC '-//OASIS//DTD DocBook XML V4.2//EN' 'http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd'> <book lang="cs"> ... </book> Díky již dříve zmíněným omezením jazyka XSLT však nemohou styly vzít aktivní jazyk v úvahu při generování rejstříku. Naštěstí některé z XSLT procesorů umožňují definice uživatelských funkcí, pomocí kterých již lze implementovat seskupování závislé na jazyku. Protože tato část stylů používá nestandardní instrukce XSLT a mohla by způsobit problémy s kompatibilitou, není zahrnuta do standardního stylu. Chceme-li český rejstřík generovat, musíme používat XSLT
procesor, který podporuje definování uživatelských funkcí podle EXSLT a tyto funkce lze použít
v definici klíče ( Stačí si pak vytvořit styl s úpravami, který ve
standardních stylech předefinuje některé šablony generující rejstřík.
Kód již je hotový v souboru <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:import href="http://docbook.sourceforge.net/release/xsl/current/fo/docbook.xsl"/> <xsl:include href="http://docbook.sourceforge.net/release/xsl/current/fo/autoidx-ng.xsl"/> <!-- Další úpravy, nastavení parametrů --> </xsl:stylesheet> Úpravy kódu pro generování rejstříku jsou dostupné i pro
HTML výstup, opět v souboru Takto upravené styly přiřadí hesla správně do skupiny,
a skupiny seřadí správně podle české abecedy. Je ošetřena
i problematika písmena „ch“. Řazení hesel
v jedné skupině je ponecháno na XSLT procesoru. Saxon[1] běžně české řazení nezvládá, ale můžeme jej o podporu
českého řazení snadno rozšířit. Stačí, když do javové cesty
( package com.icl.saxon.sort; import java.text.Collator; import java.util.Locale; public class Compare_cs extends TextComparer { int caseOrder = UPPERCASE_FIRST; public int compare(Object a, Object b) { Collator csCollator = Collator.getInstance(new Locale("cs", "cz")); return csCollator.compare(a, b); } public Comparer setCaseOrder(int caseOrder) { this.caseOrder = caseOrder; return this; } } V některých typech publikací je zapotřebí několika
samostatných rejstříků – např. předmětného a jmenného. XSL
styly si s tímto požadavkem snadno poradí. Při zápisu
rejstříkového hesla stačí v atributu <para>Bohatství moderních společností je založeno na informacích.<indexterm role="subj"><primary>informace</primary></indexterm> O rozvoj informační teorie se ve 40. letech zasloužil Claude Shannon. <indexterm role="name"><primary>Shannon, Claude</primary></indexterm></para> Na konec dokumentu pak vložíme dva elementy
<index role="subj"/> <index role="name"> <title>Jmenný rejstřík</title> </index> Zda se bude generovat několik rejstříků podle obsahu atributu
Od DocBooku 4.3 je pro určení typu rejstříku a rejstříkového
hesla k dispozici nový atribut Výhoda DocBooku a XML obecně oproti jiným technologiím pro přípravu dokumentů je možnost velmi jemného přiřazovaní významu jednotlivým částem textu. DocBook obsahuje několik desítek sémantických elementů, které umožňují odlišit jména souborů, od názvů funkcí, příkazů atd. Podívejme se na ukázku odstavce, který takto sémantické značkování používá. <para>Příkaz <command>rm</command> je užitečný, ale používejte jej opatrně. Některé soubory jako například <filename>/etc/passwd</filename> jsou pro váš systém poměrně důležité.</para> U větších tištěných příruček je velmi užitečné, pokud se všechny důležité termíny vyskytují v rejstříku. Mezi tyto termíny mohou v některých příručkách patřit i názvy příkazů nebo souborů. Pro zařazení hesel z předchozího příkladu do rejstříku bychom museli ručně doplnit odpovídající značkování. <para>Příkaz <command>rm</command><indexterm><primary>rm</primary></indexterm> <indexterm><primary>příkaz</primary><secondary>rm</secondary></indexterm> je užitečný, ale používejte jej opatrně. Některé soubory jako například <filename>/etc/passwd</filename><indexterm><primary>/etc/passwd</primary></indexterm> jsou pro váš systém poměrně důležité.</para> V rejstříku bychom pak dostali následující hesla - Symboly - Výsledek je sice užitečný, ale po pravdě řečeno, kdo by chtěl do vstupního dokumentu zapisovat mnoho redundantní informace. V tomto případě je naštěstí mapování sémantických značek na rejstříková hesla velmi jednoduché a jednoznačné, takže je můžeme snadno algoritmizovat. Není problém napsat jednoduchý XSLT styl, který do dokumentu obsahujícího pouze sémantické značky doplní rejstříková hesla podle našich požadavků. <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <!-- Zkopírování celého dokumentu --> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <!-- Příkazy se dají do rejstříku na dvě místa --> <xsl:template match="command"> <!-- Zkopírování původního elementu --> <xsl:copy-of select="."/> <!-- Vytvoření rejstříkových hesel --> <indexterm> <primary><xsl:value-of select="."/></primary> </indexterm> <indexterm> <primary>příkaz</primary> <secondary><xsl:value-of select="."/></secondary> </indexterm> </xsl:template> <!-- Každé jméno souboru se také přidá do rejstříku --> <xsl:template match="filename"> <!-- Zkopírování původního elementu --> <xsl:copy-of select="."/> <!-- Vytvoření rejstříkového hesla --> <indexterm> <primary><xsl:value-of select="."/></primary> </indexterm> </xsl:template> </xsl:stylesheet> Zpracujeme-li nyní náš dokument tímto stylem, dostaneme dočasný dokument, kde budou pro všechny příkazy a jména souborů doplněná rejstříková hesla. Dočasný soubor pak můžeme zpracovat běžnými XSL styly pro DocBook. Celý proces generování dočasného dokumentu a jeho následného zpracování si můžeme zautomatizovat pomocí makefile, dávkových souborů nebo podobné techniky. Docbookové styly nám však nabízejí možnost výše zmíněného automatického doplnění rejstříkových hesel přímo během zpracování dokumentu styly. Není proto potřeba vůbec využívat dočasný soubor a zpracovávat dokument dvěma průchody. Řešení využívá vlastnosti stylů, které se říká profilování. Profilování umožňuje podmíněně zpracovávat jen určité části dokumentu na základě hodnot uložených v atributech. V dokumentu tak můžeme např. označit, že některé kapitoly jsou určené pro začátečníky používající náš program v Linuxu a některé zase pro pokročilé uživatele Windows. Styly pro DocBook při zpracování dokumentu nejprve provedou odfiltrování nepotřebných částí dokumentu a pak provedou klasické zpracování. Filtrování je přitom interně implementováno jako speciální režim, ve kterém se provádí podmíněné kopírování dokumentu. Protože se profilování obvykle provádí pro elementy jako kapitola a podkapitola a málokdy pro sémantické inline elementy, můžeme v tomto režimu přidat šablony, které se kromě profilování postarají o doplnění rejstříkových hesel právě pro sémantické elementy. <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <!-- Naimportování původního stylu --> <xsl:import href="http://docbook.sourceforge.net/release/xsl/current/fo/profile-docbook.xsl"/> <!-- Příkazy se dají do rejstříku na dvě místa --> <xsl:template match="command" mode="profile"> <!-- Zkopírování původního elementu --> <xsl:copy-of select="."/> <!-- Vytvoření rejstříkových hesel --> <indexterm> <primary><xsl:value-of select="."/></primary> </indexterm> <indexterm> <primary>příkaz</primary> <secondary><xsl:value-of select="."/></secondary> </indexterm> </xsl:template> <!-- Každé jméno souboru se také přidá do rejstříku --> <xsl:template match="filename" mode="profile"> <!-- Zkopírování původního elementu --> <xsl:copy-of select="."/> <!-- Vytvoření rejstříkového hesla --> <indexterm> <primary><xsl:value-of select="."/></primary> </indexterm> </xsl:template> </xsl:stylesheet> Nově připravený styl pak z pohledu uživatele zvládne během jednoho kroku do dokumentu doplnit rejstříková hesla a ještě jej zpracovat (např. převést do FO nebo HTML). V článku jsme se podrobně seznámili s možnostmi generování rejstříku pro dokumenty v DocBooku za použití standardních XSL stylů. Ukázali jsme si, jak generovat rejstříky vyhovující českým zvyklostem, jak do jednoho dokumentu vložit několik rejstříků a jak ze sémantického značkování automaticky generovat rejstříková hesla. [1] DocBook. Stručný úvod do tvorby a zpracování dokumentů. URL: http://www.kosek.cz/xml/db/. [2] 105-113. „XSL FO a jeho open-source implementace“. 7.-10. listopadu 2002. Seč. . 80-7302-043-2. SLT 2002. [3] DocBook XSL: The Complete Guide. 2003. 0-9741521-1-0. 394. URL: http://www.sagehill.net/docbookxsl/index.html. [4] DocBook. The Definitive Guide. 1999. 1. 156592-580-7. 648. URL: http://www.docbook.org/tdg/en/html/docbook.html. [1] Máme teď na mysli verzi 6.5.3, která se používá s XSL styly pro DocBook, ne verzi 7.x, která implementuje návrh XSLT 2.0. | |