Přejít k navigační liště

Zdroják » PHP » Přehled podpory XML v PHP5

Přehled podpory XML v PHP5

Články PHP, Různé

Snad každý programátor webových aplikací se setkal ve své praxi s nutností zpracovat data ve formátu XML. V šestidílném seriálu Jiřího Koska si představíme nástroje a techniky, jaké máme k dispozici v aktuální verzi PHP 5, a na příkladech si ukážeme jejich silné stránky a jejich slabiny.

V následující sérii článků si na několika jednoduchých příkladech ukážeme, jaké možnosti pro práci s XML nabízí současná verze PHP. Seznámíme se tak se základními přístupy k načítání a zpracování dokumentů XML. Jedná se přitom o redakčně upravenou kapitolu z právě vydané knihy PHP a XML od Jiřího Koska.

Podpora práce s XML v PHP prošla velmi bouřlivým vývojem. První zárodky knihoven pro práci s XML se objevily již ve verzi PHP3. Jednalo se však pouze o jednoduchý proudový parser XML (SAX) vystavený okolo knihovny expat. Práce s touto knihovnou nebyla nijak zvlášť pohodlná a hodila se opravdu jen pro načítání dokumentů s nepříliš složitou strukturou.

Verze PHP4 se snažila podporu XML vylepšit, ale přiznejme si, že ne zrovna šťastným způsobem. Podpora XML byla velmi roztříštěná. Nově přibyla možnost načíst celý dokument do paměti jako DOM strom. Bohužel, rozhraní této knihovny se mezi jednotlivými verzemi PHP4.x měnilo a ani po změnách nebylo v souladu se standardem DOM rozhraní tak, jak ho definovalo konsorcium W3C. Knihovna pro práci s DOM byla vystavena nad knihovnou libxml2 a umožňovala i provádění dotazů v jazyce XPath.

Do PHP4 byla přidána i možnost provádění XSLT transformací. Nejprve byla přidána knihovna, která využívala český XSLT procesor Sablotron. Později byla přidána ještě druhá knihovna pro práci s XSLT založená na knihovně libxslt (ta je od stejného autora jako libxml2). Obě dvě knihovny mezi sebou byly samozřejmě nekompatibilní, navíc knihovna založená na Sablotronu neuměla spolupracovat s dokumenty reprezentovanými DOM stromem. Uvažovalo se tedy i o tom, že by se přidala ještě jedna implementace rozhraní DOM, kterou obsahoval Sablotron.

Ve verzi PHP5 se proto vývojáři rozhodli tuto roztříštěnost sjednotit, což byl jistě správný krok. Jeho vedlejší důsledek je však ten, že rozhraní knihoven pro práci s XML nejsou mezi verzemi PHP4 a PHP5 stejná, takže téměř všechny skripty pracující s XML je potřeba při přechodu mezi těmito verzemi PHP přepsat.

Podpora XML v PHP5 je vystavena okolo knihoven libxml2 a libxslt od Daniela Veillarda. Všechna rozhraní XML, která jsou nad nimi postavena, byla přepracována, aby se s nimi lépe pracovalo a aby odpovídala příslušným standardům (např. W3C DOM).

Nicméně praxe ukázala, že v navržených rozhraních pro PHP5.0 nebyly obsaženy všechny důležité věci. Nedostatky byly odstraněny až ve verzi 5.1. Takže pokud máte možnost volby, doporučuji pro práci s XML používat verzi PHP5.1 nebo vyšší.

Ve zbytku seriálu si ukážeme, jak pomocí jednotlivých XML rozhraní můžeme převést jednoduchý dokument XML obsahující souhrn zpráv ve formátu RSS do podoby webové stránky. Na obrázku 1 – „Dokument RSS zobrazený jako stránka HTML“ se můžeme podívat na to, jak má vypadat výsledek skriptů zobrazený v prohlížeči.

Příklad 1. Ukázkový dokument RSS – data/luparss.xml

<?xml version="1.0" encoding="windows-1250"?>
<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN"
  "http://my.netscape.com/publish/formats/rss-0.91.dtd">
