XML API

Podpora XML v Javě a .NET

Jiří Kosek

Tento článek vyšel v časopise Softwarové noviny 4/2002 a 5/2002.


Obsah

Co potřebuje vývojář
Čtení a manipulace s XML dokumentem
Validace dokumentů
XSLT transformace
Java
JAXP
JDOM
DOM4J
Electric XML
.NET
XmlReader
DOM
XPath
XSLT
Validace
Práce se schématy
Kolik API umíš...

XML se již dávno dostalo z úst vizionářů do každodenně používaných aplikací. Vývojáři proto potřebují účinné nástroje pro zpracování XML dokumentů. V následujícím článku se proto podíváme, jak jsou na tom s podporou XML dvě nejperspektivnější vývojářské platformy – Java a .NET.

Poznámka

Všechny ukázkové příklady z článku si můžete stáhnout:

Co potřebuje vývojář

Čtení a manipulace s XML dokumentem

Nejčastěji prováděnou operací s XML dokumenty je jejich načítání. Každý si sice může napsat vlastní kód, který by znak po znaku četl data ze souboru a zkoumal, zda teď čteme atribut nebo element, nebo zda jsme narazili na XML komentář. Metoda je to vhodná pro masochisty, ostatní sáhnou po hotových knihovnách, které usnadňují čtení XML dokumentů. Zažitý název pro tyto knihovny je parser.

Parser čte XML dokument ze souboru (nebo z jiného zdroje – např. z webového serveru přes HTTP protokol) a stará se o nízkoúrovňovou syntaktickou analýzu XML dokumentu – za menšítkem (<) očekává název elementu, extrahuje hodnotu atributu uzavřeného v uvozovkách nebo apostrofech apod. Přes programátorské rozhraní pak parser nabízí abstraktní model XML dokumentu – tzv. infoset. Infoset již neoperuje s jednotlivými znaky v souboru, ale s elementy, atributy, textovým obsahem elementů apod. Parser nás tak ušetří té nejméně zajímavé práce.

Samotný XML dokument resp. jeho infoset nám může být nabízen několika způsoby a historicky se proto vyvinulo několik různých API, které se hodí pro různé aplikace.

Obrázek 1. Aplikace čte XML dokument přes rozhraní nabízené parserem

První parsery nabízely událostmi řízené rozhraní. Parser postupně četl XML dokument a volal naše funkce pro obsluhu důležitých událostí, jako začátek a konec elementu, textový obsah elementu apod. Funkci byly navíc předány další důležité parametry – například název elementu, seznam atributů apod.

Událostmi řízené zpracování XML dokumentu má dvě velké výhody – je rychlé a má malé paměťové nároky. V aplikacích, kde je hlavní důraz kladen na rychlost, se proto tento přístup používá nejčastěji. Nevýhodou je naopak nutnost zpracovat XML dokument během jednoho sekvenčního průchodu. Zejména začínající programátoři mají s touto technikou problémy – důležité informace si programátor musí pamatovat ve vlastních stavových proměnných apod.

Asi nejznámější rozhraní používající událostmi řízený přístup je SAX (Simple API for XML). Toto rozhraní vzniklo velmi rychle jako výsledek společného úsilí několika vývojářů z diskusního listu xml-dev. Původně byl SAX navržen pro Javu, ale existují jeho implementace pro mnoho dalších jazyků. V současné době se již používá novější verze rozhraní SAX2, která podporuje jmenné prostory a některé další užitečné vlastnosti.

Obrázek 2. Rozhraní SAX vyvolává událost pro každý důležitý prvek XML dokumentu

Pro práci programátora je mnohem pohodlnější, když může kdykoliv přistupovat k libovolné části XML dokumentu. Aby to bylo možné, je nutné načíst celý dokument do vhodné paměťové struktury. XML dokumenty a jejich strukturu lze velmi přirozeně modelovat pomocí stromu. Nejznámější rozhraní, které pracuje se stromovou reprezentací dokumentu, je DOM (Document Object Model). Toto rozhraní vytvořilo W3C konsorcium a je zcela nezávislé na použitém jazyku. XML dokument je zpřístupněn pomocí objektů, které zastupují jednotlivé důležité prvky – elementy, atributy, textový obsah, komentáře apod. Každý objekt odpovídá jednomu uzlu ve stromu XML dokumentu a nabízí metody pro zjištění jeho typu a hodnoty, jeho dětí a rodičů.

