XPath je jazykem, který stojí jaksi na pozadí téměř veškeré práce s XML. Znalost XPath není úplně triviální, přesto je často považován za samozřejmost. Pokud vám tento jazyk prozatím nic neříká a chcete to napravit, je tento článek určen právě vám.

Zjednodušeně řečeno, XPath především umožňuje vyjádřit relativní cestu od nějakého XML uzlu k jinému elementu nebo atributu. Umí toho mnohem více, ale toto je jeho nejdůležitější poslání. Může tedy připomínat například adresářové cesty v souborových systémech, ovšem je zde podstatný rozdíl – výsledek XPath výrazu (nebo jeho části) může obsahovat jeden, více nebo žádný XML element nebo atribut. Může dokonce obsahovat i jiné datové typy. Je tedy mnohem variabilnější, což je třeba si neustále uvědomovat. Pokud vám označení „jazyk“ pro XPath připadá přehnaný, snad změníte názor, až se dozvíte o všech možnostech, které nabízí.

XPath se využívá při práci s XML velmi hojně, vlastně všude, kde je třeba vyhledávat ve struktuře XML dokumentu určité data. Chceme-li vybrat určitou množinu dat, odpovídajících zadaným podmínkám, obvykle nám postačuje jediný XPath výraz a XML parser se o prohledání dokumentu a vyhodnocení podmínek postará sám. Takovéto vyhledávání dat je výborně využitelné také v XSL transformacích.

Velmi užitečný nástroj pro ladění XPath výrazů je XPath Expression Builder. Uložte si ho na disk (lokální kopie) a pak otevřete. Budete moci vyzkoušet XPath výrazy na libovolném vlastním XML dokumentu. Kliknutím na libovolný element si určíte výchozí pozici (budeme jí říkat aktuální element) a pak můžete zkoušet různé XPath výrazy. Výsledné uzly se vám budou zvýrazňovat. Můžeme testovat na tomto jednoduchém dokumentu:

<anketa>
  <otazka>Kolik hodin strávíte denně u počítače?</otazka>
  <moznosti>
    <moznost hlasu=’12‘>12-15 hodin</moznost>
    <moznost hlasu=’5′>15-20 hodin</moznost>
    <moznost hlasu=’15‘>20-24 hodin</moznost>
    <moznost hlasu=’10‘>Můj počítač nefunguje</moznost>
  </moznosti>
</anketa>

Složky XPath výrazu

Nejdůležitější konstrukcí jazyka XPath je zřejmě cesta k XML uzlu (Location Path). Jejím vytvářením se zde budeme zabývat nejvíce. Cesta obsahuje několik kroků, přičemž každý z nich sestává z identifikátoru osy, testu uzlu a podmínky (predikátu). Povinný je ale pouze test uzlu. Jednotlivé kroky XPath výrazu se pak spojují lomítky, vyhodnocují se zleva doprava a vždy se vychází z předchozích výsledků. Na začátku zpracování celého výrazu se vychází z aktuálního uzlu. Výsledkem může být libovolný typ uzlu, tedy nejen element nebo atribut, ale třeba i textový uzel.

Vyhodnocení každého kroku si probereme nejdříve poněkud abstraktně, ale až uvidíte konkrétní příklady, princip snadno pochopíte. Nejdříve se podle identifikátoru osy určí uzly, které se budou v tomto kroku výrazu zpracovávat. Dle výchozí osy (child::) jsou to podřízené uzly aktuálního uzlu, což je asi nejběžnější a nejlogičtější přístup. Množina vybraných uzlů se omezí podle testu uzlu, kterým může být třeba název elementu. A nakonec se ještě zohlední případné dodatečné podmínky. Uzly, které v tomto procesu obstály, postupují do dalšího kroku. Ten se pak bude vyhodnocovat postupně pro všechny uzly, které do něj postoupily. Zní to možná složitě, ale výrazy mohou být poměrně jednoduché a přitom velice silné.

Pojďme se tedy podívat na jednotlivé lexikální prvky cesty XPath. Výklad bude doprovázen tabulkami s ukázkami XPath výrazů, které si můžete ihned vyzkoušet. Občas je v některém výrazu použit prvek, který bude popsán až později, snad to nebude moc vadit.

Oddělování kroků

Nejdříve si ukážeme oddělování jednotlivých kroků cesty a způsob zápisu absolutních cest.

Lomítko (/)

