Lekce 5 - Práce se soubory XML v PHP - Čtení
V předchozí lekci, Práce se soubory XML v PHP - Zápis, jsme se seznámili s prací se soubory ve
formátu XML. Probrali jsme použití třídy XMLWriter
, která
slouží na zápis XML.
Dnes se opět inspirujeme článkem Čtení XML SAXem v C# a napíšeme si podobnou aplikaci v jazyce PHP. Použijeme XML data, která jsme si vygenerovali v lekci práce se soubory XML v PHP - Zápis:
<?xml version="1.0" encoding="UTF-8"?> <uzivatele> <uzivatel vek="22"> <jmeno>Pavel Slavík</jmeno> <registrovan>21.3.2000</registrovan> </uzivatel> <uzivatel vek="31"> <jmeno>Jan Novák</jmeno> <registrovan>30.10.2012</registrovan> </uzivatel> <uzivatel vek="16"> <jmeno>Tomáš Marný</jmeno> <registrovan>12.1.2011</registrovan> </uzivatel> </uzivatele>
Tento soubor si uložíme do projektové složky.
Čtení XML metodou SAX –
třída XMLReader
Tentokrát je úloha mnohem obtížnější, než generování XML metodou SAX. Musíme totiž číst jednotlivé tokeny a jejich posloupností řídit ukládání dat. Zájemcům doporučuji metodu použít pouze ve specifických případech, třeba když z obrovského XML souboru potřebují jen vybrat některá data. V ostatních případech je výhodnější použít metodu DOM.
Třída Uzivatel
Nejprve si definujeme třídy, které budou ve složce tridy/
.
Jako první si definujeme třídu Uzivatel
:
class Uzivatel { private string $jmeno; private int $vek; private string $registrovan; public function __construct(XMLReader $data) { $this->vek = $data->getAttribute('vek'); while ($data->read()) { switch ($data->name) { case 'jmeno': $data->read(); $this->jmeno = $data->value; $data->read(); break; case 'registrovan': $data->read(); $this->registrovan = $data->value; $data->read(); break; // další elementy case '#text': break; default: return; } } } public function __toString(): string { return sprintf("%-20s %2d %10s", $this->jmeno, $this->vek, $this->registrovan); } }
Nejkomplikovanější třída dnes bude nejspíš Uzivatel
.
Nejprve ji přečteme atribut vek
elementu uzivatel
.
Poté ji přečteme i obsah elementů jmeno
a
registrovan
. Pokud parser (cyklus while()
) narazí na
neznámý element, je konstruktor ukončen. Pseudoelement #text
obsahuje bílé znaky, které jsou mezi elementy zdrojového XML a kterých se
potřebujeme zbavit. Přečtené atributy XML si uložíme do příslušných
atributů třídy.
Třída Uzivatele
Druhá třída bude Uzivatele
, která bude reprezentovat seznam
uživatelů:
class Uzivatele { private array $seznam = array(); public function __construct(XMLReader $data) { while ($data->read()) { switch ($data->name) { case 'uzivatel': if ($data->nodeType == XMLReader::ELEMENT) { $this->seznam[] = new Uzivatel($data); } break; case 'uzivatele': return; } } } public function __toString(): string { $uzivatele = array(); foreach ($this->seznam as $uzivatel) { $uzivatele[] = $uzivatel->__toString(); } return implode("\n", $uzivatele); } }
Soubor index.php
Nakonec stačí soubor index.php
:
require('tridy/Uzivatel.php'); require('tridy/Uzivatele.php'); // přečteme soubor s XML daty $data = new XMLReader(); // zde si případně upravte cestu k souboru XML $data->open('../data.xml'); // projdeme elementy XML souboru a přetransformujeme je do třídy Uzivatele while ($data->read()) { switch ($data->name) { case 'uzivatele': $uzivatele = new Uzivatele($data); break; } } // výstup si necháme vypsat do prohlížeče pro kontrolu header("Content-Type: text/plain; charset=UTF-8"); echo($uzivatele . "\n");
Pozornější programátoři si všimli, že v konstrukci switch
používáme jen 1× case
místo kratšího zápisu
if
. Je tomu tak proto, že pro čtení používáme metodiku
regulárního automatu, u které je použití switch
obvyklé. Při
parsování složitějšího dokumentu jistě oceníme snadnou
rozšiřitelnost.
Výstup
Po spuštění skriptu obdržíme následující výsledek:
Uvedený příklad není naprogramován úplně nejčistěji. Určitě by se našla kombinace validních vstupních dat, která by neprošla. Měla to být jen ukázka, že i v PHP je možné použít metodu SAX pro čtení dokumentů XML.
Čtení XML třídou
SimpleXML
Mluvili jsme o tom, že čtení XML metodou SAX není pro běžné použití
vhodné. Nyní si ukážeme ten lepší způsob pomocí třídy
SimpleXML
.
Třída SimpleXML
je určena pro jednoduchou konverzi dokumentu
XML do objektů v PHP. Na rozdíl od třídy XMLReader
však
dokument nečteme v cyklu po jednotlivých elementech, ale načteme ho celý do
objektové struktury. To je velmi výhodné, protože nejpomalejší úkon
provádí standardní knihovna, která je pro tento účel optimalizována.
Použijeme opět stejná data:
<?xml version="1.0" encoding="UTF-8"?> <uzivatele> <uzivatel vek="22"> <jmeno>Pavel Slavík</jmeno> <registrovan>21.3.2000</registrovan> </uzivatel> <uzivatel vek="31"> <jmeno>Jan Novák</jmeno> <registrovan>30.10.2012</registrovan> </uzivatel> <uzivatel vek="16"> <jmeno>Tomáš Marný</jmeno> <registrovan>12.1.2011</registrovan> </uzivatel> </uzivatele>
Třída Uzivatele
Zde nám oproti metodě SAX stačí vytvořit pouze jednu třídu
Uzivatele
:
class Uzivatele { private SimpleXMLElement $seznam; public function __construct(string $souborXML) { $this->seznam = new SimpleXMLElement($souborXML, null, true); } public function __toString(): string { $uzivatele = array(); foreach ($this->seznam as $uzivatel) { $uzivatele[] = sprintf("%-20s %2d %10s", $uzivatel->jmeno, $uzivatel['vek'], $uzivatel->registrovan); } return implode("\n", $uzivatele); } }
Soubor index.php
Skript vypisující data je velmi krátký
require('tridy/Uzivatele.php'); // zde si případně upravte cestu k souboru XML $data = new Uzivatele('../data.xml'); header("Content-Type: text/plain; charset=UTF-8"); echo($data . "\n");
Podle potřeby můžeme samozřejmě doplnit metody pro vyhledání uživatele, ověření hesla apod. Pro náš účel postačí pouhý výpis seznamu uživatelů.
Výstup
Po spuštění skriptu se v prohlížeči objeví:
Jak vidíme, čtení dokumentu třídou SimpleXMLElement
je
mnohem jednodušší, než čtení metodou SAX. Tato třída je také asi 10×
rychlejší, než XMLReader
a lépe zdokumentovaná. Pro
zpracování běžných dokumentů XML je proto mnohem výhodnější.
Kompletní kód všech příkladů z této lekce najdete jako vždy ke stažení dole pod článkem
V následujícím cvičení, Řešené úlohy k 3.-5. lekci práce se soubory v PHP, si procvičíme nabyté zkušenosti z předchozích lekcí.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 11x (5.35 kB)
Aplikace je včetně zdrojových kódů v jazyce PHP