5. XPath

Jmenný prostor System.Xml.XPath obsahuje XPath parser a výpočetní engine. Podporuje W3C XML Path Language (XPath).

5.1. Co je to XPath

[znalosti]

XPath je jazyk používaný pro identifikaci uzlů v XML dokumentu. Pravděpodobně nejdůležitějším rysem jazyka XPath je možnost vyjádření relativní cesty od uzlu k jinému uzlu či atributu. Připomíná dotazovací jazyk SQL, zejména dík tomu, že na základě podmínky vrátí jeden nebo množinu výrazů (nebo žádný) odpovídající vstupní podmínce.

Podobně jako při procházení adresářové struktury se ve struktuře XML dokumentu dá procházet pomocí lomítek. Vemme například naši kuchařku. Pomocí tříd jmenného prostoru System.Xml jsme generovali HTML kód. Používali jsme přitom metody a vlastnosti třídy XmlDocument. Pro každý element, do kterého jsme se dostali, bylo nutno testovat jeho název, abychom měli jistotu, že pracujeme právě s ním. Díky jazyku XPath se tyto podmínky stávají jednoduššími. Pokud se totiž pomocí XPath budeme chtít dostat například do uzlu postup, stačí nám k tomu výraz

[ukázka kódu]
/kucharka/recept/postup

Stručně si popíšeme význam některých symbolů a způsob získávání elementů, pro podrobnější popis doporučuji stránky Jiřího Koska (viz odkaz na Výrazy XPath).

Tabulka 8.1. Výběr z XPath

rodič/potomekPokud lomítko umístíme na začátek výrazu, jako počáteční uzel se bere kořen dokumentu. Jinak se nalezne uzel potomek v uzlu rodič aktuálního uzlu
rodič//potomekPotomek nemusí být přímým následníkem rodiče - může se vyskytovat hlouběji ve struktuře. Pokud se nachází dvě lomítka na začátku výrazu (//rodič), naleznou se všechny výskyty elementu rodič v celém dokumentu
rodič/*vybere všechny uzly uzlu rodič v aktuálním uzlu
.vybere aktuální uzel
..pohyb na element o úroveň výše
@postupvybere atribut (zde atribut postup) aktuálního uzlu
[ ]podmínka
rodič/potomek[@atribut="3"]vybere všechny elementy potomek z elementu rodič aktuálního uzlu, jejichž atributy atribut odpovídají podmínce (zde jsou tedy rovny 3)

XPath umožňuje rovněž použití funkcí. Zkráceně si některé vypíšeme:

  • position(), last(), count()

    vrací pozici aktuálního uzlu, posledního uzlu, počet uzlů v daném kontextu

  • name(), local-name(), namespace-uri(),

    úplné jméno, název aktuálního uzlu, název jmenného prostoru

  • string(), number(), boolean()

    převod objektu na typ string, number, boolean

  • contains(), substring-before(), substring-after(), string-length()...

    práce s řetězci

Využití XPath v C# a jmenném prostoru System.Xml.XPath si ukážeme na příkladech.

5.2. Způsob získání dat pomocí XPath

Jak jsme si řekli, bude o něco jednodušší při hledání informací v XML dokumentu používat XPath. V podstatě budeme pro hledání výrazů používat tři základní třídy - XPathDocument, XPathNavigator a XPathNodeIterator.

XPathDocument slouží jako cache pro načítání dat z dokumentu, XPathNavigator v sobě zahrnuje metody důležité pro implementaci dotazů XPath. XPathNavigator lze vytvořit ze tříd XPathDocument a XmlNode voláním metody CreateNavigator(). Obě třídy totiž implementují rozhraní IXPathNavigable.

XPathIterator slouží k procházení uzlů vyhovujících vstupní podmínce zadané v instanci třídy XPathNavigator nebo z jiné instance XPathIterator.

Nyní již k samotným příkladům.

Zůstaneme stále u kuchařky. Nejprve vytvoříme XPathDocument, následně mu přiřadíme XPathNavigator a pokusíme se nalézt jména všech přísad, které jsou zapotřebí pro všechny recepty s použitím XPath. Stačí provést dotaz "/kucharka/recept/ingredience/@nazev". Pokud budeme chtít zjistit, jaké ingredience to jsou, napíšeme následující kód.

[ukázka kódu]
using System.Xml.Xpath;
...
XPathDocument myXpathDoc = new XPathDocument("kucharka.xml");
XPathNavigator myNav = myXPath.Doc.CreateNavigator();
XPathNodeIterator xi = myNav.Select("/kucharka/recept/ingredience/@nazev");
while (xi.MoveNext()) {
  Console.WriteLine(xi.Current.Value);
}
...

Metoda MoveNext() objektu XPathNodeIterator se musí volat vždy, abychom měli jistotu, že pracujeme skutečně s uzly, které jsme zadali v dotazu. Jinak bychom mohli dojít k jiným výsledkům, než jsme očekávali.

Stejně jako jsme položili dotaz na instanci třídy XPathNavigator, můžeme vytvářet dotazy i na jednotlivé instance XPathNodeIterator. Lze je vytvořit nad aktuálním uzlem získaným s pomocí vlastnosti Current.

[příklad ke stažení]

Kompletní řešení generování HTML kódu kuchařky pomocí výrazů XPath je ke shlédnutí zde.