# PB029: XML

XML (Extensible Markup Language) je textový značkovací jazyk, který byl vyvinut jako zjednodušení principielně obdobného, ale mnohem složitějšího značkovacího jazyka SGML.

XML je metajazyk určený k vytváření značkovacích jazyků pro konkrétní použití (jedním z takových jazyků je např. XHTML). Slouží k textové a člověkem čitelné serializaci dat. (V tomto ohledu v dnešní době soupeří s dalšími standardy, zejména s jazykem JSON.)

Díky standardizaci a široké podpoře v programovacích jazycích a nástrojích pro vývojáře je XML hojně využívaným jazykem pro výměnu dat ve strojově zpracovatelné podobě s výhodou jejich čitelnosti člověkem v prostém textovém editoru.

## Vlastní XML jazyk

Využití XML pro definici vlastního jazyka si můžeme ukázat na příkladu jednoduchého katalogu software.

Představme si situaci, kdy si chceme vést evidenci o software, který používáme na svých osobních počítačích. Budeme si proto vytvářet jednoduchý katalog takového software v XML formátu. V tomto katalogu chceme pro každý produkt uchovávat název programu, informaci o instalačním souboru a jeho verzi, odkaz na domovskou stránku výrobce a krátký popis. V případě některých produktů se celá instalační sada může skládat z více částí (např. program a dodatečné pluginy). V našem katalogu chceme proto mít možnost popsat i tuto situaci.

Příklad takového katalogu v XML si můžete prohlédnout v souboru `programy.xml`.

## Formální definice XML jazyka

Značkování v našem souboru `programy.xml` jsme si stanovili sami. Nikomu (možná krom autora souboru `programy.xml`) proto nemůže být zřejmé, jak přesně je dané značkování definováno. (Je uvedení odkazu na domovskou stránku povinné? Je povolené uvádět uživatelské hodnocení daného produktu? Je možné elementy `program-group` zanořovat více než jednou do sebe?) Na druhou stranu jsme díky textové reprezentaci i bez jakékoliv předchozí znalosti daného jazyka schopni odhadnout význam dat v souboru obsažených.

Bez přesné definice daného značkování (našeho XML jazyka) nejsme schopni naznačkovaná data dále automatizovaně zpracovávat. Nejsme schopni provést import dat do databáze (nevíme, jaká data v jakých elementech můžeme očekávat), univerzálně definovat převod libovolného katalogu software v tomto značkovaní na HTML stránku ani bezpečně exportovat data z našeho systému (existuje například omezení na maximální povolenou délku popisu?) atd.

Uvedené problémy řeší formální definice XML jazyka. Existuje několik standardů, které se pro definici XML jazyků používají. Historicky nejstarší je Document Type Definition (DTD). Tip: DTD se hojně využívá u (X)HTML. Pokud si zobrazíte zdrojový kód této webové stránky, uvidíte odkaz na DTD na jejím druhém řádku těsně za XML prologem. Dalšími možnostmi jsou např. RELAX NG, Schematron, anebo hojně užívané a velmi mocné XML Schema.

Formální definice našeho XML jazyka užitého v `programy.xml` v jazyce XML Schema je k dispozici v souboru `seznam-software.xsd`. Z uvedené definice je zřejmé mimo jiné to, že uvedení odkazu na domovskou stránku není povinné, není povolené uvádět uživatelské hodnocení daného produktu („hvězdičky“), elementy `program-group` je možné neomezeně zanořovat do sebe a neexistuje omezení na maximální povolenou délku popisu.

### Validace

Výhodou striktních syntaktických požadavků XML a existence formální definice jazyka je, že dokumenty v takovém značkování můžeme bezpečně algoritmicky zpracovávat.

Nejzákladnější syntaktické požadavky na každý XML dokument vychází přímo ze syntaktických požadavků XML. XML dokument je dobře utvořený (well formed), pokud neobsahuje neuzavřené elementy, neobsahuje překřížené elementy, má právě jeden kořenový element atd.

