IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

5. diel - Práca so súbormi XML v PHP - Čítanie

V predchádzajúcej lekcii, Práca so súbormi XML v PHP , sme sa zoznámili s prácou so súbormi vo formáte XML. Prebrali sme použitie tried XMLWriter, XMLReader a SimpleXML.

Dnes sa opäť inšpirujeme článkom Čítanie XML SAXom v C# a napíšeme si podobnú aplikáciu v jazyku PHP. Použijeme XML dáta, ktoré sme si vygenerovali v lekcii práce so súbormi 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 súbor si uložíme do projektovej zložky.

Čítanie XML metódou SAX – trieda XMLReader

Tentokrát je úloha oveľa ťažšia, než generovanie XML metódou SAX. Musíme totiž čítať jednotlivé tokeny a ich postupnosťou riadiť ukladanie dát. Záujemcom odporúčam metódu použiť iba v špecifických prípadoch, napríklad keď z obrovského XML súboru potrebujú len vybrať niektoré dáta. V ostatných prípadoch je výhodnejšie použiť metódu DOM.

Trieda Uzivatel

Najprv si definujeme triedy, ktoré budú v zložke tridy/. Ako prvú si definujeme triedu 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;

                // ďalšie elementy
                case '#text':
                    break;

                default:
                    return;
            }
        }
    }

    public function __toString(): string
    {
        return sprintf("%-20s %2d %10s", $this->jmeno, $this->vek, $this->registrovan);
    }
}

Najkomplikovanejšia trieda dnes bude najskôr Uzivatel. Najprv ju prečítame atribút vek elementu uzivatel. Potom ju prečítame aj obsah elementov jmeno a registrovan. Pokiaľ parser (cyklus while()) narazí na neznámy element, je konštruktor ukončený. Pseudoelement #text obsahuje biele znaky, ktoré sú medzi elementmi zdrojového XML a ktorých sa potrebujeme zbaviť. Prečítané atribúty XML si uložíme do príslušných atribútov triedy.

Trieda Uzivatele

Druhá trieda bude Uzivatele, ktorá bude reprezentovať zoznam užívateľov:

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);
    }
}

Súbor index.php

Nakoniec stačí súbor index.php:

require('tridy/Uzivatel.php');
require('tridy/Uzivatele.php');

// prečítame súbor s XML dátami
$data = new XMLReader();

// tu si prípadne upravte cestu k súboru XML
$data->open('../data.xml');

// prejdeme elementy XML súboru a pretransformujeme ich do triedy Uzivatele
while ($data->read()) {
    switch ($data->name) {
        case 'uzivatele':
            $uzivatele = new Uzivatele($data);
            break;
    }
}

// výstup si necháme vypísať do prehliadača pre kontrolu
header("Content-Type: text/plain; charset=UTF-8");
echo($uzivatele . "\n");

Pozornejší programátori si všimli, že v konštrukcii switch používame len 1× case namiesto kratšieho zápisu if. Je tomu tak preto, že na čítanie používame metodiku regulárneho automatu, pri ktorej je použitie switch obvyklé. Pri parsovaní zložitejšieho dokumentu určite oceníme jednoduchú rozšíriteľnosť.

Výstup

Po spustení skriptu dostaneme nasledujúci výsledok:

Čtení XML - XMLReader
localhost

Uvedený príklad nie je naprogramovaný úplne najčistejšie. Určite by sa našla kombinácia validných vstupných dát, ktorá by neprešla. Mala to byť len ukážka, že aj v PHP je možné použiť metódu SAX na čítanie dokumentov XML.

Čítanie XML triedou SimpleXML

Hovorili sme o tom, že čítanie XML metódou SAX nie je na bežné použitie vhodné. Teraz si ukážeme ten lepší spôsob pomocou triedy SimpleXML.

Trieda SimpleXML je určená na jednoduchú konverziu dokumentu XML do objektov v PHP. Na rozdiel od triedy XMLReader však dokument nečítame v cykle po jednotlivých elementoch, ale načítame ho celý do objektovej štruktúry. To je veľmi výhodné, pretože najpomalší úkon vykonáva štandardná knižnica, ktorá je na tento účel optimalizovaná.

Použijeme opäť rovnaké dáta:

<?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>

Trieda Uzivatele

Tu nám oproti metóde SAX stačí vytvoriť iba jednu triedu 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);
    }
}

Súbor index.php

Skript vypisujúci údaje je veľmi krátky

require('tridy/Uzivatele.php');

// tu si prípadne upravte cestu k súboru XML
$data = new Uzivatele('../data.xml');

header("Content-Type: text/plain; charset=UTF-8");
echo($data . "\n");

Podľa potreby môžeme samozrejme doplniť metódy na vyhľadanie užívateľa, overenie hesla a pod. Na náš účel postačí obyčajný výpis zoznamu užívateľov.

Výstup

Po spustení skriptu sa v prehliadači objaví:

Čtení XML - SimpleXML
localhost

Ako vidíme, čítanie dokumentu triedou SimpleXMLElement je oveľa jednoduchšie, než čítanie metódou SAX. Táto trieda je tiež asi 10× rýchlejšia ako XMLReader a lepšie zdokumentovaná. Pre spracovanie bežných dokumentov XML je preto oveľa výhodnejšie.

Kompletný kód všetkých príkladov z tejto lekcie nájdete ako vždy na stiahnutie dole pod článkom:-)

V ďalšej lekcii, Práca s archívmi ZIP v PHP , sa zoznámime s prácou s archívmi vo formáte ZIP v PHP. Ukážeme si triedu ZipArchive a jej najdôležitejšie metódy.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 10x (5.35 kB)
Aplikácia je vrátane zdrojových kódov v jazyku PHP

 

Predchádzajúci článok
Práca so súbormi XML v PHP
Všetky články v sekcii
Práca so súbormi v PHP
Preskočiť článok
(neodporúčame)
Práca s archívmi ZIP v PHP
Článok pre vás napísal Samuel Hél
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje hlavně programování, nejvíce z oblasti webových technologií, dělá občasné video edity ze svých dovolených. Má rád memes, svou gf a elektroniku
Aktivity