DTD -- lekce druhá

Jiří Kosek ml.

Deklarace atributů

V XML může mít každý element libovolné množství atributů. Atributy se většinou používají pro přidání různých metainformací k elementům.

Definice atributů pro element má poměrně jednoduchý tvar:

<!ATTLIST jméno_elementu deklarace atributů>

Deklarace jednotlivých atributů se skládá ze tří částí. První částí je jméno atributu. Pro jména atributů platí stejná omezení jako pro jména elementů. Atributy jsou rovněž citlivé na velikost písmen, a tak MujAtribut a MUJATRIBUT jsou dva zcela rozdílné atributy.

Za jménem následuje typ atributu. Poslední část určuje standardní hodnotu atributu, popřípadě, zda je používání atributu u daného elementu povinné. Deklarace atributu se opakuje pro každý atribut, který má být u elementu k dispozici.

Nejobecnějším typem atributu je CDATA, který umožňuje jako hodnotu atributu zadat libovolný textový řetězec. Po deklaraci

<!ATTLIST kniha autor CDATA ...>  

Můžeme v dokumentu používat atribut autor následovně

<kniha autor="Karel Čapek">

Mnohem restriktivnějším typem než CDATA je NMTOKEN. Atribut tohoto typu může obsahovat jedno slovo, které se skládá z písmen, číslic a několika dalších speciálních znaků.

Můžeme použít i typ NMTOKENS. Atribut pak může obsahovat několik slov vyhovujících typu NMTOKEN oddělených mezerou.

<!ATTLIST dokument format NMTOKEN ...
                   okraje NMTOKENS ...>

V dokumentu pak můžeme použít element dokument například takto:

<dokument format="A4" okraje="2cm 3cm 2.5cm 3cm">
	...
</dokument>

Mezi další typy atributů patří ID, IDREF a IDREFS, které se používají pro vytváření odkazů v rámci dokumentu. Podrobněji si o nich povíme v některé z dalších částí seriálu věnované odkazům mezi XML-dokumenty.

Další dva typy jsou ENTITY a ENTITIES, které použijeme v případech, kdy atribut obsahuje jméno (resp. jména) entity. Entitám se budeme rovněž věnovat samostatně.

Dalším typem atributu, na který dnes ještě nedojde, je NOTATION. Atributy NOTATION slouží k určení typu dat, které obsahuje element, pokud se nejedná o XML-data.

Poslední možností, jak vymezit typ atributu, je uvedení výčtu přípustných hodnot atributu. Např.:

<!ATTLIST obrazek zarovnani (vlevo | vpravo | doprostred) ... >

U elementu obrazek nyní můžeme jako hodnotu atributu zarovnani uvést pouze jedno ze slov vlevo, vpravo a doprostred.

V deklaraci všech atributů jsme zatím na posledním místě používali tři tečky. Na tomto místě se uvádí standardní hodnota atributu nebo to, zda je atribut povinný.

Pokud je atribut povinný, uvede se za deklarací jeho typu slovo #REQUIRED. Parser při kontrole dokumentu ohlásí chyby vždy, když nebude tento atribut u elementu použit. XML-editor si může zadání hodnoty atributu vynutit přímo při vložení elementu, který povinný atribut obsahuje.

Opačným případem je situace, kdy můžeme atribut vynechat, a v tomto případě si jeho hodnotu podle svých potřeb domyslí sama konkrétní aplikace, která právě s dokumentem pracuje. V těchto případech se použije klíčové slovo #IMPLIED.

Další možností je specifikování standardní hodnoty. Stačí ji uvést. Pokud chceme, aby byl obrázek zarovnán vlevo, pokud není určeno jinak, použijeme deklaraci:

<!ATTLIST obrazek zarovnani (vlevo | vpravo | doprostred) "vlevo" >

Deklarace elementů a atributů je základem každého DTD. To může obsahovat ještě další prvky, i když už to není tak časté. Pokud navrhujeme nějaká složitější DTD mohou se nám hodit tzv. parametrické entity, které umožňují zkrátit a zefektivnit zápis.

Parametrické entity

V DTD často opakujeme stejné sekvence textu. V praxi např. mívají všechny elementy několik společných atributů. Je pak zbytečné znovu a znovu opisovat deklaraci týchž atributů. Práci nám mohou usnadnit parametrické entity. Pomocí zápisu

<!ENTITY % entita "nějaký text">

Definujeme parametrickou entitu, na kterou se v DTD budeme odvolávat pomocí zápisu %entita;. Použití parametrické entity z funkčního hlediska odpovídá napsání celého textu, který entita zastupuje, šetří se však práce. Následuje ukázka definice parametrické entity %spolecne-atributy;:

<!ENTITY % spolecne-atributy 
	"jazyk	CDATA 	#IMPLIED
	 utajeni (verejne|tajne|prisne-tajne) 'verejne'">

