DTD -- Definice typu dokumentu pod lupou

Ji°φ Kosek ml.

Vztah DTD k dokumentu

V ·vodnφm Φlßnku o XML jsme si °ekli, ₧e XML-dokument m∙₧e vyhovovat urΦitΘmu typu dokumentu. Definice typu dokumentu (DTD) p°itom °φkß, kterΘ elementy a atributy m∙₧eme v dokumentu pou₧φt. Navφc je zde definovßno, v jak²ch vzßjemn²ch vztazφch mohou b²t jednotlivΘ elementy pou₧ity. DTD je tedy u₧iteΦn² nßstroj, kter² nßm umo₧nφ hlφdat, zda majφ naÜe dokumenty sprßvnou strukturu. Ve sv∞t∞ se pou₧φvß mnoho DTD, kterΘ vyhovujφ r∙zn²m po₧adavk∙m. Mezi jedno z nejznßm∞jÜφch pat°φ nap°φklad DocBook, kterΘ definuje elementy a atributy vhodnΘ pro znaΦkovßnφ technickΘ dokumentace.

Tφm, ₧e naÜe dokumenty zalo₧φme na urΦitΘmu DTD, zφskßme hned dv∞ v²hody. Jednak m∙₧eme pomocφ parseru kontrolovat, zda mß nßÜ dokument sprßvnou strukturu. Druhß v²hoda je patrnß p°i pou₧itφ standardnφch DTD jako HTML nebo DocBook -- k dispozici budeme mφt mnoho u₧iteΦn²ch a jedno·Φelov²ch nßstroj∙ navrhnut²ch pro konkrΘtnφ DTD. Nap°φklad nenφ problΘm pro DocBook sehnat definici styl∙ vhodn²ch pro formßtovßnφ dokumentace Φi programy, kterΘ umφ dokumenty DocBook konvertovat do HTML a dalÜφch formßt∙.

DTD se k dokumentu p°idßvß pomocφ deklarace typu dokumentu (DOCTYPE), kterß je umφst∞na na zaΦßtku dokumentu ihned za XML deklaracφ. NejΦast∞ji je DTD ulo₧eno v samostatnΘm souboru, aby mohlo b²t vyu₧φvßno v mnoha dokumentech. V tomto p°φpad∞ mß deklarace tvar:

<!DOCTYPE ko°enov²_element SYSTEM "URL">

URL p°itom udßvß adresu nebo jmΘno souboru, ve kterΘm je ulo₧eno DTD. Ko°enov² element je jmΘno elementu, kter² je v DTD definovan² jako ko°enov² -- tj. obsahuje vÜechny dalÜφ elementy dokumentu.

Pro n∞kterß b∞₧n∞ pou₧φvanß a standardizovanß DTD je zbyteΦnΘ, aby si parser a dalÜφ aplikace Φetly DTD v₧dy ze sφt∞. Mnohem logiΦt∞jÜφ by bylo, aby v systΘmu byla p°φtomna lokßlnφ kopie soubor∙ s DTD. To je v XML mo₧nΘ pomocφ takzvan²ch ve°ejn²ch identifikßtor∙. K oznaΦenφ DTD pou₧ijeme n∞jak² textov² °et∞zec. XML-aplikace pak ve svΘm konfiguraΦnφm souboru zjistφ, ve kterΘm souboru je ulo₧eno p°φsluÜnΘ DTD. Mφsto slova SYSTEM nynφ pou₧ijeme v²raz PUBLIC, ze kter²m uvedeme identifikßtor DTD. Nakonec vÜak stejn∞ musφme p°ipojit URL, kterΘ ukazuje na soubor s DTD, aby mohla aplikace DTD zφskat i v p°φpad∞, ₧e nerozpoznß ve°ejn² identifikßtor. Deklarace typu dokumentu pak m∙₧e dopadnout t°eba takto:

<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN" "docbook.dtd">	 