Strom dokumentu můžeme procházet libovolně a opakovaně. Díky tomu je zpracování XML dokumentu velmi jednoduché. Zaplatíme za to nižší rychlostí a velkou paměťovou náročností. Při načítání XML dokumentu do paměti musíme počítat s tím, že v paměti zabere dvakrát až desetkrát více prostoru než v souboru v závislosti na použité implementaci. U souborů s hodně elementy a atributy je navíc načtení dokumentu dost pomalé, protože pro každý element a atribut se vytváří v paměti objekt.

Obrázek 3. Rozhraní DOM reprezentuje XML dokument v paměti jako stromovou hierarchii objektů

Na rozdíl od rozhraní SAX sloužícího pouze pro čtení XML dokumentů, umožňuje DOM s reprezentací XML dokumentu v paměti manipulovat, můžeme dokonce vytvořit nový XML dokument přímo v paměti. Poněkud zarážející je, že současná verze DOMu nenabízí standardní metody pro načtení a uložení XML dokumentu, takže každý parser je musí řešit po svém. Tento nedostatek odstraňuje až právě připravovaná verze DOM3.

Rozhraní DOM má za sebou poměrně dlouhou historii sahající do poloviny 90. let minulého století. O DOM se poprvé hovořilo v souvislosti s JavaScriptem a jazykem HTML. JavaScript mohl přes rozhraní DOM pracovat s důležitými informacemi na stránce zobrazené ve webovém prohlížeči – přístupné byly např. obrázky, formuláře a rámy. Další rozvoj DOM vyústil až v dynamické HTML, které umožňuje vytvářet skutečně interaktivní stránky. Velkým problémem však byla (a bohužel stáje ještě trochu je) nekompatibilita DOM rozhraní v jednotlivých prohlížečích. W3C konsorcium proto toto rozhraní standardizovalo a vznikl tak DOM1, který ve skutečnosti obsahuje dvě velmi odlišná rozhraní. Jedno pro práci s HTML dokumenty a druhé pro zpracování XML – tzv. XML Core. Tato část rozhraní je pak podporována DOM XML parsery. Další verze rozhraní DOM2 přinesla zejména podporu jmenných prostorů. Navíc byla přidána další rozhraní, která umožnila mj. snazší průchod stromem dokumentu. Do té doby bylo nutné pro průchod stromem využívat nestandardní třídy (tzv. treewalkery) nebo si psát vlastní kód, který obvykle rekurzivně procházel strom.

DOM a SAX poskytují velmi komplexní podporu pro čtení XML dokumentů. Postupem času se však ukázalo, že pro typické úlohy je jejich použití zbytečně komplikované. Během necelých posledních dvou let se proto stále častěji objevují nová rozhraní nebo rozšíření těch stávajících, která mají jeden společný cíl – usnadnit programátorům práci s XML dokumenty. Autoři těchto nových přístupů mají na mysli zejména zkrácení doby nutné na naučení práce s novým rozhraním a na zkrácení délky kódu nutného pro provedení určité operace (což je ekvivalentní se zkrácením doby vývoje aplikace).

Po počátečním nadšení z rozhraní DOM většina vývojářů zjistí, že je poměrně pracné napsat kód, který zpracuje určité specifické části dokumentu. Přišlo se proto s možností položit nad DOM stromem jednoduchý dotaz, který vybere jen určité uzly stromu – tedy určité elementy, atributy či textové uzly. Jasným kandidátem na takový dotazovací jazyk je XPath (XML Path Language), který se používá v mnoha dalších XML standardech (XSLT, XML schémata, XPointer aj.). XPath umožňuje zadávat jednoduché dotazy, podobné cestě v adresářové struktuře disku, které vybírají části ze struktury XML dokumentu. (Podrobnější informace o XPathu jste se mohli dozvědět například v seriálu o XML, který vyšel v čísle SWN 8/2000.)

