Klasa SimpleXML służy do przetwarzania dokumentów XML. Artykuł opisuje podstawowe wykorzystanie tej klasy oraz przedstawia dwa przykłady przetwarzania dokumentów XML dostępnych w internecie: kursów walut NBP oraz listy książek wydawnictwa Helion.
Klasa SimpleXML
Klasa SimpleXML służy do przetwarzania dokumentów XML. Obiekty SimpleXML tworzą drzewo, którego struktura odpowiada strukturze kodu XML. Każdemu elementowi XML odpowiada jeden obiekt SimpleXML, zaś atrybuty są zwracane w postaci tablicy asocjacyjnej.
Konstruktor {stala}SimpleXMLElement{/stala} oraz funkcje {stala}simplexml_load_file(){/stala} i {stala}simplexml_load_string(){/stala} tworzą drzewo obiektów SimpleXML na podstawie kodu XML podanego jako parametr. Metoda {stala}asXML(){/stala} działa w odwrotną stronę. Generuje kod XML drzewa obiektów dla którego została wywołana.
Do modyfikowania drzewa obiektów służą metody {stala}AddChild(){/stala} oraz {stala}AddAttribute(){/stala}. Pozwalają one na dodawanie węzłów i atrybutów.
Metoda {stala}xpath(){/stala} służy do wyszukiwania danych przy użyciu zapytań XPath, zaś funkcja {stala}simplexml_import_dom(){/stala} umożliwia konwersję formatu DOMDocument do formatu SimpleXML.
Pełne zestawienie metod klasy SimpleXML jest zawarte w załączonej tabeli.
Tworzenie obiektu SimpleXMLElement
Obiekt SimpleXMLElement możemy utworzyć na podstawie pliku XML lub napisu.
Funkcja {stala}simplexml_load_file(){/stala} pobiera jako parametr nazwę pliku XML. Podawany parametr może być adresem URL lub ścieżką lokalną:
$aparaty = simplexml_load_file(\'dane.xml\');
Funkcja {stala}simplexml_load_string(){/stala} tworzy obiekt {stala}SimpleXMLElement{/stala} na podstawie napisu. Dzięki temu kod XML może pochodzić z dowolnego źródła (np. z bazy danych), a nie tylko z pliku:
$str = file_get_contents(\'dane.xml\');
$aparaty = simplexml_load_string($str);
Konstruktor klasy {stala}SimpleXMLElemen{/stala}t pozwala na korzystanie z obu powyższych metod. Aby utworzyć obiekt na podstawie pliku, konstruktor wywołujemy z trzema parametrami:
$aparaty = new SimpleXMLElement(\'dane.xml\', null, true);
Jeśli natomiast przekazujemy do konstruktora napis, stosujemy jeden parametr:
$str = \'
...
\';
$aparaty = new SimpleXMLElement($str);
Dostęp do węzłów drzewa
Plik o nazwie {stala}data.xml{/stala} ma zawartość:
12
2
2008
Po wywołaniu:
$d = simplexml_load_file(\'data.xml\');
// obiekt $d będzie zawierał składowe:
$d->dzien
$d->miesiac
$d->rok
o wartościach:
12
2
2008
Nazwę elementu głównego (tj. {html}…{/html}) zwraca metoda {stala}getName(){/stala}:
echo $d->getName();
Składowe możemy przetwarzać pętlą {stala}foreach{/stala}, wykorzystując metodę {stala}children(){/stala}, która zwraca tablicę obiektów {stala}SimpleXMLElement{/stala} reprezentujących elementy potomne:
foreach ($d->children() as $child) {
echo $child;
}
Nazwę elementów {stala}$child{/stala} przetwarzanych w pętli możemy ustalić metodą getName():
$child->getName()
lub korzystając z rozszerzonej składni pętli foreach:
foreach ($d->children() as $nazwa => $wartosc) {
echo $nazwa;
echo \' = \';
echo $wartosc;
}
Lista identycznych elementów
Jeśli kod XML zawiera listę identycznych elementów, wtedy wszystkie elementy o tej samej nazwie (i stojące w relacji rodzeństwo) zostaną umieszczone w jednej tablicy. Plik {stala}imiona.xml{/stala} zawiera listę elementów {stala}imie{/stala}:
Alicja
Jan
Aleksander
...
Po odczytaniu pliku:
$imiona = simplexml_load_file(\'imiona.xml\');
zmienna {stala}$imiona{/stala} będzie zawierała składową {stala}imie{/stala} (tj. {stala}$imiona->imie{/stala}). Składowa ta jest tablicą. Dostęp do pierwszego imienia (tj. Alicja) uzyskamy stosując indeks 0:
echo $imiona->imie[0];
Pod indeksem 2
echo $imiona->imie[2];
znajdziemy imię Aleksander itd. Całą tablicę możemy przetworzyć w pętli {stala}foreach{/stala}:
foreach ($imiona->imie as $imie) {
echo $imie;
}
Dostęp do atrybutów
Atrybuty elementu są zwracane w postaci tablicy asocjacyjnej przez metodę {stala}attributes(){/stala}. Jeśli dokument {stala}aparaty.xml {/stala}ma postać:
EOS 5D
D3
wówczas po utworzeniu obiektu {stala}$aparaty{/stala}:
$aparaty = simplexml_load_file(\'aparaty.xml\');
każdy element tablicy {stala}$aparaty->aparat{/stala} będzie zawierał własne atrybuty. Dostęp do nich uzyskamy wywołując metodę {stala}attributes(){/stala}.
Atrybuty pierwszego aparatu możemy przypisać do tablicy {stala}$atrs{/stala}:
$atrs = $aparaty->aparat[0]->attributes();
Indeksami w zwracanej tablicy są nazwy atrybutów, a wartościami – wartości atrybutów. Instrukcje:
echo $atrs[\'producent\'];
echo $atrs[\'model\'];
wydrukują napisy:
Canon
12.7
Wszystkie atrybuty elementu możemy przetworzyć w pętli {stala}foreach{/stala}:
$atrs = $aparaty->aparat[0]->attributes();
foreach ($atrs as $atr) {
echo $atr;
}
Przetwarzanie wszystkich elementów i ich atrybutów
Wykorzystując pętlę {stala}foreach{/stala} dwukrotnie – raz do przetworzenia tablicy elementów, drugi raz do przetworzenia tablicy atrybutów – możemy dokument XML zamienić w dwupoziomową listę ul. Po odczytaniu z pliku {stala}pracownicy.xml{/stala} listy pracowników:
Jan Kowalski
Anna Nowak
przetwarzamy wszystkie elementy i ich atrybuty:
$pracownicy = simplexml_load_file(\'pracownicy.xml\');
echo \'
- \';
foreach ($pracownicy->pracownik as $p) {
echo \'
- \' . $p . \'
- \';
foreach ($p->attributes() as $atr) {
echo \'
- \' . $atr . \' \'; } echo \'
\';
}
echo \'
Wielokrotne zagnieżdżenia
Elementy XML mogą być zagnieżdżone wielokrotnie. W takiej sytuacji kolejne poziomy zagnieżdżeń stają się składowymi kolejnych składowych. Plik {stala}tcs.xml{/stala} o treści:
1953
1
Josef
Bradl
Austria
...
...
...
...
zawiera dziewięć różnych elementów: {stala}turniejCzterechSkocznii{/stala}, {stala}zawody{/stala}, {stala}rok{/stala}, {stala}miejsce{/stala}, {stala}numer{/stala}, {stala}sportowiec{/stala}, {stala}imie{/stala}, {stala}nazwisko{/stala}, {stala}kraj{/stala}.
Po odczytaniu pliku obiekt {stala}$tcs{/stala}:
$tcs = simplexml_load_file(\'tcs.xml\');
będzie miał składową tablicową {stala}$tcs->zawody{/stala}. W elemencie {stala}$tcs->zawody[0]{/stala} będą dostępne dane pierwszych zawodów, w elemencie {stala}$tcs->zawody[1]{/stala} – drugich itd.
Każdy element tablicy {stala}$tcs->zawody{/stala} będzie zawierał składowe rok oraz miejsce, np.:
$tcs->zawody[0]->rok
$tcs->zawody[0]->miejsce
Składowa miejsce będzie tablicą zawierającą zwycięzców konkursu. Pierwszy zwycięzca będzie dostępny jako:
$tcs->zawody[0]->miejsce[0]
drugi jako:
$tcs->zawody[0]->miejsce[1]
Zwycięzca będzie dalej miał składowe {stala}numer{/stala} oraz {stala}sportowiec{/stala}, zaś składowa {stala}sportowiec{/stala} będzie zawierała składowe {stala}imie{/stala}, {stala}nazwisko{/stala} oraz {stala}kraj{/stala}.
Struktura składowych obiektu {stala}$tcs{/stala} jest przedstawiona na rysunku obok. Składowe będące tablicami zawierają oznaczenie {stala}[]{/stala}.
Imię i nazwisko pierwszego zwycięzcy pierwszego konkursu znajdziemy w składowych:
$tcs->zawody[0]->miejsce[0]->sportowiec->imie
$tcs->zawody[0]->miejsce[0]->sportowiec->nazwisko
Skrypt:
echo \'
- \';
foreach ($tcs->zawody as $z) {
echo \'
- \';
echo $z->rok;
echo \'
- \';
foreach ($z->miejsce as $m) {
echo \'
- Miejsce \'; echo $m->numer; echo \': \'; echo $m->sportowiec->imie; echo \' \'; echo $m->sportowiec->nazwisko; echo \' (\'; echo $m->sportowiec->kraj; echo \') \'; } echo \'
\';
}
echo \'
przetwarza dane pochodzące z turnieju czterech skoczni z formatu XML w dwupoziomową listę wypunktowaną.
Język XPath
Metoda {stala}xpath(){/stala} pozwala na wydawanie zapytań XPath. Jeśli w dokumencie {stala}tcs.xml{/stala}, zawierającym dane turnieju czterech skoczni, zechcemy wybrać zwycięzców (czyli osoby, które zajęły pierwsze miejsce), to zadanie to zrealizuje zapytanie XPath w postaci:
zawody/miejsce[numer=1]/sportowiec
Wystarczy odczytać dokument {stala}tcs.xml{/stala}, a następnie wydać zapytanie Xpath:
$tmp = simplexml_load_file(\'tcs.xml\');
$osoby = $tmp->xpath(\'zawody/miejsce[numer=1]/Sportowiec\');
Otrzymamy tablicę obiektów {stala}SimpleXMLElement{/stala} odpowiadających elementowi sportowiec w kodzie XML. Tablicę {stala}$osoby{/stala} możemy zamienić np. w listę ul:
echo \'
- \';
foreach ($osoby as $o) {
echo \'
- \'; echo $o->imie; echo \' \'; echo $o->nazwisko; echo \' (\'; echo $o->kraj; echo \') \'; } echo \'
Przykładowe dokumenty XML dostępne w internecie
Kursy walut
Pod adresem http://www.nbp.pl/Kursy/KursyA.html znajdziemy zestawienie kursów walut publikowane przez Narodowy Bank Polski. Stosowany format XML jest następujący:
29/A/NBP/2008
2008-02-11
bat (Tajlandia)
1
THB
0,0756
dolar amerykański
1
USD
2,4906
...
Przetwarzanie rozpoczynamy od odczytania dokumentu XML:
$kursy = simplexml_load_file(\'http://www.nbp.pl/kursy/xml/a029z080211.xml\');
Następnie na podstawie atrybutów elementu głównego oraz elementów {stala}data_publikacji{/stala} i {stala}numer_tabeli{/stala} uzyskujemy szczegółowy opis zestawienia:
$rob = $kursy->attributes();
echo \'Kurs z dnia: \';
echo $kursy->data_publikacji;
echo \'Typ: \';
echo $rob[\'typ\'];
echo \'Numer tabeli: \';
echo $kursy->numer_tabeli;
Następnie przetwarzamy tablicę {stala}$kursy->pozycja{/stala}, która zawiera dane poszczególnych walut:
echo \'
\'; echo $pozycja->nazwa _ waluty; echo \' | \'; echo \'\'; echo $pozycja->przelicznik; echo \' | \'; echo \'\'; echo $pozycja->kod _ waluty; echo \' | \'; echo \'\'; echo $pozycja->kurs _ sredni; echo \' | \'; echo \'
Książki wydawnictwa Helion
Pod adresem http://helion.pl/plugins/xml/lista.cgi wydawnictwo Helion publikuje zestawienie wszystkich dostępnych książek. W dokumencie tym dane poszczególnych książek są zawarte w atrybutach elementów item:
...
Po odczytaniu dokumentu:
$h = simplexml_load_file(\'http://helion.pl/plugins/xml/lista.cgi\');
przetwarzamy tablicę {stala}$books->item{/stala}. Pobieramy wszystkie atrybuty kolejnej książki, po czym drukujemy autora, tytuł, numer ISBN oraz cenę:
foreach ($books->item as $book) {
$tmp = $book->attributes();
echo \'