DTD m∙₧eme umφstit i p°φmo do dokumentu pomocφ nßsledujφcφho zßpisu.

<!DOCTYPE kniha [
   ... DTD ...
]>

Umφst∞nφ DTD p°φmo do dokumentu nenφ p°φliÜ ΦastΘ, proto₧e pak ztrßcφme mo₧nost sdφlenφ jednoho DTD mezi n∞kolika dokumenty. U₧iteΦn∞jÜφ je vÜak mo₧nost zkombinovat ob∞ p°edeÜlΘ metody a externφ DTD upravit pomocφ lokßln∞ uveden²ch definic. Lokßlnφ Φßst DTD se zpracovßvß jeÜt∞ p°ed tou externφ a m∙₧e tedy zm∞nit n∞kterΘ definice ulo₧enΘ v externφm DTD.

<!DOCTYPE kniha SYSTEM "kniha.dtd" [
   ... definice, kterΘ zm∞nφ nebo rozÜφ°φ kniha.dtd ...
]>

Jak vypadß DTD

Kdy₧ vφme, jak p°ipojit DTD k dokumentu, m∙₧eme se podφvat na to, jak samotnΘ DTD vypadß. DTD obsahuje deklarace Φty° typ∙:

Deklarace element∙

Deklarace novΘho elementu je velice jednoduchß. Mß nßsledujφcφ tvar:

<!ELEMENT nßzev_elementu obsah_elementu>

Nßzev elementu musφ zaΦφnat pφsmenem. DalÜφ znaky nßzvu mohou obsahovat pφsmena, Φφslice a n∞kterΘ specißlnφ znaky jako '.', '-', '_' a ':'. DΘlka jmΘna nenφ nikterak omezenß. Narozdφl od HTML je d∙le₧itß velikost pφsmen. Nßsledujφcφ dva °ßdky deklarujφ dva r∙znΘ elementy kapitola a Kapitola.

<!ELEMENT kapitola ...>
<!ELEMENT Kapitola ...>

Nejzajφmav∞jÜφ je vÜak poslednφ Φßst deklarace elementu, kterß definuje, co m∙₧e element obsahovat. NejjednoduÜÜφ je prßzdn² element, kter² nem∙₧e obsahovat ₧ßdnΘ dalÜφ elementy nebo text. P°φkladem takovΘho elementu mohou b²t nap°φklad elementy br a hr, kterΘ d∙v∞rn∞ znßme z HTML. Jejich deklarace by vypadala nßsledovn∞:

<!ELEMENT br EMPTY>
<!ELEMENT hr EMPTY>

Prßv∞ klφΦovΘ slovo EMPTY urΦuje, ₧e element nesmφ nic obsahovat. V dokumentu pak musφme psßt bu∩ <br></br>, nebo zkrßcen∞ <br/>. Nenφ vÜak mo₧n² zßpis <br>, proto₧e by parser zcela marn∞ hledal ukonΦovacφ tag </br>.

Krom∞ v²Üe zmφn∞n²ch p°φpad∙ se prßzdnΘ elementy pou₧φvajφ nap°φklad pro vklßdßnφ obrßzk∙. Pomocφ atribut∙ elementu pak urΦφme soubor, ve kterΘm je obrßzek ulo₧en.

Protip≤lem k EMPTY je ANY. Toto klφΦovΘ slovo nßm zajistφ, ₧e element m∙₧e obsahovat libovolnΘ dalÜφ elementy a text. ANY se v praxi moc Φasto nevyu₧φvß, proto₧e pro pot°eby v∞tÜiny aplikacφ p°φliÜ uvol≥uje strukturu dokumentu. Vyu₧itφ nalezne nap°φklad p°i nßvrhu a lad∞nφ DTD, kdy nechceme najednou napsat celΘ DTD.

<!ELEMENT cokoliv ANY>

