Dnes si ukážeme na efetivnější metody zpracování XML pomocí PHP.
20.10.2004 15:00 | Petr Zajíc | přečteno 49506×
Minule jsme předložili něco teorie kolem XML a ukázali jsme si, jak sestavit nejjednodušší parser. Dnes si ukážeme, jak pomocí PHP sestavit parser, který bude maličko užitečnější než ten první; bude totiž skutečně něco reálného dělat. Bude to výpočet bilance z našeho ukázkového souboru finance.xml.
Minule jsme si předvedli, že existuje funkce xml_set_element_handler, která definuje, co se má stát když při parsování XML dokumentu narazíme na značky. Existuje pochopitelně funkce xml_set_character_data_handler, která se zase naopak stará o data. Rozšiřme tedy minulý příklad do podoby, v níž bude tato funkce obsažena:
<?
// úvod ...
function data ($parser, $data)
{
global $znacka;
global $bilance;
global $jeprijem;
if ($znacka=="CASTKA" and $jeprijem) $bilance+=$data;
if ($znacka=="CASTKA" and !$jeprijem) $bilance-=$data;
}
$nas_parser=xml_parser_create();
xml_set_element_handler ($nas_parser, "PocatecniZnacka", "KoncovaZnacka");
xml_set_character_data_handler($nas_parser, "data");
// atd.
echo $bilance;
?>
Ukázat celý skript | Spustit skript
To je (jak můžete vidět ze zobrazení celého skriptu) poměrně názorné
řešení. Nejprve si při procházení značkami "přepneme semafor" $jeprijem
na hodnotu TRUE nebo FALSE pokaždé, když narazíme při čtení značky na
hodnotu PRIJEM nebo VYDAJ. Jestliže potom v datech (obsažených mezi
značkami CASTKA, jiné nás nezajímají) narazíme na číslo, přičteme jej
nebo odečteme, a to podle toho, zda se jedná o příjem nebo výdaj.
Tento skript je sice poměrně názorný, je však nešikovně napsaný. Protože, jak jsme již uvedli v díle o funkcích, nejsou automaticky globální proměnné k dispozici v těle fukcí, a to tak dlouho, dokud jim to nenařídíme pomocí klíčového slova global. Takže je na to potřeba myslet. Elegantním řešením by bylo přepsat celou záležitost s použitím třídy, protože proměnné třídy jsou v čleských funcích k dispozici. Mohlo by to vypadat třeba takto:
<?
// nejdřív definice třídy
class bilance
{
var $soubor;
var $bilance=0;
var $priv_jeprijem=false;
var $priv_znacka="";
var $priv_parser;
function PocatecniZnacka
($parser, $nazev, $atributy)
{
// atd...
}
function KoncovaZnacka
($parser, $nazev) {}
function data ($parser, $data)
{
// atd...
}
function parse ()
{
$this->priv_parser=xml_parser_create();
xml_set_object($this->priv_parser, $this);
xml_set_element_handler
($this->priv_parser, "PocatecniZnacka", "KoncovaZnacka");
xml_set_character_data_handler($this->priv_parser, "data");
if (!($obsahsouboru
= fopen($this->soubor, "r"))) die("Nemohu otevřít
XML pro čtení.");
while ($data
= fread($obsahsouboru, 1024)) xml_parse($this->priv_parser, $data, feof($obsahsouboru));
xml_parser_free($this->priv_parser);
}
}
// teď vlastní program
$moje_bilance = new bilance;
$moje_bilance->soubor = "./finance.xml";
$moje_bilance->parse();
echo $moje_bilance->bilance;
?>
Ukázat celý skript | Spustit skript
Omlouvám se za poněkud delší ukázku, ale kratší to být nemohlo. Co
se s naším kódem stalo? Všechny ty otravné práce s parsováním jsme
zapouzdřili do třídy nazvané bilance. Takže, všimnete-li si závěru,
stačí zavést novou instanci této třídy, předat jí soubor ke zpracování,
spustit parser a nechat si zobrazit výsledek. V třídě samotné je
podstatný řádek s voláním funkce xml_set_object
(v kódu výše jsem to zvýraznil), která umožní použít pro zpracování
členské funkce třídy namísto veřejných funkcí. Neboli, kdybyste řádek s
voláním xml_set_object zakomentovali, nenajde parser funkce
PocatecniZnacka, KoncovaZnacka a data, protože žádné takové veřejné
funkce ve skriptu neexistují (jsou to "jen" členské funkce dané třídy).
Použitím třídy jsme se samozřejmě rovněž vyhnuli nutnosti neustále
používat klíčové slovo global. Místo toho sice používáme konstrukci
this->proměnná k volání členských proměnných třídy, ale je to daleko
elegantnější. Kromě toho lze třídu podle potřeby rozšířit nebo napsat
dceřinné třídy.
Pozn.: Trochu odbočím. Kdykoli se Vám
během programování bude zdát, že něco sice funguje, ale šlo by to
napsat přehledněji, nelitujte a přepište to. Příklad výše je toho
typickou ukázkou. Odměnou Vám bude nejen přehlednější kód, ale
(většinou) i kód rychlejší a skoro vždy to oceníte časem, až se k
danému programu budete vracet a budete se v něm muset vyznat.
Příště se zaměříme na problém tvorby XML dokumentů pomocí PHP.