LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> Perl (135) - XML - čtení a zápis

Perl XML je univerzálním jazykem pro přenos nejrůznějších dokumentů. Jak si s jeho parsováním poradí Perl?

24.6.2011 00:00 | Jiří Václavík | Články autora | přečteno 6064×

Jazyk XML (Extensible Markup Language) netřeba dlouze představovat. Jde o značkovací jazyk, který se masivně používá pro přenos dokumentů. Příklad XML dokumentu je k vidění na Wikipedii.

Nyní budeme zkoumat nástroje, které dokáží v našich programech s XML pohodlně zacházet. Díky oblibě XML jich je k dispozici celá řada.

Základním nástrojem pro nejjednodušší operace s XML daty je modul XML::Simple z archivu modulů CPAN. XML::Simple umí jedinou věc - konvertuje XML data do datové struktury Perlu a naopak.

Hned na úvod poznamenejme, že XML::Simple má jeden zásadní nedostatek. Nelze mixovat obsah a elementy uvnitř jednoho elementu. S tím si XML::Simple neporadí a je třeba použít něco silnějšího.

Další potenciální slabinou XML::Simple je, že je náročný na paměť a u extrémně velkých souborů to může působit problémy. S tím souvisí i to, že nelze zpracovávat data dávkově. K tomu slouží specializované moduly, které pracují s nástrojem zvaným SAX.

Modul XML::Simple obsahuje dvě hlavní metody. XMLin pro načtení XML souboru a naopak XMLout pro export do XML.

Čtení XML dat

Budeme na chvíli pracovat s následujícím souborem.

<?xml version="1.0" encoding="UTF-8"?>
<katalog>
  <kniha id="1">
    <nazev>Stopařův průvodce Galaxií 1.</nazev>
    <autor>Adams Douglas</autor>
    <foto src="stoparuv.jpg" alt="Titulní strana - Stopařův průvodce"/>
    <popis>
      Nezapomeňte: <citace>ručník je dost možná tou nejužitečnější věcí ve vesmíru</citace>.
    </popis>
    <cena>319</cena>
  </kniha>
  <kniha id="2">
    <nazev>Alchymista</nazev>
    <autor>Coelho Paulo</autor>
    <foto src="alchymista.jpg" alt="Titulní strana - Alchymista"/>
    <popis>
      Cesta za pokladem.
    </popis>
    <cena>399.90</cena>
  </kniha>
</katalog>

Podívejme se na úvod, jak tedy načteme XML soubor katalog.xml.

use XML::Simple;
use Data::Dumper;
$katalog = XMLin("katalog.xml");
print Dumper $katalog;

Zároveň jsme díky modulu Data::Dumper vytiskli strukturu právě vytvořené proměnné $katalog.

$VAR1 = {
          'kniha' => {
                     '1' => {
                            'foto' => {
                                      'alt' => "Titulní strana - Stopařův průvodce",
                                      'src' => 'stoparuv.jpg'
                                    },
                            'autor' => 'Adams Douglas',
                            'popis' => {
                                       'citace' => "ručník je dost možná tou nejužitečnější věcí ve vesmíru",
                                       'content' => [
                                                      "
      Nezapomeňte: ",
                                                      '.
    '
                                                    ]
                                     },
                            'nazev' => "Stopařův průvodce Galaxií 1.",
                            'cena' => '319'
                          },
                     '2' => {
                            'foto' => {
                                      'alt' => "Titulní strana - Alchymista",
                                      'src' => 'alchymista.jpg'
                                    },
                            'autor' => 'Coelho Paulo',
                            'popis' => '
      Cesta za pokladem.
    ',
                            'nazev' => 'Alchymista',
                            'cena' => '399.90'
                          }
                   }
        };

Jako parametr XMLin jsme uvedli jméno souboru. Kdybychom použili metodu bez argumentů, hledal by se soubor stejného názvu jako skript (přesněji __FILE__) s tím, že by se přípona pozměnila na .xml. Další možností je vložit přímo řetězec ve formátu XML.

Modul funguje i s objektovým přístupem.

XML::Simple->new()->XMLin("neco.xml")

Uveďme zde ještě pár poznámek, jak se data ukládají. Především, ukládání do datové struktury je ztrátové, ale není to nic kritického. Na několika příkladech si nyní vysvětlíme, jak konverze probíhá. Podle nich uvidíme, kde dochází k nejednoznačnostem, které se potom pokusíme odstranit. Ne u všech to půjde.

Uvnitř elementu může být buď text nebo další struktura elementů. Je-li tam text, pak se též objeví jako příslušná hodnota hashe. V opačném případě bude touto hodnotou nějaká další anonymní datová struktura.

Pokud máme XML opakované elementy, pak jsou položky (knihy) reprezentovány jako prvky anonymního pole.

<kniha>...</kniha>
<kniha>...</kniha>
...

