Potřebujete pomoci s XML schématy?
Nabízím školení, konzultace, vývoj schémat na zakázku. Nevájte a kontaktujte mne.

Podpořte provoz stránek
Platba probíhá pomocí služby PayPal a je možné platit kartou nebo převodem z vašeho PayPal účtu.

Kapitola 7. Best-practices pro návrh schémat

7.1. Elementy nebo atributy
7.2. Jmenné prostory
7.3. Názvy elementů a atributů
7.4. Defaultní a fixní hodnoty
7.5. Verzování schémat
7.6. Rozšiřitelnost schémat

V následující části se podíváme na některá pravidla získaná praktickým používáním schémat. Tato pravidla nemusí platit ve všech případech, ale ve většině případů se vám rozhodně vyplatí se jimi řídit.

7.1 Elementy nebo atributy

Ve všech případech je možné atribut nahradit vnořeným podelementem. Mohlo by se proto zdát, že atributy jsou v XML zcela zbytečné. Nicméně existují dva případy, kdy se jejich použití může hodit:

  • Potřeba kompaktního zápisu – hodnota atributu je uzavřená v uvozovkách nebo apostrofech, není potřeba ji uzavírat koncovým tagem. Ve většině případů je tak zapsání atributu podstatně kratší. To může mít význam při návrhu schémat pro dokumenty, které se budou editovat především ručně bez použití nějakých speciálních XML editorů. Na druhou stranu je pravda, že bychom se při návrhu schématu neměli nechat příliš omezovat požadavky kladenými nějakou nedostatečnou aplikací. Aplikace se mění a data v XML zůstávají – návrh dobrého formátu by proto měl mít přednost.

  • Zjednodušení modelu obsahu – atributy se ve schémových jazycích jako WXS nebo DTD definují odděleně od podelementů. V některých případech by proto přesunutí atributu do podelementu mohlo vést k nutnosti rozvolnit stávající model obsahu a výsledkem by bylo schéma, které by bylo volnější než jsme původně zamýšleli.

Jaká existují další pravidla? U jednoho elementu není možné mít dva atributy stejného jména. Z tohoto důvodu nejde do atributu ukládat hodnoty s opakovaným výskytem.

Hodnotu atributu také nejde dále strukturovat pomocí podelementů. Atributy se proto nehodí pro uchovávání hodnot, které je potřeba dále strukturovat nebo lze očekávat, že v budoucnosti potřeba dalšího strukturování vznikne. Potřeba dalšího strukturování však hrozí u všech informací, které mohou obsahovat volný text. Nikdy nevíme, kdy náš formát dat začnou používat třeba v Japonsku nebo v Izraeli. Do japonského textu se však poměrně často vkládají tzv. Ruby anotace, které slouží k zápisu alternativy nějakého textu v jednodušší slabikové abecedě nebo v latince. Podobně, při kombinaci anglického textu s hebrejským je potřeba pomocí elementu označit, který text je anglicky a který hebrejský, aby se při zobrazování mohl správně změnit směr sazby textu.

Například v japonštině se Tokyo v písmu kanji zapíše jako 東京. U méně obvyklých slov se však nad kanji zápis často zapisuje i výslovnost pomocí slabikové abecedy hiragana:

text anotace Ruby →とうきょう 
základní text → 

Je jasné, že text s anotací nejde reprezentovat prostým řetězcem, ale je k tomu potřeba struktura elementů. Naše ukázka by se pomocí značkování Ruby zapsala jako:

<ruby>
  <rb></rb>
  <rt>とう</rt>
  <rb></rb>
  <rt>きょう</rt>
</ruby>

Docházíme tedy k závěru, že do atributů je vhodné ukládat pouze hodnoty, u kterých dopředu známe obor hodnot a tento obor je poměrně omezený. Do této kategorie spadají například čísla, data nebo textové hodnoty, pro které máme číselník (např. kódy měn apod.).

7.2 Jmenné prostory

Každý nově navržený XML formát by měl definovat elementy ve vlastním jmenném prostoru. Elementy, které nepatří do jmenného prostoru nejde snadno a jednoznačně kombinovat v jednom dokumentu s jinými elementy. Uzavíráme si tak do budoucna cestu pro využití našeho formátu způsoby, které si dnes ještě ani nedovedeme představit.

Do jmenného prostoru by měly patřit všechny elementy, jejich atributy bychom přitom do jmenného prostoru zařazovat neměli. To znamená, že v WXS použijeme atribut targetNamespace a atribut elementFormDefault nastavíme na hodnotu qualified (viz 3.5 – „Jmenné prostory“). V RELAX NG se přiřazení jmenného prostoru provádí atributem ns (viz 4.5 – „Jmenné prostory“).

