reklama

Poznáváme C# a Microsoft. NET 46. díl – použití XPath

Další díl tohoto seriálu bude opět poletovat okolo problematiky XML. Dnes se podíváme na možné použití jazyka XPath v prostředí .NET.

Jazyk XPath

Tento jazyk byl jako standard vydán v roce 1999 světovým konsorciem W3C. Tento jazyk zjednodušeně řečeno, mimo jiné, umožňuje pomocí své dotazové syntaxe vyjádřit, která množina uzlů má být získána. Jinak řečeno, pomocí použití tohoto jazyku jsme schopni vybrat určitou množinu dat na základě specifických podmínek.

Jazyk XPath je kromě jiného jednou z největších „pomocníků“ při používání XSL transformací. Nechci se v tomto díle zabývat popisem tohoto ne zrovna triviálního jazyku a proto případné zájemce o učení se odkážu na jeden výborný tutoriál, který naleznete na adrese http://www.w3schools.com/xpath/.

Užití XPath v .NET

Pro naše ukázkové příklady budeme opět používat náš známý XML dokument obsahující data o zaměstnancích.

<?xml version="1.0" encoding="utf-8" ?>
<zamestnanci>
  <zamestnanec jmeno="Michal" prijmeni="Racek" pozice="Vyvojar"/>
  <zamestnanec jmeno="Jan" prijmeni="Novak" pozice="Analytik"/>
  <zamestnanec jmeno="Jiri" prijmeni="Joudek" pozice="Vyvojar"/>
</zamestnanci>

Zkusme se zamyslet nad situací, kdy chceme najít nějakého konkrétního zaměstnance, tedy například podle příjmení. Bez použití jazyku XPath s použitím přístupu přes DOM bychom takovýto požadavek splnili možná podobným způsobem jako je ten následující.

/// <summary>
/// Vyhleda uzel zamestnance podle prijmeni
/// </summary>
/// <param name="Prijmeni">Prijmeni hledaneho zamestnance</param>
internal static void HledaniZamestnanceBezXPath(string Prijmeni)
{
  //ziskani cesty odkud je aplikace spustena
  string lPath = AppDomain.CurrentDomain.BaseDirectory + "zamestnanci.xml";
  XmlDocument lDoc = new XmlDocument();
  lDoc.Load(lPath);
  XmlNode lRootElem = lDoc.DocumentElement;
  foreach(XmlNode lNode in lRootElem)
{
    if (lNode.Name.Equals("zamestnanec"))
    {
      foreach (XmlAttribute lAttribute in lNode.Attributes)
      {
        if (lAttribute.Name.Equals("prijmeni") && lAttribute.Value.Equals(Prijmeni))
          {
          Console.WriteLine("Hledany zamestanec : {0} {1} - {2}", lNode.Attributes["jmeno"].Value, lNode.Attributes["prijmeni"].Value, lNode.Attributes["pozice"].Value);
        }
      }
    }
  }
}

public static void HledaniBezXPath()
{
  HledaniZamestnanceBezXPath("Joudek");
}

Tento příklad samozřejmě bude funkční, ale je poněkud složitý a navíc takovýto přístup k vyhledávání uzlů je v případě, kdy jsou hledané uzly závislé na složité hierarchii rodičovských uzlů, také dost náchylné k chybám. Zkusme tento požadavek naimplementovat nějak elegantněji. Samozřejmě mám na mysli s použitím XPath.

public static void HledaniXPath()
{
  HledaniZamestnanceXPath("Joudek");
}

/// <summary>
/// Vyhleda uzel zamestnance podle prijmeni pouzitim XPath
/// </summary>
/// <param name="Prijmeni">Prijmeni hledaneho zamestnance</param>
internal static void HledaniZamestnanceXPath(string Prijmeni)
{
  string lPath = AppDomain.CurrentDomain.BaseDirectory + "zamestnanci.xml";
  XmlDocument lDoc = new XmlDocument();
  lDoc.Load(lPath);
  //sestaveni XPath dotazu
  string lXPathQuery = "descendant::zamestnanec[@prijmeni=`" + Prijmeni + "`]";
  //vyvolani XPath dotazu
  XmlNodeList lResult = lDoc.SelectNodes(lXPathQuery);
  if (lResult.Count > 0)
  {
    XmlNode lResultNode = lResult[0];
    Console.WriteLine("Hledany zamestanec : {0} {1} - {2}", lResultNode.Attributes["jmeno"].Value, lResultNode.Attributes["prijmeni"].Value, lResultNode.Attributes["pozice"].Value);
  }
}

Po sestavení XPath dotazu, k jeho spuštění a získání výsledku v podobě XMLNodeListu, použijeme metodu SelectNodes, která je definována již na předkovi třídy XMLDocument, tedy na třídě XMLNode. Po té již jednoduše procházíme výsledný list uzlů.

Rozhraní XPath a třída XPathNavigator