Kontrolu, zda je libovolný XML dobře utvořený, můžeme provést např. nástrojem `xmllint`: `xmllint --noout programy.xml` Takovou kontrolu můžeme provést na libovolném XML dokumentu, není k ní třeba žádná formální definice použitého XML jazyka, neboť se kontroluje pouze základní XML syntaxe, nikoliv formát kódovaných dat. Pokud dokument není well formed, žádná aplikace nesmí pokračovat v jeho dalším zpracování a musí ohlásit chybu.

Tip: Parametr `--noout` zajistí, že `xmllint` vypisuje pouze chyby. Pokud tedy po spuštění příkazu program bez jakéhokoliv hlášení skončí, znamená to, že žádné chyby nebyly v dokumentu nalezeny.

Pokud chcete výsledek kontroly testovat automatizovaně např. ve skriptu, můžete kontrolovat návratovou hodnotu vrácenou programem při jeho ukončení: `$ xmllint --noout programy.xml
$ echo $?
0` Hodnota `0` znamená úspěšnou kontrolu bez nalezených chyb, nenulové hodnoty indikují výskyt různých typů chyb (viz manuálová stránka programu: `man xmllint`).

Pokud dokument chyby obsahuje, jsou vypsány. Vyzkoušejte si toto chování úmyslným zanesením chyby do dokumentu (např. smazáním uzavírací značky některého elementu apod.).

Pokud je k dispozici formální definice použitého jazyka, je na vstupním dokumentu, který o sobě tvrdí, že obsahuje značkování v daném jazyce, možné provést validaci, tzn. kontrolu shody obsahu dokumentu s definicí daného jazyka. Při použití definice v jazyce XML Schema můžeme opět použít např. nástroj `xmllint`: `xmllint --noout --schema seznam-software.xsd programy.xml`

Tip: Rozdíl mezi kontrolou dobrého utvoření XML dokumentu a validací dle formální definice jazyka si můžete snadno vyzkoušet: Přidejte do dokumentu `programy.xml` nějaký vlastní element, který není součástí jazyka definovaného schématem `seznam-software.xsd`, ale zároveň nebude porušovat syntaktická pravidla XML. Následně zkuste upravený dokument zkontrolovat na správnost utvoření i validitu vůči schématu `seznam-software.xsd`.

Tip: Nástroj `xmllint` podporuje pouze jazyk XML Schema 1.0. Pro využití jazyka XML Schema 1.1 můžete využít nástroj Apache Xerces2-J.

Pokud je vstupní dokument dobře utvořený (well formed) a validní, můžeme jej bezpečně automaticky zpracovávat – máme jistotu, že přesně známe formát dat, která se v takovém dokumentu mohou vyskytnout, a zpracovávající software by na ně tedy měl být plně připraven.

## Stylování XML dokumentů

XML jazyky slouží k předávání dat ve strojově zpracovatelném formátu. Často však může být užitečné definovat způsob, jakým se XML dokument vykreslí při zobrazení ve webovém prohlížeči.

Pokud si v prohlížeči otevřeme soubor `programy.xml`, zobrazí se nám pouze zdrojový kód příslušného XML dokumentu. Pokud si však vytvoříme CSS stylopis a k XML dokumentu jej připojíme, vyobrazí se nám dokument v moderních prohlížečích jako běžná webová stránka.

Stylování XML dokumentů ilustruje CSS stylopis `seznam-software.css`, který je určený pro libovolný XML dokument v jazyce definovaném XML schématem `seznam-software.xsd`. Ukázkový výsledek je možné si prohlédnout na souboru `programy-s-css.xml`, který je krom přidání odkazu na CSS stylopis shodný s dokumentem `programy.xml`:

    1 --- programy.xml        2015-10-30 15:23:16.521464364 +0200
    2 +++ programy-s-css.xml  2015-10-30 15:25:43.325325463 +0200
    3 @@ -1,4 +1,5 @@
    4  <?xml version="1.0" encoding="UTF-8"?>
    5 +<?xml-stylesheet type="text/css" href="seznam-software.css"?>
    6  <programs title="Programy"
    7            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    8            xsi:noNamespaceSchemaLocation="seznam-software.xsd">

## XML transformace