Otázkou zůstává, jak správně zvolit název jmenného prostoru pro nově vytvářené schéma. Vhodné je, aby byl název intuitivní, snadno zapamatovatelný a navržený tak, aby vás neomezil do budoucna. Název jmenného prostoru musí mít tvar URI adresy a dnes se běžně používají jak URN tak URL. Nejde jednoznačně říci, která z těchto variant je lepší.

Při používání URN musíme použít buď experimentální prostor začínající písmenem x nebo jej odvodit z doménového jména. Například já, jako vlastník domény kosek.cz, bych mohl používat URN začínající na:

urn:x-traktor:…
urn:x-test:…
urn:cz-kosek:…

Další část URN by měla naznačit, že URI se používá jako identifikátor jmenného prostoru (použitím slova jako je ns nebo namespace) a identifikovat jméno schématu. Následuje ukázka několika existujících i smyšlených jmenných prostorů, která využívají URN:

urn:oasis:names:tc:entity:xmlns:xml:catalog 
urn:oasis:names:specification:ubl:schema:xsd:DocumentStatusCode-1.0 
urn:x-test:ns:faktura
urn:x-test:namespace:faktura
urn:cz-kosek:ns:kalendar

Stále častější bývá používání URL jako názvů jmenných prostorů. Jejich výhoda spočívá v tom, že na jejich adresu lze umístit dokumentaci schématu a odkazy na související dokumenty. Nevýhodu lze zase spatřovat v tom, že začínající uživatelé XML jsou poněkud zmateni tím, že název jmenného prostoru je jen identifikátor a že se při zpracování dokumentu nečtou žádná data z URL adresy odpovídající názvu jmenného prostoru.

Rozhodneme-li se používat pro názvy jmenných prostorů URL, musíme je obzvláště pečlivě navrhnout, aby nekolidovaly s adresami používanými pro dokumenty umístěnými na webovém serveru. Obvykle se to řeší tak, že hned první část cesty v URL obsahuje slovo ns nebo namespace a tyto URL adresy jsou vyhrazeny pro tvorbu jmenných prostorů:

http://docbook.org/ns/docbook
http://relaxng.org/ns/structure/1.0 
http://obix.com/ns/module/version 
http://kosek.cz/namespace/kalendar

Někdy může být užitečné do URL zabudovat i číslo roku, aby se v budoucnu dal prostor URL rozšiřovat. Tento přístup využívají například jmenné prostory W3C:

http://www.w3.org/1999/xhtml
http://www.w3.org/1999/XSL/Transform
http://www.w3.org/2001/XMLSchema

Na adresu jmenného prostoru pak bývá vhodné umístit HTML stránku (nebo ještě lépe dokument RDDL), která stručně popíše jmenný prostor, odkáže na dokumentaci jeho elementů a případně i na odpovídající schéma, existuje-li. Dokument bychom měli vystavit už z toho důvodu, že většina méně znalých se bude snažit psát adresu jmenného prostoru do prohlížeče, protože bude vypadat jako obyčejné URL.

7.3 Názvy elementů a atributů

Volbě názvu elementů a atributů je dobré věnovat zvýšenou pozornost, protože přispějí ke srozumitelnosti a použitelnosti schématu. Rozhodně není vhodné používat nesrozumitelné a kryptické názvy elementů jako A01, A02, … A72, byť by se třeba takto jednotlivé pole jmenovaly v nějakém starším formátu, ze kterého se přechází na XML. Ve starších formátech je toto pojmenování většinou dáno technickými omezení doby a zvolené technologie pro ukládání dat. Potřebujeme-li z důvodů zpětné kompatibility zachovat původní jména, můžeme je uložit do atributů s fixní hodnotou ve schématu nebo si mapování uložit v nějaké externí mapovací tabulce (která samozřejmě může mít podobu dokumentu XML, aby šla snadno použít např. při zpracování dokumentů pomocí XSLT).

Na druhou stranu bychom se samozřejmě měli vyvarovat i opačných extrémů, jako je element s názvem SPZneboRegistračníZnačkaMotorovéhoVozidla.

Název by měl být samopopisný v jeho kontextu, ale neměl by být na druhou stranu příliš dlouhý. U víceslovných názvů je dobré jednotlivá slova oddělit např. změnou velikosti písma, nebo vložením pomlčky či podtržítka. Např.: JednotkováCena, jednotkováCena nebo jednotková_cena. Důležité je rozhodnout se pro jednu konvenci a tu pak konzistentně používat. V opačném případě budou autoři vytvářející dokumenty podle vašeho schématu zmatení.

