2006.03_Generowanie kodu XML z pakietem XML_Serializer_[XML].pdf

(501 KB) Pobierz
440385809 UNPDF
PEAR
Generowanie kodu XML
z pakietem XML_Serializer
Aaron Wormus
Stopień trudności: ll l
Przedstawiamy kolejny bardzo przydatny
pakiet PEAR'owy, tym razem związany z XML.
W artykule pokażemy zastosowanie XML-owego
niezbędnika PHP, czyli pakietu XML_Serializer,
pozwalającego szybko i w łatwy sposób
generować dokumenty XML.
XML pod koniec lat 90., po-
wszechne podejście do tego
języka uległo poważnym zmianom. Spe-
cyikację XML pierwotnie opracowała gru-
pa robocza W3C złożona z przedstawicieli
wielu znanych korporacji informatycznych,
więc w marketingowej gorączce związanej
w utworzeniem nowego, rozszerzalnego
języka znaczników obsługa XML-a była
dodawana do wielu programów tylko po
to, by dołożyć najnowszy chwytliwy skrót
do opisu produktu.
Z biegiem lat gorączka ostygła i za-
częto używać XML-a do celów, do któ-
rych został stworzony. Obecnie można po-
wiedzieć, że XML zadomowił się na do-
bre w informatyce, a w dodatku znajdu-
je zastosowanie w miejscach, o których
się autorom pierwotnej specyikacji na-
wet nie śniło. Formaty XML-owe spotyka-
my na każdym kroku, od protokołów Web
Services poprzez eksport danych z apli-
kacji po standard Internet Content Syndi-
cation, a wraz z popularyzacją technolo-
gii AJAX XML coraz częściej pojawiają się
również na zwykłych stronach interneto-
wych. W obliczu wszechobecności XML-a
we współczesnej informatyce, umiejętność
tworzenia i parsowania kodu XML stała się
koniecznością dla każdego programisty.
Oczywiście XML znalazł również dro-
gę do świata PHP, gdzie zadomowił się na
dobre w różnorodnych zastosowaniach:
formatowaniu dokumentów, składowaniu
danych, protokołach SOAP i XML-RPC
i wielu innych.
W SIECI
1. http://pear.php.net/package/
XML_Serializer
– strona główna pakietu
XML_Serializer
2. http://xulplanet.com
– XULPlanet, ciekawa witry-
na o języku XUL
3. http://imdb.com
– IMDB, czyli Internet Movie
Data Base
Co należy wiedzieć...
Powinieneś się dobrze orientować
w tematyce XML.
Co obiecujemy...
Pokażemy jak generować różnego
rodzaju dokumenty XML z pomocą
pakietu XML_Serializer
76
www.phpsolmag.org
PHP Solutions Nr 3/2006
O d czasu stworzenia standardu
440385809.014.png 440385809.015.png
 
440385809.016.png 440385809.001.png 440385809.002.png 440385809.003.png
 