Stylování pomocí jazyka CSS je užitečné, ale často nedostačující. V rámci stylopisu například nemůžeme do výsledné stránky dodat další navigační a strukturní prvky ani data jinak předzpracovat ze strojové do lidsky čitelné podoby. Mnohdy proto potřebujeme silnější transformační mechanismus.

Jednou z možností, jak transformovat data ve formátu XML, jsou stylopisy v jazyce XSLT. XSLT je deklarativní programovací jazyk, který popisuje převod z jednoho XML jazyka buďto do XML jazyka jiného, nebo do libovolného jiného textového formátu, jako je HTML, LaTeX, apod.

Libovolný XML dokument v jazyce definovaném XML schématem `seznam-software.xsd` můžeme převést do HTML pomocí XSLT stylopisu `seznam-software-do-html.xsl`. Vyzkoušet si to můžeme na našem dokumentu `programy.xml` pomocí XSLT procesoru `xsltproc`: `xsltproc --output programy.html seznam-software-do-html.xsl programy.xml` Informace obsažené v XML dokumentu tak mohou být přímo vizuálně prezentovány čtenáři ve webovém prohlížeči otevřením HTML stránky `programy.html`.

Tip: Procesor `xsltproc` podporuje pouze jazyk XSLT 1.0. Pro využití jazyka XSLT 2.0 a XSLT 3.0 můžete využít procesor Saxon-HE.

XSLT stylopis můžeme odkazovat přímo z XML dokumentu. Některé webové prohlížeče pak při otevření takového XML dokumentu nezobrazí samotná XML data, ale přímo výslednou HTML stránku, která je výsledkem XSLT transformace daným stylopisem. Vyzkoušet si to můžete na souboru `programy-s-xsl.xml`, který je krom přidání odkazu na XSLT stylopis shodný s dokumentem `programy.xml`:

    1 --- programy.xml        2014-10-20 00:38:11.211197875 +0200
    2 +++ programy-s-xsl.xml  2014-10-20 00:38:17.135173512 +0200
    3 @@ -1,4 +1,5 @@
    4  <?xml version="1.0" encoding="UTF-8"?>
    5 +<?xml-stylesheet type="text/xsl" href="seznam-software-do-html.xsl"?>
    6  <programs title="Programy"
    7            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    8            xsi:noNamespaceSchemaLocation="seznam-software.xsd">

## Praktické úkoly k procvičení

1. Přidejte si do `programy.xml` další položku `<program>…</program>` s popisem nějakého svého oblíbeného programu.
   - Ověřte, že je dokument po úpravě stále validní.
   - Prohlédněte si novou podobu dokumentu po transformaci do HTML.
2. Rozšiřte definici jazyka `seznam-software.xsd` o nový podelement elementu `program`, který se bude jmenovat `user-rating`, bude nepovinný, neopakovatelný, a povolenou hodnotou bude celé číslo od nuly do pěti (tzn. hodnocení „nula až pět hvězdiček“).
   - Přidejte nově definovaný element k jednomu nebo více záznamům ve vašem katalogu software `programy.xml`.
   - Ověřte, že je dokument po úpravě stále validní.
3. Rozšiřte ukázkovou XML transformaci v souboru `seznam-software-do-html.xsl` o podporu nově definovaného elementu `user-rating`.
   - [do výšky 2 bonusových bodů dle chytrosti řešení] Hodnocení uvedené ve vstupním XML dokumentu je možné reprezentovat i jinak než prostým výpisem čísla uvedeného přímo v XML. Může být reprezentováno např. graficky opakovaným výpisem symbolů „★“ a „☆“ (např. tedy „★★★☆☆“ pro hodnocení 3) apod.
4. [za 3 bonusové body] Vytvořte vlastní předpis XML transformace, která libovolný dokument v XML jazyce definovaném XML schématem `seznam-software.xsd` převede do jazyka LaTeX.
   - Z důvodu lepší podpory Unicode je vhodné vytvářet zdrojový text pro sazbu XeLaTeXem/LuaLaTeXem.
   - Symboly hvězdiček naleznete např. v LaTeXovém balíčku `pifont`.
   - Výslednou transformaci aplikujte na svůj dokument `programy.xml` a získaný zdrojový text přeložte TeXem.