7.4 Defaultní a fixní hodnoty

Většina schémových jazyků umožňuje pro atributy (a někdy i pro elementy) určit implicitní hodnotu, která se atributu/elementu přiřadí, není-li atribut/element v dokumentu uveden. Používání této vlastnosti se v poslední době nedoporučuje, protože dokument pak obsahuje jiné informace, když je zpracován se schématem, a bez schématu.

7.5 Verzování schémat

Ve většině případů není schéma statický dokument, který jednou vznikne a už se dále nemění. Budoucnost obvykle přináší nové požadavky, pro které je nutné schéma upravit. Dnes se nejčastěji používá následující přístup.

Verze schématu se uvádí v atributu version u kořenového elementu dokumentu. S každým novou verzí schématu se toto číslo zvyšuje. Dojde-li pak ve schématu k radikální změně – změna názvu elementů, změna struktury dokumentu – obvykle nová verze schématu používá jiný jmenný prostor, než ta předchozí. Je-li však změna zpětně kompatibilní – přidají se například jen nové nepovinné elementy – jmenný prostor se nemění. To umožňuje beze změny používat i starší aplikace na nové dokumenty.

7.6 Rozšiřitelnost schémat

Počítáme-li s tím, že se schéma bude dále vyvíjet, nebo že má smysl, aby se dokumentu vkládaly i jiné elementy než definované ve schématu, je dobré je navrhnout jako otevřené. To znamená, že k libovolnému elementu dovoluje schéma přidat další podelementy.

Ve WXS se pro tuto definici používá element any. Jde u něj určit z jakého jmenného prostoru jsou elementy povoleny a kolik jich může být. Nejvolnější varianta je

<xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded"/>

která říká, že v daném místě se může vyskytovat libovolný počet elementů z libovolného jmenného prostoru. Kromě ##any můžeme použít ještě identifikátory ##targetNamespace pro aktuální cílový jmenný prostor, ##other pro jakýkoliv jmenný prostor kromě cílového a pak jde samozřejmě zadat URI adresu nějakého konkrétního jmenného prostoru.

Pomocí atributu processContents ještě můžeme určit, jak se mají elementy popsané pomocí any validovat. Hodnota skip říká, že se elementy nebudou validovat, hodnota strict říká, že se musí validovat a konečně hodnota lax říká, že se validace provede v případě, že se pro elementy najde odpovídající schéma.

Vložení any alespoň na některá místa schématu podporuje rozšiřitelnost a je velmi žádoucí. Je však potřeba dávat pozor na to, aby před elementy definovanými pomocí any nebyly volitelné elementy (minOccurs="0"), protože pak schéma není jednoznačné. Například následující schéma tutu podmínku porušuje a není proto korektní:

w
x
s
<xs:element name="osoba"> <xs:complexType> <xs:sequence> <xs:element name="jmeno" type="xs:string"/> <xs:element name="email" type="xs:string" minOccurs="0"/> <xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element>

Problém je v tom, že při validaci dokumentu:

<osoba>
  <jmeno>Pepa</jmeno>
  <email>pepa@example.com</email>
</osoba>

nejde určit, zda se element email má validovat podle element nebo any. WXS je však navržené tak, aby vždy šlo instanci dokumentu jednoznačně mapovat na datové typy ve schématu – to je nesmírně důležité například při data-bindingu.

Podobně rozšiřitelně a navíc s mnohem méně omezeními lze schémata navrhovat v RELAX NG. Musíme si nejprve definovat vzor pro jakýkoliv i opakující se element a ten pak použít na odpovídajícím místě schématu.

r
n
g
<define name="anything"> <zeroOrMore> <choice> <element> <anyName/> <ref name="anything"/> </element> <attribute> <anyName/> <text/> </attribute> </choice> </zeroOrMore> </define>

Je zde použita speciální notace pro zápis jména elementu nebo atributu. Vzor anyName vyhoví jakémukoliv názvu. Jde jej kombinovat i se vzorem except a přesně určit jaké jmenné prostory jsou povolené a zakázané.

© Jiří Kosek 2014

Tento dokument je určen výhradně pro osobní potřebu seznámení se schémovými jazyky. Jakékoliv jiné použití, včetně dalšího šíření, pořizování kopií, použití při školeních a výuce apod. je výslovně zakázáno a bude považováno za porušení autorských práv.

Dokument je zkrácenou verzí školicích materiálů používaných během školení XML schémata. Školení se mj. věnuje i problematice data-bindingu a využití informací ze schématu uvnitř aplikací.


Copyright © 2003-2013 Jiří Kosek