Pokud je rozlišíme parametrem s názvem id (tak jsme to udělali v případě knih i v úvodním příkladu), pak se ukládají jako hash tvaru {1=>{...}, 2=>{...}, ...}.

<kniha id=1>...</kniha>
<kniha id=2>...</kniha>
...

Dodejme ještě, že úplně stejně by se do datové struktury uložilo následující.

<kniha><id>1</id>...</kniha>
<kniha><id>2</id>...</kniha>
...

Nabízí se otázka: Jde celé toto "chytré" chování nějak obejít? Odpověď je: Ano, stačí data načítat s parametrem ForceArray => 1. Výsledná datová struktura je složitější a strukturou více popisuje vstupní data.

XMLin("ukazka.xml", ForceArray => 1);

Opět zde narážíme na nedostatky XML::Simple. Vždy jde o to, co vlastně chceme. Pokud jen chceme získat několik jednotlivých dat a nejednoznačnosti nejsou podstatné, bude se lépe pracovat s původní verzí (avšak zde poznamenejme, že robusnější řešení nabízí xPath). Pokud chceme XML upravit a uložit, bude lepší využít ForceArray, neboť výsledné XML by se pak mohlo hodně změnit (to uvidíme podrobněji dále).

Dalších parametrů je celá řada. Pro další informace se odkažme na dokumentaci.

Ještě si všimněme, jak se element <citace></citace> objevil ve výsledné datové struktuře. Již jsme na to narazili v úvodu. Pokud se uvnitř elementu objevuje text (což je zde fyzicky obsah elementu <content></content>) a další elementy, pak XML::Simple vůbec neumí rozlišit jejich pořadí. Měli bychom tedy použít nějaký jiný nástroj.

Práce s jednotlivými daty a xPath

Samozřejmě můžeme pomocí pravidel pro datové struktury tisknout i konkrétní skaláry. Například následující volání má za následek vytisknutí autora 1. knihy v seznamu.

print $katalog->{kniha}->{1}->{autor};

Pravdou však je, že to není příliš pohodlné. Je ale třeba si uvědomit, že pro tisk jakýchkoliv dat je uvedení cesty k nim nezbytné. Přirozenou otázkou je, zda neexistuje nějakým způsobem standardizovaná cesta k jednotlivým datům ve formě řetězce. Ano, samozřejmě již existuje a daný jazyk se nazývá xPath.

Nebudeme se jím podrobně zabývat, pouze si uvedeme příklad. Na CPANu je řada modulů, které xPath podporují. Uveďme například XML::XPath::Simple. Autora první knihy zde získáme takto.

use XML::XPath::Simple;
$xpath = new XML::XPath::Simple(xml => "ukazka.xml");
print $xpath->valueof("/katalog/kniha[1]/autor");

Pro zájemce o xPath je k dispozici například tutoriál na w3schools.com.

Zápis XML dat

Nyní bychom samozřejmě mohli s touto strukturou pracovat. To zatím ponechme stranou a podívejme se, jak z datové struktury vytvoříme XML.

O výstup do XML dat se stará Metoda XMLout. Vytiskněme na úvod naši datovou strukturu $katalog na standardní výstup ve formátu XML.

print XMLout($katalog);

Výstup nás možná překvapí, protože náš původní XML soubor vypadal trochu jinak. Důvod jsme již uvedli. Struktura dat nicméně zůstává stejná.

<opt>
  <kniha name="1" autor="Adams Douglas" cena="319" nazev="Stopařův průvodce Galaxií 1.">
    <foto alt="Titulní strana - Stopařův průvodce" src="stoparuv.jpg" />
    <popis citace="ručník je dost možná tou nejužitečnější věcí ve vesmíru">
      <content>
      Nezapomeňte: </content>
      <content>.
    </content>
    </popis>
  </kniha>
  <kniha name="2" autor="Coelho Paulo" cena="399.90" nazev="Alchymista" popis="
      Cesta za pokladem.
    ">
    <foto alt="Titulní strana - Alchymista" src="alchymista.jpg" />
  </kniha>
</opt>

Předně, velmi záleží na tom, zda jsme načetli XML soubor s parametrem ForceArray. Předcházející soubor nám vznikl bez ForceArray. Jeho nastavením získáme lehce změněný výstup, který je podobnější úvodní verzi.

<opt>
  <kniha name="1">
    <autor>Adams Douglas</autor>
    <cena>319</cena>
    <foto alt="Titulní strana - Stopařův průvodce" src="stoparuv.jpg" />
    <nazev>Stopařův průvodce Galaxií 1.</nazev>
    <popis>
      <citace>ručník je dost možná tou nejužitečnější věcí ve vesmíru</citace>
      <content>
      Nezapomeňte: </content>
      <content>.
    </content>
    </popis>
  </kniha>
  <kniha name="2">
    <autor>Coelho Paulo</autor>
    <cena>399.90</cena>
    <foto alt="Titulní strana - Alchymista" src="alchymista.jpg" />
    <nazev>Alchymista</nazev>
    <popis>
      Cesta za pokladem.
    </popis>
  </kniha>