<rss version="0.91">
  <channel>
    <title>Lupa.cz</title>
    <link>http://www.lupa.cz/</link>
    <description>Server o českém Internetu</description>
    <language>cs</language>
    <item>
      <title>Zazděný Telecom</title>
      <link>http://r.iinfo.cz/?f=rss&u=http%3A%2F%2Fwww.lupa.cz%2Fclanek.php3%3Fshow%3D3656</link>
      <description>Na Olšanské ulici v Praze, přímo před budovou Českého Telecomu, vyrostla včera dopoledne zeď. Postavila ji společnost Tele2 na oplátku za to, jak Český Telecom zazdívá její klienty. Chce tím upozornit na problém s pomalým přepojováním  svých zákazníků na ústřednách Českého Telecomu, kvůli možnosti využívat pevnou volbu operátora.  </description>
    </item>
    <item>
      <title>Dana Bérová: Byla to nabídka, která se neodmítá</title>
      <link>http://r.iinfo.cz/?f=rss&u=http%3A%2F%2Fwww.lupa.cz%2Fclanek.php3%3Fshow%3D3657</link>
      <description>Téměř před rokem byl u příležitosti prvního dne Invexu (6. října 2003) spuštěn testovací provoz Portálu veřejné správy. Hned druhý den byl portál vyhlášen Událostí roku české informatiky a telekomunikací 2003 a cenu šla přebírat šéfka  úseku e-government ministerstva informatiky Dana Bérová. </description>
    </item>
    <item>
      <title>Rychlost je nanic, následuj instinkt</title>
      <link>http://r.iinfo.cz/?f=rss&u=http%3A%2F%2Fwww.lupa.cz%2Fclanek.php3%3Fshow%3D3658</link>
      <description>Už docela dlouho mám doma připojení k Internetu od UPC a pomalu to přestávám stíhat: z původních 128 kbit/s jsem se za pár let dostal až na dříve neuvěřitelných 1.536 kbit/s; tvrdí to alespoň mail, který jsem tento týden od UPC dostal. Platím pořád stejně, takže mohu být rád. No jo - ale co si mám vlastně s takovým pásmem počít?</description>
    </item>
    <item>
      <title>Za co dostali mobilní operátoři pokuty?</title>
      <link>http://r.iinfo.cz/?f=rss&u=http%3A%2F%2Fwww.lupa.cz%2Fclanek.php3%3Fshow%3D3655</link>
      <description>Propojovací dohody, které Český Mobil uzavřel s Eurotelem a s Radiomobilem, vyhodnotil Český telekomunikační úřad jako exkluzivní a operátorům přikázal jejich dodržování. ÚOHS je také vyhodnotil jako exkluzivní, ale kvalifikoval to jako porušení zákona o ochraně hospodářské soutěže, udělil za ně operátorům pokuty a zakázal jejich plnění.</description>
    </item>
    <item>
      <title>Překryvné sítě jako lék na neduhy Internetu</title>
      <link>http://r.iinfo.cz/?f=rss&u=http%3A%2F%2Fwww.lupa.cz%2Fclanek.php3%3Fshow%3D3654</link>
      <description>Jednoduchá architektura současného Internetu stále přináší řadu výhod zejména z hlediska jeho rozšiřování, znamená však ale i potíže se správou, bezpečností a celkovým zdravím a výkonem celosvětové sítě. Současný stav nedává mnoho šancí pro budoucí  požadavky informační společnosti. Kudy tedy dál s Internetem?</description>
    </item>
  </channel>
</rss>

Obrázek 1. Dokument RSS zobrazený jako stránka HTMLKosek

SimpleXML – jednoduše na věc

Dokumenty XML mají hierarchickou strukturu tvořenou vnořením jednotlivých elementů. Hierarchické struktury lze v počítači reprezentovat mnoha způsoby, v poslední době je populární modelování pomocí objektů. Knihovna SimpleXML využívá právě tento způsob. Dokument XML načte celý do paměti do struktury objektů, jejichž jména odpovídají názvům elementů zpracovávaného dokumentu. Díky tomu se pak velmi jednoduše přistupuje k jednotlivým informacím.

Pro vytvoření struktury objektů z dokument XML slouží funkce simplexml_load_file(), která jako parametr očekává jméno souboru ke zpracování. Výsledkem je objekt, který zastupuje celý dokument XML.

$xml = simplexml_load_file("dokument.xml");

Podelementy jsou přitom dostupné jako členské proměnné. K elementu channel se tak dostaneme zápisem:

$xml->channel

Tímto způsobem můžeme v úrovni XML přeskočit několik úrovní a podívat se třeba na název kanálu:

$xml->channel->title

Tento zápis nám již rovnou vrátí název kanálu v souboru RSS, protože element title už obsahuje jen text. V případě, že element obsahuje další podelementy, není mapován na řetězec, ale na pole objektů, které reprezentují jednotlivé podelementy. K druhé položce kanálu se proto dostaneme zápisem:

$xml->channel->item[1]

Všimněte si, že číslování začíná od nuly, jak je v PHP u polí obvyklé. Analogicky tak můžeme získat i název druhé položky v kanálu:

$xml->channel->item[1]->title

Obrázek 2. V SimpleXML jsou jednotlivé části XML reprezentovány jako objekty a jejich členské proměnnéKosek

SimpleXML zpřístupňuje nejen elementy a jejich obsah, ale i atributy. Atributy jsou reprezentovány asociativním polem, které je dostupné na objektu odpovídajícího elementu. Např. atribut version u elementu rss získáme pomocí zápisu:

$xml['version']

Díky jednoduchému principu knihovny SimpleXML není problém načíst dokument RSS a vytvořit z něj webovou stránku, jak ukazuje příklad.

Příklad 2. Čtení XML pomocí SimpleXML – simplexml.php

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

$xml = simplexml_load_file("../data/luparss.xml");

?>

    <h1>Přehled aktuálních zpráv ze serveru
      <a href="<?php echo htmlspecialchars($xml->channel->link, ENT_QUOTES)?>"><?php echo htmlspecialchars($xml->channel->title)?></a>
    </h1>

    <dl>
<?php

foreach($xml->channel->item as $zprava)
{
  echo "<dt><a href='" . htmlspecialchars($zprava->link, ENT_QUOTES) . "'>" . htmlspecialchars($zprava->title) . "</a></dt>n";
  echo "<dd>" . htmlspecialchars($zprava->description) . "</dd>n";
}

?>
    </dl>
  </body>
</html>

Příklad si zaslouží jistě pár komentářů. Můžeme si všimnout, že na veškeré vypisované hodnoty pocházející z dokumentu XML aplikujeme funkci htmlspecialchars(). Ta zajistí, že znaky, které mají v HTML speciální význam (např. & a <), se do výstupu zapíší jako odpovídající entity &amp;&lt;.

Uvnitř hodnoty atributu se v HTML nesmí vyskytovat znak uvozovky, resp. apostrofu v závislosti na tom, jaký znak je použit pro uzavření hodnoty atributu. Při generování atributů proto funkci htmlspecialchars() předáváme jako druhý parametr konstantu ENT_QUOTES, která zajistí, že na entity se převedou i znaky uvozovek a apostrofů.

Jednotlivé položky uvnitř kanálu se opakují, a proto je nejjednodušší je zpracovat pomocí cyklu:

foreach($xml->channel->item as $zprava)

Uvnitř cyklu pak bude proměnná $zprava postupně obsahovat objekty odpovídající jednotlivým elementům  item.

Knihovna SimpleXML je díky své jednoduchosti velmi oblíbená. Hodí se zejména pro zpracování menších dokumentů s jednoduchou a pravidelnou strukturou. Naopak práce s dokumenty, které používají jmenné prostory nebo smíšený obsah, už v SimpleXML tak bezproblémová není.

V příštím díle seriálu se podíváme na rozhraní SAX, které je v PHP nejdéle, ale také nabízí nejméně komfortní práci s XML.

Více informací o knize naleznete na stránkách nadavatelství Grada a na stránkách autora.
V rámci konference WebExpo 2009 proběhne autogramiáda knihy.

Komentáře

Subscribe
Upozornit na
guest
5 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
Jarda

Jde nějak rozumně otestovat, jestli je XML v pořádku? Protože simplexml_load_file při špatném XML umře na Fatal a není cesty zpět.

Ondra

V PHP nápovědě je tomu věnována celá stránka (přímo u SimpleXML)

http://cz2.php.net/…s-errors.php

michal.kocarek

Pokud i přesto potřebujete načíst non well-formed XML document, můžete nastavit parametr $options funkci simplexml_load_fi­le() nebo simplexml_load_strin­g() na některou z LIBXML_ERR_* konstant.

Pokud chcete chyby v XML kompletně ignorovat a načíst, co se dá :), tak mě osobně se vždy osvědčilo použití DOMDocument::lo­adHTML(), které právě tohle umí. (Do SimpleXML se to pak převede pomocí simplexml_impor­t_dom().)

michal.kocarek

PHP obsahuje dvě rozšíření vystavená nad libxml2: SimpleXML a DOMDocument.

Načtenou XML strukturu lze reprezentovat pomocí obou těchto rozhraní. SimpleXML umožňuje práci pouze s tagy, atributy a jejich (nesmíšeným) obsahem. Zatímco DOMDocument poskytuje rozhraní pro práci s kompletním dokumentem (umožňuje zpracovávat entity, komentáře, instrukce preprocesoru, at­p.).

PHP poskytuje dvě „zázračné“ funkce dom_import_sim­plexml() a simplexml_impor­t_dom(), které vrací referenci na předanou XML strukturu přes objekty druhé knihovny. Díky těmto funkcím můžete na jednu XML strukturu nahlížet přes obě knihovny (např. pomocí XPath v SimpleXML vybrat elementy a poté na ně aplikovat nějakou funkci z DOMDocumentu). A jelikož obě knihovny jsou vystaveny nad libxml2, tak volání těchto převodních funkcí nijak nezvýší paměťové nároky na uložení XML (struktura se v paměti neduplikuje).

tiso

Tú knihu som si akurát včera kúpil.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.