XML_Serializer
PEAR
Słowo o XML-u
Zanim zajmiemy się samym pakietem
XML_Serializer, nie zawadzi pokrótce
przyjrzeć się formatowi i strukturze doku-
mentów XML.
Twórcy specyikacji XML wzorowa-
li się na standardzie języka znaczników
SGML (ang. Standard General Markup
Language ), opracowanym jeszcze w la-
tach 80. jako format tekstowy nadają-
cy się do przetwarzania przez kompu-
ter. Ze względu na wysoki stopień ogól-
ności SGML był jednak językiem bar-
dzo skomplikowanym, stąd też potrze-
ba opracowania prostszej jego wersji,
nadającej się do wykorzystania w Inter-
necie i niewymagającej pełnego parse-
ra SGML do przetwarzania dokumentów.
XML jest więc podzbiorem języka SGML
i opiera się na podobnych do niego za-
łożeniach, ale z uwzględnieniem dodat-
kowych ograniczeń mających na celu
uproszczenie procesu parsowania.
Listing 1 przedstawia przykłado-
wy kod prostego dokumentu XML opi-
sującego moje ulubione ilmy. XML wy-
gląda znajomo dla każdego, kto zna
HTML. Nieprzypadkowo – oba języ-
ki są podzbiorami ogólniejszego forma-
tu SGML. Dokument zaczyna się od de-
klaracji XML, określającej wersję forma-
tu XML oraz metodę kodowania tekstu.
W przypadku dokumentów w Unikodzie,
w deklaracji XML należy umieścić atrybut
encoding = "utf-8" .
Ciało dokumentu XML stanowi je-
den znacznik nadrzędny, zawierają-
cy całą resztę dokumentu. W przykła-
dzie z Listingu 1 znacznikiem nadrzęd-
nym jest <movies> , w którym znajduje
się wiele znaczników <movie> . Na ra-
zie dokument nie zawiera zbyt dużo in-
formacji, może poza tym, że lubię ilmy
z dobrą ścieżką dźwiękową. Listing 2
przedstawia ten sam dokument roz-
budowany o dodatkowe znaczniki za-
gnieżdżone i atrybuty.
Specyikacja XML znacznie oczywi-
ście wykracza poza te proste przykłady,
ale dla potrzeb tego artykułu więcej infor-
macji o samym XML-u nie będziemy po-
trzebować.
Pakiet XML_Serializer nosi oznacze-
nie beta , jednak nie wynika ono z jako-
ści kodu, a jedynie sygnalizuje możli-
wość przyszłych zmian w API. Zgodnie
ze standardami PEAR, oznaczenie pa-
kietu jako stabilnego ( stable ) jest równo-
znacznie zamrożeniu API w celu utrzy-
mania kompatybilności. Z tego też wzglę-
du twórcy intensywnie rozwijanych pakie-
tów utrzymują je w stanie beta do czasu
osiągnięcia przez API dojrzałości gwa-
rantującej brak poważniejszych zmian
w przyszłości.
Praca z pakietem
XML_Serializer
Zanim zagłębimy się w mechanizmy
funkcjonowania pakietu XML_Seriali-
zer, przyjrzyjmy się kodowi pokazujące-
mu, jak łatwo generować kod XML z po-
mocą tego narzędzia (Listing 3). Zaczy-
namy od dołączenia pliku zawierającego
kod klasy XML_Serializer , po czym two-
rzymy tablicę zawierającą dane oraz ta-
blicę zawierającą opcje, na podstawie
których XML_Serializer będzie genero-
wać kod XML.
Tworząc instancję klasy XML_Serializer
przekazujemy konstruktorowi tablicę opcji,
Instalacja pakietu
XML_Serializer
XML_Serializer jest zależny od kilku in-
nych pakietów PEAR, więc instalacja
wymaga wykonania następującego po-
lecenia: pear install --alldeps xml_
serializer-beta . Spowoduje to zainstalo-
wanie pakietów: XML_Serializer, XML_Util
i XML_Parser.
Listing 3. Generowanie kodu XML z pomocą pakietu XML_Serializer
require_once 'XML/Serializer.php' ;
$movies = array ( "Piąty Element" , "High Fidelity" ) ;
$options = array ( 'rootName' = > 'movies' , 'defaultTagName' = > 'movie' ) ;
$serializer = & new XML_Serializer ( $options ) ;
$status = $serializer - > serialize ( $movies ) ;
$xml = $serializer - > getSerializedData () ;
header ( 'Content-type: text/xml' ) ;
echo $xml ;
Listing 1. Lista ulubionych ilmów
w prostym dokumencie XML
< ?xml version= "1.0" ? >
< movies >
< movie > Piąty Element < /movie >
< movie > High Fidelity < /movie >
< /movies >
Listing 4. Generowanie kodu XML w trybie simplexml
Listing 2. Lista ulubionych ilmów
z nieco bardziej szczegółowymi
informacjami
$movies = array ( 'movie' = > array ( 'Piąty Element' , 'High Fidelity' )) ;
$options = array ( 'rootName' = > 'movies' , 'mode' = > 'simplexml' ) ;
Listing 5. Dodawanie atrybutów do znaczników XML za pomocą
tablicy asocjacyjnej
< movies >
< movie name= "Piąty Element" >
< writer > Luc Besson < /writer >
< year > 1997 < /year >
< imdb > tt0119116 < /imdb >
< /movie >
< movie name= "High Fidelity" >
< writer > Nick Hornby < /writer >
< year > 2000 < /year >
< imdb > tt0146882 < /imdb >
< /movie >
< /movies >
$movies = array ( array ( 'attr' = > array ( 'name' = > 'Piąty Element' ) ,
"writer" = > "Luc Besson" ,
"year" = > "1997" ,
"imdb" = > "tt0119116" ) ,
array ( 'attr' = > array ( 'name' = > 'High Fidelity' ) ,
"writer" = > "Nick Hornby" ,
"year" = > "2000" ,
"imdb" = > "tt0146882" )) ;
$options = array ( 'rootName' = > 'movies' ,
'attributesArray' = > "attr" ,
'defaultTagName' = > 'movie' ) ;
PHP Solutions Nr 3/2006
www.phpsolmag.org
77
440385809.004.png
 
 
440385809.005.png 440385809.006.png 440385809.007.png
PEAR
XML_Serializer
Tabela 1. Niektóre opcje pakietu XML_Serializer
Nazwa Opis
indent Ciąg znaków używany do tworzenia wcięć
linebreak Znak nowej linii (domyślnie \n)
addDecl Dodanie deklaracji XML
encoding Kodowanie znaków w dokumencie
defaultTagName Domyślna nazwa używana w przypadku braku jawnie określonego znacznika
scalarAsAttribute Serializacja wszystkich wartości jako atrybutów; może dotyczyć tylko wybranych znaczników
indentAttributes Wyrównanie atrybutów w pionie w obrębie znacznika
addDoctype Dodanie deklaracji XML Doctype
doctype Ciąg znaków lub tablica z deklaracją Doctype
rootName Ciąg znaków z nazwą znacznika głównego
rootAttributes Atrybuty znacznika głównego
attributesArray Klucz wskazujący tablicę atrybutów dla znacznika macierzystego
contentName Klucz wskazujący wartość używaną jako treść znacznika macierzystego; opcja używana z attributesArray
commentName Treść komentarza
tagMap Odwzorowania nazw znaczników
mode Opcja trybu – ustawienie trybu simplexml spowoduje wykorzystanie klucza wartości macierzystej jako nazwy
znacznika
overrideOptions Pozwala opcjom ustawionym za pomocą setOption() lub setOptions() przesłaniać opcje przekazane w konstruktorze
po czym możemy pobrać dane seriali-
zowane do kodu XML wywołując metodę
getSerializedData() . Kod z Listingu 3
zwraca dane XML odpowiadające przy-
kładowi z Listingu 1. Opcje generowania
XML-a można też zmieniać już po utwo-
rzeniu instancji XML_Serializer za po-
mocą metod setOption() i setOptions() .
Jeśli opcje przekazane za pomocą
setOption() mają przesłonić opcje pier-
wotnie przekazane konstruktorowi, na-
leży ustawić parametr overrideOptions
na true .
Przyglądając się kodowi XML z do-
tychczasowych przykładów nietrudno do-
strzec podobieństwo między strukturą
drzewa znaczników XML a strukturą ta-
blicy asocjacyjnej w PHP. XML_Serializer
wykorzystuje to właśnie podobieństwo
– jak widać z przykładu, wystarczy tabli-
ca z danymi i kilka opcji określających
sposób generowania kodu XML.
Zapoznanie się ze wszystkimi do-
stępnymi opcjami jest istotnym elemen-
tem opanowania pakietu XML_Serializer.
Na podstawie tablicy danych można wy-
generować dowolnego rodzaju kod XML
– wystarczy tylko podać odpowiednie
opcje, a niekiedy dodatkowo zmodyiko-
wać strukturę tablicy, by dokładniej odpo-
wiadała strukturze pożądanego dokumen-
tu XML. Tabela 1 przedstawia najważniej-
sze opcje, z których wiele poznamy na
kolejnych przykładach. Dostępne są też
inne opcje, ale dla potrzeb tego artykułu
ich znajomość nie jest konieczna.
Listing 6. Kod XML wygenerowa-
ny z opcją traktowania wszystkich
wartości jako atrybutów
< movies >
< movie imdb= "tt0119116"
name= "Piąty Element"
writer= "Luc Besson"
year= "1997" / >
< movie imdb= "tt0146882"
name= "High Fidelity"
writer= "Nick Hornby"
year= "2000" / >
< /movies >
Tryby działania
W pierwszym przykładzie wykorzy-
staliśmy prostą tablicę jednowymiaro-
Listing 7. XML z dodatkowymi
informacjami o postaciach z ilmów
< movies >
< movie name= 'Piąty Element' >
< writer > Luc Besson < /writer >
< year > 1997 < /year >
< imdb > tt0119116 < /imdb >
< character name= 'Leeloo' >
< actor > Milla Jovovich < /actor >
< imdb > nm0000170 < /imdb >
< /character >
< character name= 'Korben Dallas' >
< actor > Bruce Willis < /actor >
< imdb > nm0000246 < /imdb >
< /character >
< /movie >
<!-- ... -->
< /movies >
Rysunek 1. Interfejs dla skryptu pobierającego dane o ilmach z bazy IMDB
78
www.phpsolmag.org
PHP Solutions Nr 3/2006
440385809.008.png 440385809.009.png 440385809.010.png
XML_Serializer
PEAR
wą, a nazwy znaczników XML wska-
zaliśmy za pomocą opcji rootName
i defaultTagName . XML_Serializer po-
zwala też osiągnąć ten sam efekt w inny
sposób, co w naszym prostym przykła-
dzie nie jest może konieczne, ale bar-
dzo się przydaje w przypadku bardziej
złożonych dokumentów XML.
Za pomocą opcji mode możemy usta-
wić tryb działania simplexml , w którym z
każdą wartością tablicy kojarzona jest
nazwa klucza tablicy nadrzędnej, odpo-
wiadająca nazwie znacznika. W trybie
domyślnym można podać tylko jedną
wartość defaultTagName , podczas gdy
tryb simplexml pozwala jawnie określać
nazwy znaczników na poszczególnych
poziomach, co daje znacznie większą
kontrolę nad strukturą dokumentu XML.
Kod z Listingu 4 generuje identyczny
XML, jak przykład wcześniejszy, ale tym
razem korzystając z trybu simplexml .
Decyzja o wyborze trybu w dużym
stopniu zależy od rodzaju generowa-
nego kodu XML. Tryb domyślny jest ła-
twy w obsłudze i w wielu przypadkach
sprawdza się zupełnie dobrze, jednak
w przypadku bardziej złożonych doku-
mentów jedyną możliwością jest tryb
simplexml . Pewną wadą pracy w trybie
simplexml jest konieczność tworzenia
znacznie bardziej rozbudowanych ta-
blic danych.
XML_Serializer udostępnia kilka
metod pracy z atrybutami. Pierw-
szym sposobem jest wykorzysta-
nie opcji attributesArray , pozwalają-
cej na przekazanie klucza deiniujące-
go tablicę zawierającą nazwy i warto-
ści atrybutów, które mają być dodane
do znacznika macierzystego. W kodzie
z Listingu 5 klucz ten nosi nazwę attr .
Wskazanie tak przygotowanej tablicy
w opcjach przekazywanych obiekto-
wi klasy XML_Serializer daje w wyniku
kod XML z Listingu 2.
Dość często traia się kod XML,
w którym wszystkie wartości są składo-
wane jako atrybuty, czyli nie ma żadnych
wartości w obrębie samych znaczników.
Jeśli tak faktycznie jest, to można usta-
wić opcję scalarAsAttributes na true ,
co spowoduje traktowanie wszystkich
wartości kluczy w ramach danego znacz-
nika jako atrybutów. Listing 6 pokazuje
kod XML wygenerowany z tych samych
danych po podaniu tej opcji.
żemy w tej samej tablicy umieścić dwóch
kluczy o takiej samej nazwie character .
Moglibyśmy nie używać klucza, ale wte-
dy XML_Serializer użyłby klucza domyśl-
nego, któremu wcześniej przypisaliśmy
wartość movie – a zupełnie nie o to nam
chodzi.
Rozwiązanie problemu wymaga
przejścia we wspomniany wcześniej tryb
simplexml i modyikacji struktury tabli-
cy. Dla zwiększenia czytelności podzieli-
łem jedną rozbudowaną tablicę na dwie
mniejsze. W rzeczywistości dane bę-
dą najczęściej pobierane z zewnętrzne-
go źródła (na przykład bazy danych lub
usługi sieciowej), więc nie ma potrzeby
operowania na dużych i niewygodnych
tablicach zagnieżdżonych. Dla potrzeb
naszego przykładu tablice dobrze jednak
ilustrują proces generowania kodu wy-
nikowego – Listing 8 pokazuje deinicje
odpowiednich tablic.
Rzeczywisty przykład
Na tym etapie wiemy już, na czym pole-
ga generowanie kodu XML za pomocą
pakietu XML_Serializer, pora więc wyko-
rzystać tę wiedzę w praktyce i wygenero-
wać coś, co mogłoby się przydać w rze-
czywistych zastosowaniach. W tym ce-
lu wygenerujemy plik w formacie XUL
– schemacie XML używanym do dei-
niowania struktury interfejsu użytkowni-
ka w przeglądarkach z rodziny Mozilla.
Wykorzystamy tablicę danych z ostat-
niego przykładu, po czym podając od-
powiednie opcje przetworzymy ją do po-
staci poprawnego dokumentu XUL, któ-
Znaczniki zagnieżdżone
Mamy już całkiem porządną struktu-
rę dokumentu XML do składowania in-
formacji o ulubionych ilmach, ale przy-
dałoby się ją jeszcze nieco rozbudować
o informacje na temat głównych posta-
ci ilmu. Wymaga to dodania dla każdej
postaci zestawu znaczników ją opisują-
cych – Listing 7 przedstawia przykłado-
wy kod XML.
W tym momencie pojawia się pro-
blem: nie da się takiego dokumentu zapi-
sać w postaci tablicy PHP, gdyż nie mo-
Dodawanie atrybutów
Dotychczasowe przykłady generowały
bardzo prosty kod XML, więc w kolejnym
przykładzie pora wprowadzić atrybuty.
R E K L A M A
PHP Solutions Nr 3/2006
www.phpsolmag.org
79
440385809.011.png
PEAR
XML_Serializer
Listing 8. Tablica danych o ilmach po przebudowaniu do pracy w trybie simplexml
ry zostanie następnie zinterpretowany
przez przeglądarkę jako okno interfejsu
użytkownika z zakładkami zawierający-
mi dodatkowe informacje o ilmach po-
brane z bazy danych IMDB (Rysunek 1).
Listing 9 przedstawia kod realizujący to
zadanie.
Dane z tablicy $movies z poprzed-
niego przykładu są pobierane w pę-
tli foreach i używane do stworzenia no-
wej tablicy, na podstawie której zosta-
nie wygenerowany kod XUL. Niektóre
z opcji poznaliśmy już wcześniej, lecz
pojawia się również kilka nowych. Opcja
rootAttributes przyjmuje argument
w postaci tablicy określającej atrybuty dla
znacznika głównego – generujemy doku-
ment XUL, więc musimy podać odpo-
wiednią dla tego formatu wartość atrybu-
tu namespace . Dodatkowo nadałem oknu
tytuł Moje ulubione ilmy i ustawiłem
dwie spacje jako ciąg używany tworzenia
wcięć w kodzie XML (to oczywiście tylko
kosmetyka, ale dzięki temu kod jest bar-
dziej czytelny).
Listing 10 przedstawia kod XML gene-
rowany przez ten przykład, a na Rysun-
ku 1 widzimy ostateczną postać interfej-
su XUL wyświetlanego przez przeglądar-
ki Mozilla.
$characters = array (
array (
'attr' = > array ( 'name' = > 'Leeloo' ) ,
'actor' = > 'Milla Jovovich' ,
'imdb' = > 'nm0000170' ) ,
array (
'attr' = > array ( 'name' = > 'Korben Dallas' ) ,
'actor' = > 'Bruce Willis' ,
'imdb' = > 'nm0000246' )) ;
$movies = array ( 'movie' = > array ( array ( 'attr' = > array ( 'name' = >
'Piąty Element' ) ,
'writer' = > "Luc Besson" ,
'year' = > "1997" ,
'imdb' = > "tt0119116" ,
'character' = > $characters )) ;
$options = array (
'rootName' = > 'movies' ,
'attributesArray' = > "attr" ,
'mode' = > 'simplexml' ) ;
Listing 9. Kod generujący dokument z deinicją interfejsu XUL
$browser_data = array ( 'height' = > "400" , 'width' = > "550" ) ;
foreach ( $movies [ 'movie' ] as $m ){
$tabs [ "tab" ][] = array ( 'label' = > $m [ 'attr' ][ 'name' ] ." ({ $m [ 'year' ]}) ");
$url = " http://us.imdb.com/title/". $m [ 'imdb' ] ;
$movie_site = array ( "src" = > $url , "id" = > $m [ 'imdb' ]) ;
$tab [ 'label' ] = $m [ 'attr' ][ 'name' ] ;
$tab [ 'browser' ] = array_merge ( $browser_data , $movie_site ) ;
$tab_panels [ 'tabpanel' ][] = $tab ;
}
$data = array ( "tabbox" = > array ( "tabs" = > $tabs , "tabpanels" = > $tab_panels )) ;
$options = array ( 'addDecl' = > TRUE,
'rootName' = > 'window' ,
"defaultTagName" = > 'tab' ,
"scalarAsAttributes" = > true,
"mode" = > 'simplexml' ,
'indent' = > ' ' ,
'rootAttributes' = > array ( "xmlns" = >
"http://...is.only.xul" , "title" = > "Moje ulubione ilmy" )) ;
$serializer = &new XML_Serializer ( $options ) ;
$status = $serializer - > serialize ( $data ) ;
$xml = $serializer - > getSerializedData () ;
header ( 'Content-type: application/vnd.mozilla.xul+xml' ) ;
echo $xml ;
Podsumowanie
W tym krótkim artykule poznaliśmy zasa-
dy wykorzystania pakietu XML_Serializer
do tworzenia różnego rodzaju plików
XML. XML_Serializer to naprawdę świetny
pakiet i intensywnie korzystam z niego
w codziennej pracy. Istnieją wprawdzie
inne sposoby generowania kodu XML, ale
jak dotąd nie znalazłem żadnego rozwią-
zania, które sprawdzałoby się równie do-
brze i byłoby równie proste. Mam nadzieję,
że udało mi się pokazać możliwości tego
pakietu i że będzie on dla Czytelników
równie użyteczny, jak dla mnie. n
Listing 10. Kod XUL wygenerowany przez przykładowy skrypt
< ?xml version= "1.0" ? >
< window title= "Moje ulubione ilmy" xmlns= "http://www.mozilla.org/keymaster/
gatekeeper/there.is.only.xul" >
< tabbox >
< tabs >
< tab label= "Piąty Element (1997)" / >
< tab label= "High Fidelity (2000)" / >
< /tabs >
< tabpanels >
< tabpanel label= "Piąty Element" >
< browser height= "400" id= "tt0119116" src= "..." width= "550" / >
< /tabpanel >
< tabpanel label= "High Fidelity" >
< browser height= "400" id= "tt0146882" src= "..." width= "550" / >
< /tabpanel >
< /tabpanels >
< /tabbox >
< /window >
O autorze
Aaron Wormus programuje w PHP od
1999 r. Zajmował się tworzeniem roz-
wiązań intranetowych w Perlu i technolo-
giach pokrewnych. Aaron koncentruje się
na dostarczaniu przedsiębiorstwom wy-
sokiej jakości rozwiązań intranetowych
i wykorzystuje potęgę PHP w pracy kon-
sultanta.
Kontakt z autorem: aaron@wormus.com
80
www.phpsolmag.org
PHP Solutions Nr 3/2006
440385809.012.png 440385809.013.png
Zgłoś jeśli naruszono regulamin