Stejně jako u adresářové struktury, jednotlivé kroky v XPath cestě lze oddělovat lomítky. Pokud je lomítko na začátku výrazu, znamená to, že výraz není vztažen k aktuálnímu elementu, ale počítá se od kořene dokumentu.

Výraz Aktuální uzel Vyhodnocení
moznosti/moznost anketa Všechny elementy moznost, které jsou přímými potomky elementů moznosti, obsažených v elementu anketa.
/anketa jakýkoli Kořenový element dokumentu.

Dvě lomítka (//)

Dvě lomítka bezprostředně za sebou slouží k překonání víceúrovňové struktury. Pokud jsou dvě lomítka na začátku výrazu, opět se jedná o absolutní cestu od kořene dokumentu, takže lze snadno vybrat libovolný element odkudkoli. Více vám vysvětlí příklady:

Výraz Aktuální uzel Vyhodnocení
anketa//moznost kořen dokumentu Funguje, i když elementy moznost nejsou přímými potomky elementu anketa.
//moznost jakýkoli uzel Vrací všechny elementy daného jména v jakémkoli kontextu.
//* jakýkoli uzel Všechny elementy XML dokumentu.

Identifikátory osy

Testu uzlu může předcházet takzvaný identifikátor osy. Ten vlastně určuje směr procházení XML dokumentu, tedy říká, odkud se uzly k vyhodnocení budou vytahovat. Pokud identifikátor osy neuvedeme, použije se child::, dále tedy postupují potomci aktuálního uzlu. Všechno ale může být úplně naopak a ještě k tomu naruby, jak se dozvíte v následujícím přehledu všech identifikátorů osy:

Identifikátor Vyhodnocené uzly
child:: Přímí potomci aktuálního uzlu.
descendand:: Všichni potomci aktuálního uzlu.
descendand-or-self:: Aktuální uzel a všichni potomci.
self:: Aktuální uzel.
ancestor-or-self:: Aktuální uzel a všichni jeho předci.
ancestor:: Všichni předci aktuálního uzlu.
parent:: Rodič aktuálního uzlu.
following:: Všechny uzly, které se v toku XML dokumentu nacházejí za aktuálním uzlem.
preceding:: Všechny uzly, které se v toku XML dokumentu nacházejí před aktuálním uzlem.
following-sibling:: Všichni následující sourozenci aktuálního uzlu.
preceding-sibling:: Všichni předcházející sourozenci aktuálního uzlu.
attribute:: Atributy aktuálního uzlu.
namespace:: Deklarované jmenné prostory.

Pokud vám to připadá složité, nic si z toho nedělejte a prozatím berte v úvahu pouze výchozí typ osy child. Uvědomte si, že za postupné procházení strukturou dokumentu nemohou lomítka, ale právě osa. Pomůže vám to pochopit celou problematiku.

Testy uzlu

Jak již bylo řečeno, test uzlu dále vymezuje množinu uzlů, která byla určena identifikátorem osy. Jejich používání je velice jednoduché.

Uzel určený názvem

Je to jeden z nejzákladnějších testů uzlu. Vybere všechny XML elementy s daným názvem. Tento test zapíšeme jednoduchým zápisem testovaného názvu elementu.

Výraz Aktuální uzel Vyhodnocení
moznost moznosti Všechny podřízené elementy s daným názvem.
anketa kořen dokumentu Kořenový element dokumentu.

Uzel určený typem

Tento test uzlu bere ohled na typ uzlu, a vybírá pouze určitý typ. Tento test se zapisuje typem uzlu následovaným prázdnými kulatými závorkami. Máme tyto možnosti: comment(), text(), processing-instruction() a node().

Výraz Aktuální uzel Vyhodnocení
//text() jakýkoli element Vybere všechny textové uzly v dokumentu.

Podmínky ([])

Do hranatých závorek se zapisují další podmínky, které zužují výsledky předchozího vyhodnocení. Pokud místo podmínky napíšeme pouze číslo, vybere podmínka pouze uzel umístěný na pozici s daným pořadovým číslem.

Výraz Aktuální uzel Vyhodnocení
//moznost[@hlasu="5"] jakýkoli element Všechny elementy moznost, jejichž atribut hlasu má hodnotu rovnou 5.
*[2] jakýkoli element V pořadí druhý element podřízený aktuálnímu.

Zkracování syntaxe

Protože některé konstrukce se používají velice často, existují pro ně zkrácené tvary. Doporučuji je používat, mimo jiné zvyšují přehlednost celého výrazu.

Hvězdička (*)

Hvězdička použitá jako test uzlu vybírá všechny poskytnuté elementy.

Výraz Aktuální uzel Vyhodnocení
* kořen dokumentu Kořenový element dokumentu.
anketa/* kořen dokumentu Všechny elementy podřízené kořenovému elementu anketa.

Tečka (.)

Tečka nahrazuje odkaz na sebe sama, což se někdy může hodit. Je vlastně náhražkou celého kroku, takže k němu již nelze připojit podmínky.

Výraz Aktuální uzel Vyhodnocení
. jakýkoli uzel Aktuální uzel.
./* jakýkoli uzel Má úplně stejný význam jako jen *, tedy vrací všechny podřízené elementy.

Dvě tečky (..)

Dvě tečky (stejně jako v adresářové cestě) umožní pohyb o jednu úroveň výše. Opět nahrazuje jeden celý krok, který lze česky vyjádřit jako rodič aktuálního uzlu.

Výraz Aktuální uzel Vyhodnocení
.. anketa Vrací kořen dokumentu.
../* jakýkoli uzel Vybere všechny sourozence aktuálního elementu včetně jeho samotného.

Zavináč (@)

Zavináč nahrazuje identifikátor osy attribute::. Jako test uzlu pak obvykle poslouží název atributu.

Výraz Aktuální uzel Vyhodnocení
@* jakýkoli element Všechny atributy aktuálního elementu.
//@hlasu jakýkoli element Všechny atributy hlasu v celém dokumentu.
//@hlasu/.. jakýkoli element Všechny nadřízené elementy k těmto atributům. Lze tak zjistit všechny elementy obsahující daný atribut.

Operátory

V XPath se používají operátory obvyklé snad ve všech programovacích jazycích. Využívají se především v podmínkách. Pořadí vyhodnocení je možné upravovat závorkami.

Operátory Význam
| Sjednocuje výsledky více výrazů
+, -, *, div, mod Matematické operátory. Pro dělení se používá div, protože znaménko / slouží k jinému účelu (viz. výše).
=, !=, <, <=, >, >= Relační operátory. Význam je zřejmý.
and, or Logické operátory.

Funkce

XPath obsahuje celou řadu užitečných funkcí, které můžete využít hlavně při tvorbě podmínek. Pro přehled uvádím krátkou tabulku základních funkcí:

position(), last(), count()
Pořadové číslo aktuálního XML uzlu, pořadové číslo posledního uzlu a počet uzlů v daném kontextu.
name(), namespace-uri(), local-name()
Úplné kvalifikované jméno, název jmenného prostoru a lokální název aktuálního XML uzlu.
string(), number(), boolean()
Převede libovolný objekt na řetězcovou, číselnou a logickou hodnotu.
concat()
Spojí řetězce v parametrech.
starts-with(), contains(), substring-before(), substring-after(), substring(), string-length(), normalize-space(), translate()
Vysvětlení těchto řetězcových funkcí již přesahuje rozsah tohoto článku, zmiňuji se pouze proto, abyste věděli o jejich existenci.
floor(), ceiling(), round()
Zaokrouhlení čísla dolů, nahoru a na nejbližší celé číslo.
sum()
Objekty v parametru jsou zkonvertovány na čísla, a funkce vrátí jejich součet.
not(), true(), false()
Negace logického výrazu, logická jednička a logická nula.

V konkrétním prostředí (například XSLT) mohou být doplněny ještě další funkce, které zde uvedeny nejsou, popřípadě může existovat možnost si další funkce naprogramovat.

Složitější příklady

Výraz Aktuální uzel Vyhodnocení
//moznost[last()] jakýkoli element Poslední možnost v pořadí.
sum(*/@hlasu) moznosti Součet všech hlasů.
moznost[number(@hlasu)>=10]/text() moznosti Texty možností, které mají alespoň 10 hlasů.

Více příkladů uvádět nebudu, myslím, že časem v praxi narazíte na mnoho zajímavých případů. Pokud jste článek studovali pečlivě, máte velice slušný základ tohoto jazyka, který vám určitě nějakou dobu bude bohatě stačit. V opačném případě můžete své znalosti ještě doladit studiem z dalších zdrojů.

Odkazy, zdroje

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

1 Příspěvěk v diskuzi

Odpovědět