XMLReader – když se zamotáme do SAX

V minulém dílu seriálu o práci s XML soubory v jazyce PHP jsme probírali rozhraní SAX. V dnešním pokračování je na řadě rozhraní XMLReader, které je do určité míry podobné (zpracovává XML soubor po částech), ale používá opačný směr toku událostí a dovoluje zjednodušit kód výsledné aplikace.

Seriál: Přehled podpory XML v PHP5 (6 dílů)

  1. Přehled podpory XML v PHP5 5.10.2009
  2. PHP a XML: SAX – čteme pěkně popořádku 12.10.2009
  3. XMLReader – když se zamotáme do SAX 19.10.2009
  4. DOM – načteme to do paměti 26.10.2009
  5. XPath – rychle to najdeme 2.11.2009
  6. XSLT – jazyk budoucnosti 9.11.2009

Jak jsme viděli, rozhraní SAX je sice rychlé a nenáročné na zdroje, ale práce s ním není moc pohodlná. Je to způsobeno push modelem, který SAX používá (viz obrázek 4 – „Princip push modelu přístupu k dokumentu XML“ v minulém dílu). Tuto nevýhodu SAXu překonávají novější rozhraní, která staví na tzv. pull modelu. Zatímco push parser (SAX) zahrnuje naši aplikaci proudem událostí, které zkrátka musíme obsloužit, pull parser aplikaci předá data, jen když si o to aplikace řekne. Data tedy čteme v tu chvíli, kdy je potřebujeme. Díky tomu může být kód aplikace mnohem přehlednější a přímočařejší.

Kosek
Pull model čtení dat

Pull parser je v PHP dostupný jako třída XMLReader. Díky této objektové obálce je práce s  XMLReader velmi jednoduchá. Nejprve si musíme vždy vytvořit novou instanci parseru a pak říci, jaký dokument se bude načítat:

$reader = new XMLReader();
$reader->open("dokument.xml");

V tomto okamžiku je dokument XML připraven ke čtení. V okamžiku, kdy náš skript bude chtít přečíst část dokumentu, stačí použít metodu read(), která přečte další část dokumentu XML (počáteční tag, obsah elementu apod.). V případě, že jsme na konci dokumentu, vrací metoda hodnotu false, v opačném případě true. Chceme-li tedy postupně přečíst celý dokument, stačí metodu volat v cyklu  while:

while ($reader->read())
{
  …
}

Chcete se naučit o PHP víc?

Akademie Root.cz pořádá školení Kurz programování v PHP5. Jednodenní kurz programování v PHP 5 je určen všem webovým vývojářům, kteří se chtějí do hloubky seznámit a sžít s programovacím jazykem PHP ve verzi 5. První část kurzu je zaměřena na nový objektový model se všemi jeho vlastnostmi, ošetření chyb pomocí výjimek a efektivní využití těchto konceptů. Druhá část je zaměřena na nové knihovny PHP 5, především pro práci s databázemi, XML a objekty. Pozornost je věnována i zajištění kompatibility s PHP 4, přechodu z této verze a výhledu na PHP 6. Máte zájem o jiné školení? Napište nám!

Na objektu XMLReader je dostupných několik vlastností, které umožňují zjišťovat informace o části dokumentu, na kterou jsme se právě přesunuli. Můžeme například zjišťovat druh uzlu (nodeType) a jeho název (name). Jsme-li nastaveni na elementu (tedy na jeho počátečním tagu), lze pomocí metody readString() přečíst celý textový obsah elementu. Použití těchto metod pro čtení dokumentu RSS demonstruje následující příklad.

<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN'>
<html lang="cs">
  <head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8">
    <title>Přehled zpráv</title>
  </head>
  <body>
<?php

// vytvoření nového XMLReaderu
$reader = new XMLReader();

// otevření souboru pro čtení
$reader->open("../data/luparss.xml");

// dokud je co, čteme další část dokumentu XML
while ($reader->read())
{
  // obsluha odkazu (element link)
  if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "link")
    echo "<h1>Přehled aktuálních zpráv ze serveru
      <a href='" . htmlspecialchars($reader->readString(), ENT_QUOTES) . "'>" .
      $title . "</a></h1>";

  // obsluha názvu kanálu
  if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "title")
    $title = htmlspecialchars($reader->readString());

  // obsluha položky v kanálu
  if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "item")
  {
    echo "<dl>";

    // dokud je co, čteme další část dokumentu XML
    // předpokládáme přitom, že elementy jsou uvnitř elementu item
    while ($reader->read())
    {
      if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "link")
                echo "<dt><a href='" . htmlspecialchars($reader->readString(), ENT_QUOTES) . "'>" .
                    $title . "</a></dt>n";

      if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "title")
                $title = htmlspecialchars($reader->readString());

      if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "description")
                echo "<dd>" .  htmlspecialchars($reader->readString()) . "</dd>n";
    }

    echo "</dl>";
  }
}

?>
  </body>
</html>

V příkladu je použita konstanta XMLREADER_ELEMENT, která definuje kód uzlu, který odpovídá začátku elementu. Zároveň vidíme, že podle potřeby můžeme čtení z dokumentu XML zanořovat níže do struktury kódu – např. když chceme jinak zpracovat obsah elementu item. Práce s  XMLReader je principem podobná jako sekvenční čtení souborů, a proto je mnoha programátorům velmi blízká. Navíc zachovává výhody rozhraní SAX, jako je rychlost a malá paměťová náročnost.

V příštím díle se podíváme na snad nejznámější rozhraní pro práci s XML, na rozhraní DOM. Toto rozhraní je webovým vývojářům dobře známé, protože stejné rozhraní se používá i v JavaScriptu pro manipulaci se stránkou načtenou do prohlížeče.

Více informací o knize naleznete na stránkách nadavatelství Grada a na stránkách autora.

Komentáře: 11

Přehled komentářů

brablc No nevim
Jiří Kosek Re: No nevim
Jakub Vrána Re: No nevim
Jiří Kosek Re: No nevim
peter Re: No nevim
Jakub Vrána Re: No nevim
brablc Re: No nevim
Jiří Kosek Re: No nevim
Jakub Vrána Re: No nevim
Jiří Kosek Re: No nevim
Jakub Vrána Re: No nevim
Zdroj: https://www.zdrojak.cz/?p=3103