V∞tÜinou mßme na vno°enΘ elementy mnohem striktn∞jÜφ po₧adavky a s EMPTY a ANY nevystaΦφme. V tomto p°φpad∞ pak pou₧ijeme tzv. modelovou skupinu (model group). Modelovß skupina se pou₧φvß pro definici element∙, kterΘ obsahujφ dalÜφ elementy nebo majφ smφÜen² obsah (obsahujφ ji₧ p°φmo text a elementy).

Modelovß skupina je v₧dy uzav°ena do kulat²ch zßvorek a obsahuje alespo≥ jedno slovo. Tφmto slovem nejΦast∞ji b²vß jmΘno elementu, kter² m∙₧e b²t obsa₧en v prßv∞ definovanΘm elementu. Vno°enΘ elementy m∙₧eme navzßjem kombinovat pomocφ odd∞lovaΦ∙ ',' a '|'. Elementy odd∞lenΘ Φßrkou musφ nßsledovat v po°adφ, v jakΘm jsou uvedeny. Pokud mß tedy element html obsahovat zßhlavφ (head) a t∞lo (body), pou₧ijeme deklaraci:

<!ELEMENT html (head, body)>

Pokud naopak elementy odd∞lφme znakem '|' m∙₧e b²t obsa₧en pouze jeden z nich. P°φklad: potomek m∙₧e b²t dcera nebo syn. V DTD to vyjßd°φme takto:

<!ELEMENT potomek (dcera | syn)>

Pomocφ zßvorek m∙₧eme ob∞ dv∞ varianty navzßjem kombinovat. Pokud mß n∞jak² element obsahovat elementy a, b a za nimi bu∩ c nebo d, pou₧ijeme modelovou skupinu (a, b, (c | d)).

Krom∞ po°adφ element∙ musφme urΦit jejich poΦet, zda jsou povinnΘ Φi zda se mohou opakovat. Pokud v modelovΘ skupin∞ uvedeme pouze jmΘno elementu, musφ b²t element p°φtomen prßv∞ jednou. Pokud je vÜak v²skyt elementu nepovinn², uvedeme za jeho jmΘno znak '?'. Pokud nap°φklad Φlßnek obsahuje v₧dy nßzev, ale autora obsahovat nemusφ, m∙₧eme pou₧φt nßsledujφcφ deklaraci:

<!ELEMENT clanek (nazev, autor?)>

DalÜφ obvyklou situacφ je, ₧e n∞jak² element se m∙₧e opakovat, ale musφ b²t p°φtomen alespo≥ jednou. Nap°φklad kniha se sklßdß z n∞kolika kapitol, ale musφ obsahovat alespo≥ jednu kapitolu:

<!ELEMENT kniha (kapitola+)>

Vra¥me se k p°edchozφmu p°φkladu a p°edklßdejme, ₧e Φlßnek m∙₧e mφt vφce autor∙ a nemusφ mφt autora ₧ßdnΘho. V tomto p°φpad∞ s v²hodou vyu₧ijeme znak '*', kter² indikuje libovoln² poΦet opakovßnφ.

<!ELEMENT clanek (nazev, autor*)>

VÜe m∙₧eme podle pot°eby kombinovat. Pokud chceme vyjßd°it, ₧e seznam obsahuje alespo≥ dv∞ polo₧ky, m∙₧eme pou₧φt modelovou skupinu (polozka, polozka+).

Indikßtor poΦtu v²skyt∙ m∙₧eme p°ipojit i za modelovou skupinu. Nap°φklad zßpis (a, b)? °φkß, ₧e se elementy a a b bu∩ musφ vyskytovat v danΘm po°adφ, nebo nesmφ b²t pou₧ity.

Specißlnφ pozornost si zaslou₧φ p°φpad, kdy je obsahem elementu ji₧ samotn² text. To vyjßd°φme pomocφ slova #PCDATA. Pokud by nap°φklad element em obsahoval ji₧ pouze text, a ne dalÜφ elementy, pou₧ili bychom pro jeho deklaraci zßpis:

<!ELEMENT em (#PCDATA)>

Pokud m∙₧e element obsahovat jak text tak elementy °φkßme, ₧e mß smφÜen² obsah. V tomto p°φpad∞ musφ mφt deklarace jeho obsahu specißlnφ tvar. #PCDATA musφ b²t uvedeno ve skupin∞ jako prvnφ, skupina musφ b²t spojena pomocφ operßtoru '|' a musφ b²t voliteln∞ opakovatelnß (*). Nap°φklad

<!ELEMENT em  (#PCDATA, sub, sup)*>
<!ELEMENT sub (#PCDATA)>
<!ELEMENT sup (#PCDATA)>

Dokument pak m∙₧e obsahovat nßsledujφcφ text vyhovujφcφ DTD:

<em>Pozor na lφh - C<sub>2</sub>H<sub>5</sub>OH.</em>

Mßme za sebou ·vod do tvorby tΘ Φßsti DTD, kterß definuje pou₧itelnΘ elementy. P°φÜt∞ se podφvßme na to, jak k element∙m p°idat atributy. PotΘ si ji₧ ukß₧eme, jak m∙₧eme pomocφ parseru kontrolovat sprßvnost naÜich dokument∙.

Ve°ejnΘ identifikßtory

Pou₧itφ ve°ejn²ch identifikßtor∙ mß mnohΘ v²hody. Aby jsme je mohli pou₧φt, musφme mφt na svΘm poΦφtaΦi lokßlnφ kopie vÜech soubor∙ DTD, kterΘ pou₧φvßme. V souboru catalog pak musφme mφt k dispozici mapovßnφ mezi ve°ejn²mi identifikßtory a soubory. Mßme-li nap°φklad DTD ulo₧ena v adresß°i c:\dtd, budeme mφt pro DocBook v katalogovΘm souboru °ßdek

PUBLIC "-//OASIS//DTD DocBook V3.1//EN" "c:\dtd\docbook.dtd"

Aby vÜechny aplikace katalogov² soubor naÜly, musφme jeho umφst∞nφ ulo₧it do prom∞nnΘ prost°edφ SGML_CATALOG_FILES.

Samotn² v²znam jednotliv²ch Φßsti ve°ejnΘho identifikßtoru vychßzφ z SGML. Prvnφ znak '-' znamenß, ₧e identifikßtor nenφ zaregistrovßn. Znamenß to, ₧e nenφ zaruΦena jeho celosv∞tovß jednoznaΦnost. Pro registrovanΘ identifikßtory se na tomto mφst∞ pou₧φvß znak '+'. Pokud je vlastnφkem organizace ISO, uvßdφ se na zaΦßtku °et∞zec ISO 8879:1986.

DalÜφ Φßst identifikßtoru oznaΦuje organizaci nebo osobu, kterß je vlastnφkem souboru oznaΦenΘho ve°ejn²m identifikßtorem. Nap°φklad pro HTML mß identifikßtor tvar

-//W3C//DTD HTML 4.0 Transitional//EN

Na prvnφ pohled vidφme, ₧e vlastnφkem je konsorcium W3C. U DocBooku je to zase firma Oasis.

Za dalÜφmi dv∞ma lomφtky nßsleduje urΦenφ typu souboru. V naÜem p°φpad∞ tam bude v₧dy DTD, proto₧e se odkazujeme na soubor s DTD. PotΘ nßsleduje textovΘ oznaΦenφ dokumentu -- nap°φklad DocBook V3.1 pro verzi 3.1 systΘmu DocBook. Za poslednφmi dv∞ma lomφtky je k≤d jazyka, ve kterΘm je DTD zapsßno. NejΦast∞ji se setkßme s k≤dem EN, kter² odpovφdß angliΦtin∞.

© Ji°φ Kosek 1999