<!ELEMENT clanek	(nazev, autor?, p*)>
<!ATTLIST clanek	%spolecne-atributy;>
<!ELEMENT nazev	(#PCDATA)>
<!ATTLIST nazev	%spolecne-atributy;>
<!ELEMENT autor	(#PCDATA)>
<!ATTLIST autor  	%spolecne-atributy;>
<!ELEMENT p  	(#PCDATA)>
<!ATTLIST p  	%spolecne-atributy;
          id 	ID 	#REQUIRED>

V ukázkovém DTD deklarujeme elementy clanek, nazev, autor a p. Všechny elementy přitom mají atributy jazyk a utajeni. Element p má navíc ještě atribut id. Kdybychom nevyužili parametrické entity, byl by zápis mnohem delší a jeho pozdější modifikace by byla náročnější.

<!ELEMENT clanek (nazev, autor?, p*)>
<!ATTLIST clanek 
	 jazyk 	CDATA 	#IMPLIED
	 utajeni (verejne|tajne|prisne-tajne) 'verejne'>
<!ELEMENT nazev   (#PCDATA)>
<!ATTLIST nazev  
	 jazyk 	CDATA 	#IMPLIED
	 utajeni (verejne|tajne|prisne-tajne) 'verejne'>
<!ELEMENT autor   (#PCDATA)>
<!ATTLIST autor  
	 jazyk 	CDATA 	#IMPLIED
	 utajeni (verejne|tajne|prisne-tajne) 'verejne'>
<!ELEMENT p	(#PCDATA)>
<!ATTLIST p 
	 jazyk 	CDATA 	#IMPLIED
	 utajeni (verejne|tajne|prisne-tajne) 'verejne'
	 id 	ID 	#REQUIRED>

Kontrola dokumentu oproti DTD

Výhoda ukládání dokumentů v XML spočívá především v možnosti zachytit pomocí elementů strukturu dokumentu. Základním nástrojem, který se při práci s XML dokumenty používá, je parser. Parser je program, který kontroluje, zda je dokument správně strukturovaný. Lepší parsery zároveň kontrolují, zda dokument odpovídá danému DTD (samozřejmě jen pokud DTD pro dokument existuje).

Parsery dnes existují ve dvou podobách. Tou první jsou knihovny pro různé programovací jazyky, které můžeme využívat v našich programech. Parser nám pak kromě detekce chyb v dokumentu umožní velmi snadné čtení dat z XML dokumentů. K tomu, jak parser využít z pohledu programátora, se ještě podrobněji vrátíme v některém z dalších dílů. Pro nás je nyní důležité, že většina parserů existuje i v podobě jednoduchých programů, kterým na vstup předáme XML dokument, a na výstupu obdržíme případný přehled chyb v dokumentu.

Parser využijeme zejména v situaci, kdy chceme ověřit, zda náš dokument neobsahuje nějaké syntaktické a strukturní chyby. Tato situace může nastat v případě, kdy dokument vytváříme v editoru, který nemá podporu XML a umožní nám vytvořit chybný dokument. Dnes je k dispozici mnoho parserů napsaných v různých programovacích jazycích. Velice populární platformou pro psaní parserů je jazyk Java. Z hlediska výkonu jsou však dnes lepší parsery napsané v jazyce C++. Použitý jazyk nás však jako uživatele nemusí až zas tak moc zajímat, důležitá je funkčnost.

Za jeden z nejlepších parserů se dnes považuje parser SP od Jamese Clarka. SP je k dispozici zdarma včetně zdrojových textů, pracuje ve Windows i na Unixu (dokonce existuje i verze pro MS-DOS). Jeho kvality dokládá i to, že se stal základem mnoha komerčních parserů, které jsou prodávané za velké peníze. SP byl původně parser vyvinutý pro jazyk SGML, ale od verze 1.3 podporuje i XML. Nic nám nebrání v jeho využití.

SP si můžete stáhnout ze serveru www.jclark.com. Pro spuštění SP ve Windows budete konkrétně potřebovat soubor ftp://ftp.jclark.com/pub/win32/sp1_3.zip. Soubor rozbalíme například do adresáře c:\sp. Pokud si chceme usnadnit spouštění parseru, přidáme si do proměnné PATH cestu c:\sp\bin.

Samotný parser je realizován programem nsgmls. Před jeho spuštěním musíme nastavit ještě několik proměnných prostředí, aby správně pracovala podpora XML. Proměnná SP_CHARSET_FIXED musí být nastavena na hodnotu YES. Proměnná SP_ENCODING by měla mít hodnotu XML. Jelikož zatím není k dispozici mnoho editorů, které by přímo podporovaly kódování UTF-8, které je v XML preferováno, je lepší proměnnou SP_ENCODING nastavit na hodnotu windows, resp. iso-8859-2 v Unixu. Pro psaní XML dokumentů pak můžeme použít libovolný textový editor. Poslední proměnnou, kterou musíme nastavit, je SGML_CATALOG_FILES. Do proměnné musíme uložit cestu k souboru xml.soc -- např. c:\sp\pubtext\xml.soc.

Nyní si vytvoříme dokument, který budeme parserem kontrolovat. Dejme tomu, že vytvoříme dokument, který vyhovuje DTD, které jsme před chvílí použili jako příklad pro parametrické entity. DTD uložíme do souboru clanek.dtd. Náš testovací dokument pokus.xml může být třeba takovýto:

<!DOCTYPE clanek SYSTEM "clanek.dtd">
<clanek>
<nazev>O myších bez lidí</nazev>
<p>Myši možná nejsou tak...</p>
<p>Myšlenka, že myši ovládají...</p>
</clanek>

Pomocí příkazu

nsgmls -wxml -s pokus.xml

spustíme parser. Pokud je náš dokument dobře strukturovaný a vyhovuje zadanému DTD, neohlásí parser žádnou chybu. Zkuste v dokumentu záměrně udělat nějakou chybu (zapomeňte ukončovací tag, překřižte tagy, použijte neexistující atribut apod.) a uvidíte, jak vám o tom podá nsgmls zprávu.

Pokud máme XML dokument, ke kterému neexistuje DTD, můžeme jej pomocí nsgmls také zkontrolovat. Stačí použít parametr -wno-valid a u dokumentu bude pouze kontrolováno, zda je správně strukturovaný (well-formed).

© Jiří Kosek 1999