</opt>

Nastavením dodatečných parametrů pro metodu XMLout můžeme docílit ještě dalších změn.

Parametrem KeepRoot => 0 se zbavíme obalujícího elementu <opt></opt>.

Také se nám cestou ztratila úvodní deklarace z XML souboru. Můžeme ji doplnit parametrem XMLDecl => "<?xml version='1.0'?>".

Abychom nemuseli vrácený řetězec složitě zapisovat do souboru, lze užít také parametr OutputFile => 'novy_katalog.xml', který vytiskne výsledek do uvedeného souboru na místo standardního výstupu. Výsledné volání nyní vypadá takto.

XML::Simple::XMLout($katalog, 
    KeepRoot   => 0, 
    XMLDecl    => "<?xml version='1.0'?>",
    OutputFile => "new.xml",
);

Verze pro tisk

pridej.cz

 

DISKUZE

Nejsou žádné diskuzní příspěvky u dané položky.



Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

24.7.2014 7:19 /MaReK Olšavský
Na stránkách OpenSource.com vyšel příjemný příběh o startu malé firmy díky F/L/OSS. Za pozornost stojí i tyto malé příběhy, nejen přechody států a velkých firem na svobodná řešení, či svobodné formáty (jímž je i aktuální přechod Spojeného Království).
Přidat komentář

24.7.2014 7:19 /MaReK Olšavský
Mozilla hodlá soupeřit s Googlem i v segmentu „minipočítačů do HDMI“. soupeř Chromecastu, ale s Firefox OS. Podle informací, jež jsou aktuálně k dispozici, by příchod takového zařízení nemusel trvat dlouho.
Přidat komentář

24.7.2014 7:19 /MaReK Olšavský
Oracle již vydal svůj klon RHEL 7, který však není „pouze rekompilací“ s jinými značkami (jako mnohem populárnější a známější CentOS, či Scientific Linux), ale má i vlastní přidanou hodnotu v Ksplice, nebo vlastním jádře. Pokud uživatel/správce nemá dostatek financí na zaplacení RHELu 7, může být Oracle Linux lepší možností, než CentOS, či Scientific, ale „zaplatí“ minimálně vydáním svých údajů firmě Oracle.
Komentářů: 1

23.7.2014 7:25 /MaReK Olšavský
NVidia opravdu vstoupila na trh tabletů modelem Shield Tablet, za cenu US$ 299 (za ovladač se platí dalších US$ 59). V tabletu je mikroprocesor Tegra K1 (Cortex-A15 jádro, výroba nVidia), FullHD display a 16&bnsp;GB velké úložiště. Nejedná se o zástupce levných tabletů s Androidem, cílovou skupinou kupujících by měli být hráči.
Přidat komentář

23.7.2014 7:25 /MaReK Olšavský
Po odchodu Jono Bacona musel Canonical přestavět strukturu teamu, v němž již není jediný „komunitní manager“. Ubuntu není malou distribucí a pro řízení jejího vývoje je potřeba mnohem více lidí.
Přidat komentář

22.7.2014 6:32 /MaReK Olšavský
PHP 6 mělo být již před několika lety, blížící se PHP 5.6 (aktuálně je v RC2) nabízí snad vše, co mělo obsahovat PHP 6. Vzhledem k aktuálnímu stavu je pravděpodobné, že přístí „velkou“ verzí bude PHP 7, verze 6 se v číselné řadě přeskočí.
Přidat komentář

22.7.2014 6:32 /MaReK Olšavský
Pokud používáte CentOS 6.x a chcete přejít na novou řadu, mohl by vám pomoci krátký návod o několika drobných krocích. Na CentOS 7 mohou přejít jen ti, jež jej provozují na architektuře x86-64, podpora 32 bitového x86 a ARM by měla přijít se zpožděním.
Přidat komentář

21.7.2014 6:46 /MaReK Olšavský
EFF ohlásila Open Wireless Router, (zatím) experimentální firmware pro bezdrátové routery. Firmware umožňuje vytvoření pomalého otevřeného WiFi připojení pro návštěvníky, vedle sítě pro běžné uživatele, to vše při zachování maximální bezpečnosti a soukromí.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

24.7.2014 8:06 / Stanislav David
ksplice

15.7.2014 6:16 / MaReK Olšavský
2017

25.6.2014 19:04 / Petr Ježek
více argumentů

25.6.2014 19:01 / Petr Ježek
nejde o ideologii

25.6.2014 6:41 / DoubleR
Naprogramování ATmega328

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2014) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze | zákony online