Hlavní navigace

Úskalí XML

Petr Cimprich

Jedním z hlavních požadavků kladených na jazyk XML měla být jeho relativní jednoduchost. Jednoduchostí a přehledností se XML mělo odlišit od svého předchůdce SGML. Jednoduchost a přehlednost měla umožnit maximální využití nového formátu pro přenos dokumentů, snadnou implementaci nástrojů a spolupráci s dalšími technologiemi. Jak se to podařilo?

To asi musí posoudit každý sám. Já bych řekl, že víceméně ano, aspoň soudě podle úspěchu, se kterým se XML setkalo. Časem samozřejmě přibývá dalších a dalších standardů a komplexnost technologií XML roste, to je přirozený vývoj. Překvapivá úskalí však obsahuje už jádro XML (XML 1.0, jmenné prostory) a nejtěsnější okruh základních technologií (kam počítám zejménaDOM, XPath, XSLT a XML Schema).

Na některá z těchto kritických, nebo třeba jen zajímavých míst se pokusím upozornit v sérii několika krátkých článků; tento je první z nich. Nebude se jednat ani o úvod do XML, ani o souvislý výklad. Ke čtení by měla postačit pouze základní znalost jazyka XML, znalci se možná budou nudit. Většina problematických oblastí souvisí buď s dědictvím ze SGML, deklaracemi DTD a externími entitami, nebo se jmennými prostory a kvalifikovanými jmény. První ukázka možných problémů se týká kombinace obou těchto možností.

Jmenné prostory a DTD

Jména elementů a atributů mohou být zařazena do jmenných prostorů. Elementy a attributy jsou pak označeny kvalifikovnými jmény skládajícími se z nepovinného prefixu a lokálního jména. Prefix pouze zastupuje skutečný identifikátor jmenného prostoru (v XML 1.0 je jím URI), proto musí existovat deklarace vázající každý použitý prefix ke jmennému prostoru. Deklarace mají podobu vyhrazených attributů začínajících na ‚xmlns‘. Vše může vypadat například takto:

<?xml version="1.0"?>
<p:root
xmlns:p="http://gingerall.org/ns/example">text</p:root>

Deklarační atribut, stejně jako jakýkoli jiný atribut v XML, může být definován buď přímo u elementu, ke kterému patří, nebo může být definován implicitně v definici typu dokumentu. Opatříme-li náš dokument interní deklarací DTD, můžeme deklarační atribut v elementu root vynechat:

<?xml version="1.0"?>
<!DOCTYPE p:root [
<!ELEMENT p:root (#PCDATA)>
<!ATTLIST p:root
    xmlns:p CDATA "http://gingerall.org/ns/example">
]>
<p:root>text</p:root>

Deklarace DTD nemusí nutně být součástí dokumentu XML, který popisuje, ale může být uložena v samostatném souboru:

<?xml version="1.0"?>
<!DOCTYPE p:root SYSTEM "root.dtd">
<p:root>text</p:root>

<!-- soubor root.dtd -->
<!ELEMENT p:root (#PCDATA)>

<!ATTLIST p:root
    xmlns:p CDATA "http://gingerall.org/ns/example">

Všechny tři uvedené varianty jsou podle doporučení W3C (XML 1.0, Namespaces in XML 1.0) zcela v pořádku, ale přesto druhé dvě nelze s klidným svědomím doporučit. Problém je v tom, že definice DTD není povinnou součástí dokumentu. To je z mnoha důvodů dobře a je to jedno z podstatných zjednodušení oproti SGML, ale našem případě nám to může způsobit potíže. Kromě validujících parserů, které dokument vždy ověřují oproti příslušnému DTD a doplňují implicitní atributy, totiž existuje velká skupina parserů, jež DTD více či méně ignorují. Nevalidujících parserů je dnes dokonce pravděpodobně většina. Tyto parsery se často omezují na vyhodnocení entit a tím jejich práce s DTD končí. Načítání druhé a třetí varianty by nevalidující parser mohl ukončit chybovým hlášení o nedeklarovaném prefixu. Kvalitní nevalidující parsery (např. Expat) si sice dokáží poradit se všemi třemi variantami, ale kvůli přenositelnosti vaší aplikace XML je rozumnější na to nespoléhat.

Při pohledu na výše uvedené příklady jste si asi všimli další do očí bijící slabiny kombinace DTD a jmenných prostorů. Jména v DTD jsou kvalifikovaná, tedy včetně prefixu. Pokud byste se rozhodli použít v některé instanci dokumentu pro daný jmenný prostor jiný prefix, validace oproti DTD s původním prefixem se nemusí nepodařit (dobré parsery, jako je Expat, si s tím znovu poradí). To je rozpor s požadavkem na nevýznamovost prefixů svědčící o nedokonalé slučitelnosti převzatých definic DTD a později doplněných jmenných prostorů. Navíc existují validátory, které namísto kvalifikovaných jmen pracují pouze s lokálními jmény. Pak se vám může stát, že k validaci jednoho dokumentu budete potřebovat dvě verze DTD!

Pokud to jde, je lepší se kombinaci DTD a jmenných prostorů vyhýbat. Když není zbytí, rozhodně nikdy nesvěřujte deklarace prefixů implicitním atributům; jinak se můžete rozloučit s interoperabi­litou. Problém spolupráce DTD a jmenných prostorů se řešit nebude, protože definice DTD jsou považovány za zastaralé a na jejich místo se tlačí krásný nový (nejen) validační jazyk W3C XML Schema. WXS se jmennými prostory od začátku počítá, tudíž se problémům, které s nimi má DTD, elegantně vyhýbá a přináší své vlastní. Ale o tom až někdy přístě.

Našli jste v článku chybu?