Kromě výše zmíněného způsobu spuštění XPath dotazu, existuje ještě jedna cesta, která je představována použitím nějaké implementace rozhraní IXPathNavigable. Toto rozhraní je implementováno také třídou XMLNode. Rozhraní předepisuje jednu jedinou metodu, kterou je CreateNavigator. Tato metoda vrací odkaz na instanci třídy XPathNavigator, která umožňuje číst data pomocí kurzorového modelu (posuny kurzoru na určité části dat). Následující příklad ukazuje jak na to pomocí užití výše zmíněné třídy.

/// <summary>
/// Ukazka pouziti dotazu XPath pomoci tridy XPathNavigator
/// </summary>
public class XPathNavigatorExam
{
  /// <summary>
  /// Vyhleda uzel zamestnance podle pozice pouzitim XPath
  /// </summary>
  /// <param name="Pozice">Pozice hledanych zamestnancu</param>
  internal static void HledaniZamestnance(string Pozice)
  {
    string lPath = AppDomain.CurrentDomain.BaseDirectory + "zamestnanci.xml";
    XmlDocument lDoc = new XmlDocument();
    lDoc.Load(lPath);
    XPathNavigator lNavigator = lDoc.CreateNavigator();
    string lXPathQuery = "descendant::zamestnanec[@pozice=`" + Pozice + "`]";
    //zkompilujeme XPath dotaz
    XPathExpression lCompiledQuery = lNavigator.Compile(lXPathQuery);
    //provedeme dotaz
    XPathNodeIterator lIterator = lNavigator.Select(lCompiledQuery);
    //zobrazime vysledky
    while(lIterator.MoveNext())
    {
      //vytvorime klon navigatoru
      XPathNavigator lClonedNavigator = lIterator.Current.Clone();
      //posun na prvni uzel
      lClonedNavigator.MoveToFirstChild();
      //posun na atribut jmeno
      lClonedNavigator.MoveToAttribute("jmeno","");
      string lJmeno = lClonedNavigator.Value;
      //posun na dalsi atribut, kterym je prijmeni
      lClonedNavigator.MoveToNextAttribute();
      string lPrijmeni = lClonedNavigator.Value;
      Console.WriteLine("{0} {1}", lJmeno, lPrijmeni);
    }
  }
public static void NajdiZamestnance()
  {
    HledaniZamestnance("Vyvojar");
  }
}

Po získání odkazu na instanci třídy XPathNavigator, můžeme XPath dotaz zkompilovat pomocí jeho metody Compile, jejíž návratová hodnota je typu XPathExpression, která slouží právě k reprezentaci kompilovaných výrazů jazyku XPath. Po zavolání metody Select na instanci třídy XPathNavigator získáme odkaz na instanci třídy XPathNodeIterator, který následně použijeme k průchodu vybranými uzly.

Při každé iteraci listem, vytvoříme klon instance třídy XPathNavigator a to z důvodu abychom posouvali kurzor na speciální instanci. Po té na tomto klonu voláme metody (MoveToFirstChild, MoveToAttribute, MoveToNextAttribute) k zajištění posunu kurzoru na námi chtěné pozice. Obsah kurzoru si na dané pozici přečteme skrze instanční vlastnost Value třídy XPathNavigator.

Příklady k článku naleznete zde.

Témata článku: Software, Microsoft, Programování

1 komentář

Nejnovější komentáře

  • Pavel Polívka 24. 11. 2007 13:42:06
    Programovou oflline verzi seriálu naleznete ke stažení na...
reklama
Určitě si přečtěte

Microsoft: Zbavte se už konečně zastaralých a děravých Windows 7

Microsoft: Zbavte se už konečně zastaralých a děravých Windows 7

** Microsoft pomalu začíná kritizovat svůj nejpopulárnější OS ** Chce konečně dostat podniky na Desítky ** Bezpečnostní podpora Sedmiček vydrží ještě necelé tři roky

17.  1.  2017 | Jakub Čížek | 306

Pojďme programovat elektroniku: Sestavíme si mobil a pošleme SMS

Pojďme programovat elektroniku: Sestavíme si mobil a pošleme SMS

** Kolik stál váš mobilní telefon? ** Základní GSM modem koupíte za stovku ** Umí telefonovat, posílat SMS a zvládne i GPRS

13.  1.  2017 | Jakub Čížek | 27

Český státní blacklist už funguje. Ministerstvo financí se pochlubilo s detaily

Český státní blacklist už funguje. Ministerstvo financí se pochlubilo s detaily

** Dva týdny po Novém roce zajím zeje prázdnotou ** Ministerstvo vydalo metodický pokyn ** Takhle to bude fungovat v praxi

16.  1.  2017 | Jakub Čížek | 49


Aktuální číslo časopisu Computer

99 nejlepších programů pro váš počítač

Zvykejte si na umělou inteligenci

Velké testy PC zdrojů a gamepadů

Alternativní zdroje energie

reklama
reklama