Zjednodušení se dočkaly i parsery, které pracují nad XML dokumentem sekvenčně. O parserech podporujících rozhraní SAX se někdy říká, že jsou to tzv. push parsery – tlačí do aplikace proud událostí odpovídající jednotlivým prvkům XML dokumentu. Tento na událostech postavený přístup není všem programátorům vlastní, a tak vznikly pull parsery. Mají všechny přednosti událostmi řízených parserů – rychlost a paměťovou nenáročnost – a navíc se s nimi velmi jednoduše pracuje. Programátor si podle potřeby říká o další a další části dokumentu a parser mu je postupně předává, dokud nedorazí na konec dokumentu.

Validace dokumentů

Většina parserů standardně pracuje v tzv. nevalidujícím režimu. Při čtení XML dokumentu je jen kontrolováno, zda je správně strukturovaný (well-formed). Tj. zda jsou dodržena základní syntaktická omezení jako spárované tagy, hodnoty atributů uzavřené v uvozovkách či apostrofech apod.

Pro každou třídu XML dokumentů však můžeme pomocí speciálního jazyka přesně formálně definovat jaké elementy lze v dokumentu použít, jaké mohou mít atributy a obsah. Těmto jazykům se říká jazyky pro definování schématu dokumentu. Nejznámější je bezesporu DTD. Postupem času vznikly i další, které nabízejí oproti DTD různá vylepšení (podporu jmenných prostorů, datových typů apod.) – např. XML schémata nebo Relax NG.

Pokud máme k dokumentu schéma, může parser během čtení kontrolovat, zda dokument schématu vyhovuje. Provádí pak tzv. validaci. Validující parser je samozřejmě pomalejší než nevalidující, na druhou stranu pak naše aplikace nemusí testovat tolik chybových stavů v XML dokumentech – ty zachytí parser při validaci.

Většina parserů je schopná pracovat i ve validujícím režimu a kontrolovat dokumenty oproti DTD. Postupně přibývají i parsery s podporou XML schémat a dalších jazyků.

Obrázek 4. Pokud dokument používá DTD nebo XML schéma, může parser před vytvořením infosetu provést validaci

Běžné parsery zpřístupňují XML dokument v podobě jeho infosetu. V této reprezentaci jsou všechny hodnoty v dokumentu chápány jako textové řetězce. Pokud však k dokumentu existuje XML schéma, může parser během validace přiřadit jednotlivým částem XML dokumentu jejich datový typ – číslo, řetězec, logická hodnota, datum apod. Získáme tak PSVI (Post-Schema Validation Infoset) – infoset zvalidovaný oproti schématu. Aplikace se pak nemusí starat o typovou konverzi netextových dat – práci už udělal parser.

Obrázek 5. Potřebujeme-li znát datové typy jednotlivých elementů a atributů, použijeme API zpřístupňující PSVI

Existence schématu má ještě jednu výhodu. Můžeme z něj vygenerovat sadu tříd, které dokáží reprezentovat XML dokument. Nemusíme pak s dokumentem manipulovat pomocí poněkud abstraktního rozhraní DOM, ale použijeme speciální jednoúčelové rozhraní, kdy se jednotlivé elementy a atributy namapují do paměťových objektů s odpovídajícím názvem. Tento přístup se hodí zejména pro dokumenty s plošší, datově orientovanou strukturou. Nejčastěji se s ním setkáte pod názvem data-binding nebo generátor tříd (class generator).

XSLT transformace

Výše zmíněná rozhraní a parsery nám umožňují celkem pohodlně číst a ukládat XML dokumenty. Samotnou logiku zpracování dokumentu si však musíme vždy napsat sami. Častou operací při zpracování XML dokumentů je transformace XML do dalšího formátu. Tím může být například HTML, když chceme XML dokument zobrazit v prohlížeči, nebo XML s jinou strukturou, když potřebujeme propojit dva systémy s odlišným formátem XML zpráv. Existuje proto speciální jazyk XSLT, který umožňuje poměrně jednoduše pomocí šablon popsat transformaci XML dokumentu do HTML, XML nebo čistého textu.

Protože primárním cílem při návrhu XSLT byla konverze do HTML pro snadné zobrazení XML dokumentů, říká se programu v XSLT často styl, protože definuje zobrazení XML dokumentu pomocí převodu do HTML.

XSLT transformaci můžeme provádět pomocí programu, který se jmenuje XSLT procesor. K dispozici může být podobně jako parser v podobě programátorské knihovny.

© Jiří Kosek 2002