01/2008
Narzędzia
54
XSLT
www.phpsolmag.org
55
X
SLT (ang. eXtensible Stylesheet Lan-
guage Transformations) to język
transformacji dokumentów XML.
Za jego pomocą możemy więc przetrans-
formować dane XML w jakąś inną postać,
na przykład w dokument HTML. To nato-
miast otwiera przed nami szereg nowych
opcji związanych z oddzieleniem treści stro-
ny od tagów HTML, możliwością generowa-
nia jak i wykorzystania plików XML przez
inne aplikacje webowe (mobilność danych)
i nie tylko. Zalety i wady XSLT przedstawi-
my jednak trochę później. Aby łatwiej było
nam zrozumieć całą ideę i sens stosowania
transformacji XSL, zaczniemy od prostego
przykładu, omawiając jednocześnie podsta-
wy tego języka.
Metoda 1. – XML + XSL
Pierwszym przykładem wykorzystania trans-
formacji XSL jest strona przedstawiająca spis
użytkowników serwisu wraz z kilkoma pod-
stawowymi informacjami o nich. Stwórzmy
więc plik
users.xml
o treści zaprezentowa-
nej na Listingu 1. Kod jest tutaj bardzo pro-
sty – niejasne mogą być jedynie dwie pierw-
sze linijki. Pierwsza to nagłówek informują-
cy o tym, że jest to plik XML (oraz ustalający
jego kodowanie). Druga natomiast jest odno-
śnikiem do pliku XSL, który za chwilę stwo-
rzymy. Dalsza część kodu to podstawowe in-
formacje o użytkownikach: nazwa użytkow-
nika (
nick
),
wiek
(age),
ranga
(rank) oraz
ilość postów na wyimaginowanym
forum
(posts). Na Listingu 1. zamieściliśmy tylko
trzech użytkowników, ale ich liczba oczywi-
ście może być dowolna.
Mamy więc dane, które chcemy wyświe-
tlić. Drugim krokiem jest stworzenie pliku
XSL mówiącego przeglądarce jak te dane po-
winny zostać wyświetlone. Aby ułatwić zro-
zumienie tego procesu dodajmy, że XSL dla
plików XML jest tym samym czym CSS dla
HTML. Można więc plik XSL nazwać arku-
szem stylów, jednak jego kod potrafi o wie-
le więcej – XSLT posiada struktury znane
z języków funkcyjnych, jak na przykład pę-
tle, czy instrukcje warunkowe. Plik XSL daje
więc nam pełną kontrolę nad generowanym
kodem strony.
Stwórzmy plik
users.xsl
, którego kod znaj-
duje się na Listingu 2. Trzy pierwsze linijki de-
klarują wersję i kodowanie pliku oraz informu-
ją, że jest to plik XSL. Element
xsl:template
tworzy nowy szablon, który (w naszym przy-
padku) zawiera cały właściwy kod generowanej
strony. Jeden plik XSL może zawierać wiele sza-
blonów, a każdy z nich może dotyczyć zupełnie
innej części drzewa pliku XML.
W naszym przypadku szablon wskazuje na
users (
<xsl:template match="users">
), czy-
li element zawierający wszystkie nasze dane
(jeśli nie wiesz o jakim elemencie mówimy,
przyjrzyj się dokładnie plikowi
users.xml
).
W dalszej części kodu przygotowujemy
tabelkę zawierającą informacje pobrane ze
stworzonego wcześniej pliku XML. Zwróć-
my szczególną uwagę na kod zawarty pomię-
dzy
<xsl:for-each select="user"> a </
xsl:for-each>
. Jest to pętla podobna do fore-
ach (znanej z PHP) – iteruje przez wszystkie
elementy o nazwie user dostarczając zawar-
tych w nich danych, które natomiast umiesz-
czamy w odpowiednich miejscach wiersza
tabelki. Dokonujemy tego za pomocą
<xsl:
value-of select="dziecko"/>
, gdzie dziec-
ko to nazwa elementu znajdującego się w ele-
mencie
user
.
W tym miejscu pragniemy zwrócić uwa-
gę czytelnika na sposób pobierania wartości
XSLT
Transformacje XSL to bardzo potężne i przydatne narzędzie, za pomocą
którego możemy m.in. łatwo oddzielić treść strony od kodu określającego
jej wygląd, zapewniając sobie możliwość wykorzystania tych samych
danych w różny sposób.
Dowiesz się...
• Co to jest XSLT i jak się tego używa;
• Poznasz różne metody wykorzystania XSLT;
• Poznasz wady i zalety transformacji XSL;
• Dowiesz się jak zoptymalizować generowanie
stron internetowych.
Powinieneś wiedzieć...
• Posiadać znajomość języków XML, XHTML
oraz PHP;
• Mieć doświadczenie w programowaniu stron z
wykorzystaniem DOM.
Poziom trudności
Czy warto zamienić HTML na XML ?
Listing 1. Zawartość pliku users.xml
prezentującego listę użytkowników strony
<
?xml version=
"1.0"
encoding=
"UTF-8"
?
>
<
?xml-stylesheet type=
"text/xsl"
href=
"users.xsl"
?
>
<
users
>
<
user
>
<
nick
>
admin
<
/nick
>
<
age
>
23
<
/age
>
<
rank
>
Administrator
<
/rank
>
<
posts
>
190
<
/posts
>
<
/user
>
<
user
>
<
nick
>
abc
<
/nick
>
<
age
>
19
<
/age
>
<
rank
>
Ekspert
<
/rank
>
<
posts
>
1240
<
/posts
>
<
/user
>
<
user
>
<
nick
>
xyz123
<
/nick
>
<
age
>
15
<
/age
>
<
rank
>
Początkujący
<
/rank
>
<
posts
>
3
<
/posts
>
<
/user
>
<
/users
>
01/2008
Narzędzia
54
XSLT
www.phpsolmag.org
55
poszczególnych elementów pliku XML. Przy
bardziej skomplikowanych szablonach waż-
ne jest rozumienie takich pojęć jak: dziec-
ko (ang. child), rodzic (parent), przodek (ance-
stor), potomek (descendant) itd. Jest to bezpo-
średnio związane z faktem, że XSLT do wska-
zywania na różne części dokumentu wykorzy-
stuje język XPath.
Dlatego też, jeśli czytelnik nie jest zazna-
jomiony z wyżej wymienionymi pojęciami,
polecamy lekturę stron traktujących o tej te-
matyce – ich adresy zamieszczamy w ram-
ce W Sieci.
Korzystając z okazji, chcielibyśmy także
wspomnieć o jeszcze jednym, powiązanym
z naszym tematem (a dokładniej z XML),
standardzie W3C. Jest nim XML Sche-
ma Definition – w skrócie XSD (lub XML
Schema). Służy on do definiowania struktu-
ry dokumentu XML. Czytelnikom zaznajo-
mionym z DTD dodamy, że XSD jest uwa-
żany za jego następcę. Wszystkich zaintere-
sowanych tym tematem ponownie odsyłamy
do ramki W Sieci.
Teraz możemy sprawdzić efekty naszych
działań. Zobaczymy je uruchamiając stro-
nę
users.xml
w przeglądarce interneto-
wej (możemy to zrobić lokalnie; nie ma
potrzeby umieszczania plików na serwe-
rze). Oczom naszym ukaże się prosta tabel-
ka przedstawiająca informacje o fikcyjnych
użytkownikach zmyślonego serwisu.
Pierwszy krok w stronę poznania XSLT
mamy więc za sobą. Jak widać na powyż-
szym przykładzie, aby opanować umiejęt-
ność efektywnego korzystania z transfor-
macji XSL, musimy - poza zdolnością wy-
obrażania sobie dokumentu XML jako drze-
wa elementów (co jest pośrednio związane
ze znajomością wspomnianego wcześniej
XPath) – poznać tylko kilka podstawowych
reguł i definicji w nim panujących. Z trzema
jesteśmy już zaznajomieni – pojęcie szablo-
nu (
xsl:template
), pętli (
xsl:for-each
)
oraz pobierania wartości (
xsl:value-of
).
Metoda 2. – PHP + XML + XSL
Uważni czytelnicy studiując poprzedni
przykład, być może zwrócili uwagę na fakt,
że wynikowy kod strony (kod HTML) jest
generowany w locie. Faktycznie, w dodat-
ku dokonuje tego przeglądarka interneto-
wa użytkownika. Ma to swój plus (odciąże-
nie serwera), jak i minus (ryzyko niekompa-
tybilności).
O wadach i zaletach powiemy nieco póź-
niej; teraz zaprezentujemy drugi sposób wy-
korzystania XSLT, w którym brzemię gene-
rowania kodu wynikowego przerzucimy na
serwer.
PHP od wersji 5_ ma wbudowane wspar-
cie dla transformacji XSL (serwer PHP mu-
si być uruchomiony z opcją –
with-xsl
, a w
systemie konieczna jest obecność bibliote-
ki
libxslt
– więcej informacji na ten te-
mat zamieściliśmy w ramce Instalacja XSLT
w PHP5).
Możemy więc bez problemu wygenero-
wać kod HTML i wysłać go do przeglądar-
ki użytkownika. Taką właśnie metodę wyko-
rzystamy w drugim przykładzie. Potrzebuje-
my tylko jednego dodatkowego pliku PHP,
w którym dokonamy transformacji. Nazwij-
my go users.php. Kod PHP wraz z komenta-
rzami przedstawia Listing 3.
Czynności zawarte na tym Listingu spro-
wadzają się do wczytania pliku XML oraz
XSL (do tego celu wykorzystujemy jeden ze
standardowo dostępnych modułów PHP5,
zwany po prostu Document Object Model
– DOM), dokonania transformacji i osta-
tecznie wysłania efektu końcowego do prze-
glądarki. Widzimy więc, że całą pracę wyko-
nuje za nas PHP (a dokładniej obiekt XSLT-
Processor).
Tego przykładu oczywiście nie możemy
sprawdzić lokalnie, chyba że mamy uru-
chomione środowisko z obsługą PHP. W in-
nym przypadku musimy przesłać wszystkie
trzy pliki na serwer, a następnie otworzyć w
przeglądarce stronę users.php. Rezultat z te-
go jak i poprzedniego przykładu wydaje się
być taki sam, jednak wszystko się zmienia,
gdy zajrzymy do kodu źródłowego strony.
Możemy przekonać się na własne oczy, że
w pierwszym przypadku kod strony to plik
XML, a w drugim (wygenerowanym przez
PHP) rezultatem jest zwykły HTML.
Druga metoda zapewnia nam pełną kom-
patybilność z przeglądarkami nieobsługują-
cymi XSLT, jednak każdorazowe generowa-
nie strony w większym stopniu obciąża ser-
wer. Pierwsza metoda nie dokonuje dodat-
kowego narzutu, lecz decydując się na stoso-
wanie jej musimy pamiętać, że użytkownik
posiadający niekompatybilną przeglądarkę
nie będzie mógł korzystać z naszej strony.
Wyjścia z tej sytuacji są co najmniej dwa.
W dodatku oba mogą być stosowane jedno-
cześnie. Przestudiujemy je dokładnie trochę
później, teraz zaprezentujemy jeszcze jeden
– prawdopodobnie najbardziej interesujący
– sposób wykorzystania transformacji XSL.
Metoda 3.
– MySQL + PHP + XSL
Używanie XSLT mijałoby się z celem, gdy-
byśmy musieli ręcznie tworzyć pliki XML
zawierające treść naszych stron. Czemu
nie generować takich plików automatycz-
nie, pozyskując dane z bazy MySQL? Przy
przemyślanej konstrukcji serwisu taka me-
toda zapewni nam dużą elastyczność w spo-
sobie wyświetlania danych, nie pociągając
za sobą konieczności ingerencji w kod PHP.
Sprawdźmy więc, jak to wygląda w praktyce.
Naszym pierwszym krokiem jest stwo-
rzenie tabeli w bazie danych oraz zapełnie-
nie jej fikcyjnymi informacjami. Stwórzmy
więc teraz za jego pomocą nową tabelę w ba-
zie danych.
Następną czynnością jest napisanie skryp-
tu PHP, który pobierze dane, wygeneruje na
ich podstawie plik XML, dokona transfor-
Listing 2. Plik users.xsl dokonujący
formatowania danych XML
<
?xml version=
"1.0"
encoding=
"UTF-8"
?
>
<
xsl:stylesheet version=
"1.0"
xmlns:xsl=
"http://www.w3.org/1999/XSL/
Transform"
>
<
xsl:template match=
"users"
>
<
html
>
<
body
>
<
h2
>
Lista użytkowników
<
/h2
>
<
table
>
<
tr
>
<
th
>
Nazwa
<
/th
>
<
th
>
Wiek
<
/th
>
<
th
>
Ranga
<
/th
>
<
th
>
Postów
<
/th
>
<
/tr
>
<
xsl:for-each select=
"user"
>
<
tr
>
<
td
><
xsl:value-of select=
"nick"
/
><
/td
>
<
td
><
xsl:value-of select=
"age"
/
><
/td
>
<
td
><
xsl:value-of select=
"rank"
/
><
/td
>
<
td
><
xsl:value-of select=
"posts"
/
><
/td
>
<
/tr
>
<
/xsl:for-each
>
<
/table
>
<
/body
>
<
/html
>
<
/xsl:template
>
<
/xsl:stylesheet
>
Listing 3. Plik users.php generujący kod
HTML na podstawie dwóch poprzednich
plików
<?
php
// Wczytujemy plik XML
$xml
=
new DOMDocument
(
'1.0'
,
'UTF-8'
)
;
$xml
->
load
(
'users.xml'
)
;
// Wczytujemy arkusz XSL
$xsl
=
new DOMDocument
(
'1.0'
,
'UTF-8'
)
;
$xsl
->
load
(
'users.xsl'
)
;
// Podczepiamy arkusz XSL
$proc
=
new XSLTProcessor
;
$proc
->
importStyleSheet
(
$xsl
)
;
// Wyświetlamy kod HTML wygenerowany na
podstawie pliku
XML i arkusza
XSL
echo
$proc
->
transformToXML
(
$xml
)
;
?>
01/2008
Narzędzia
56
XSLT
www.phpsolmag.org
57
macji XSL oraz wyśle rezultat do przeglą-
darki użytkownika. Wszystkie te czynności
wykonuje kod zawarty na Listingu 4.
Poza nawiązaniem połączenia z bazą da-
nych (linijka 4. – nie zapomnij wstawić
swoich danych!), pobraniem informacji za-
pisanych w tabelce users (za pomocą me-
tody
$mysqli->query()
) oraz generowa-
niem kodu wyjściowego (trzy ostatnie blo-
ki kodu) , znanym z poprzedniego przykładu,
ten skrypt dokonuje jeszcze jednej, bardzo waż-
nej rzeczy. Jest nią oczywiście tworzenie doku-
mentu XML na podstawie danych z bazy My-
SQL, który zostaje następnie użyty do wyge-
nerowania rezultatu końcowego w postaci
strony HTML. Dość intensywnie używamy
w tym kodzie metod
createElement()
oraz
appendChild()
. O ile nazwa tej pierwszej
mówi wszystko, o tyle druga może wydać
się niejasna. Metoda
appendChild()
wsta-
wia nowy węzeł do struktury (drzewa) na-
szego pliku XML. Jako argument pobiera
element, który zostanie podczepiony do wę-
zła wywołującego tę metodę. Tym sposobem
umieszczamy wszystkie informacje o da-
nym użytkowniku do elementu
user
, któ-
ry natomiast wstawiamy do węzła główne-
go –
users
.
W tym miejscu chcielibyśmy raz jesz-
cze odciągnąć uwagę czytelnika od właści-
wego tematu artykułu i krótko wspomnieć
o pewnym dodatkowym narzędziu, któ-
re warto znać. Jest nim SimpleXML - mo-
duł standardowo dostępny w PHP od wer-
sji 5. SimpleXML okazuje się niezastąpiony
we wszelkich działaniach na danych w for-
macie XML, a te –jak wiemy –są nieodzow-
ną częścią programowania z wykorzysta-
niem XSLT. Korzystanie z SimpleXML jest
(jak sama nazwa wskazuje) proste –aby jed-
nak zapewnić czytelnikowi przyjemny start,
w ramce W Sieci podajemy adresy stron opi-
sujących to narzędzie.
Metoda trzecia kryje w sobie z pewnością
największą moc i ukazuje prawdziwą potę-
gę drzemiącą w XSLT. Jako że nasza wiedza
o transformacjach XSL przybrała już dosyć
sensowne kształty, czas ją sobie porządnie
usystematyzować. Dlatego też zajmiemy się
teraz omówieniem wad i zalet każdej z po-
znanych metod użytkowania XSLT. Następ-
nie porównamy możliwości tej nowo pozna-
nej techniki ze sposobem, którego używali-
śmy wcześniej, a mianowicie z ręcznym two-
rzeniem kodu HTML formatowanym za po-
mocą arkuszy stylów CSS. Wbrew pozorom
żadna z tych metod nie jest lepsza od dru-
giej -- każda ma plusy i minusy. Ważne jest
więc, aby wybrać odpowiednią dla dane-
go projektu. W nieco dalszej części artyku-
łu postaramy się pomóc dokonać prawidło-
wego wyboru.
Wady i zalety
przedstawionych metod
Nie ma róży bez kolców, a XSLT nie jest pod
tym względem wyjątkiem. Dotychczas omó-
wiliśmy trzy metody wykorzystania transfor-
macji XSL. Pierwsza polega na stworzeniu pli-
ku XML zawierającego treść strony oraz pliku
XSL formatującego tą treść. Plik XML posiada
również odnośnik do arkusza XSL, dzięki cze-
mu przeglądarka wie jak ma wygenerować stro-
nę. Ważną zaletą tej metody z pewnością jest
brak obciążenia serwera, ponieważ cały proces
generowania odbywa się po stronie odwiedza-
jącego (client-side).
Niestety, jak to zazwyczaj bywa przy czyn-
nościach odbywających się po stronie klien-
ta, transformacje XSL również mogą być nie-
obsługiwane przez przeglądarkę odwiedzają-
cego. Radzi sobie z nimi bez problemu Mo-
zilla Firefox (i podobne), jak również Internet
Explorer od wersji 6. Sytuacja jednak nie jest
już taka różowa w przypadku Opery (ta ofi-
cjalnie wspiera XSLT od wersji 9; mimo to
wciąż zdarzają się jej dziwne problemy z for-
matowaniem), a jeszcze gorsza w przeglądar-
ce Safari. Zapewne ten stan rzeczy ulegnie
zmianie wraz z pojawianiem się następnych
wersji tych przeglądarek, jednak nie można
lekceważyć tego problemu.
Listing 4. Plik users_database.php generujący kod XML na podstawie danych z bazy MySQL
<?
php
// Podajemy podstawowe informacje o połączeniu z bazą danych
// oraz ustawiamy kodowanie znaków
$mysqli
=
new
mysqli
(
"localhost"
,
"nazwa_uzytkownika"
,
"haslo"
,
"nazwa_tabeli"
)
;
$mysqli
-
>
set_charset
(
"utf8"
)
;
// Pobieramy informacje o użytkownikach
$result
=
$mysqli
-
>
query
(
"SELECT * FROM `users`"
)
;
// Tworzymy dokument XML
$xml
=
new
DomDocument
(
'1.0'
,
'UTF-8'
)
;
// Tworzymy główny węzeł
$users
=
$xml
-
>
createElement
(
'users'
)
;
$users
=
$xml
-
>
appendChild
(
$users
)
;
// Pobieramy jednego użytkownika i dodajemy informacje o nim do pliku XML
while
(
$row
=
$result
-
>
fetch_assoc
())
{
// Tworzymy gałąź 'user' zawierającą informacje o konkretnym użytkowniku
$user
=
$xml
-
>
createElement
(
'user'
)
;
$user
=
$users
-
>
appendChild
(
$user
)
;
// Dodajemy wszystkie informacje,
tj. nick, wiek, ranga i liczba postów
foreach
(
$row
as
$fieldName
=
>
$fieldValue
)
{
$child
=
$xml
-
>
createElement
(
$fieldName
,
$fieldValue
)
;
$child
=
$user
-
>
appendChild
(
$child
)
;
}
}
// Zamykamy zasoby bazy danych
$result
-
>
close
()
;
$mysqli
-
>
close
()
;
// Wczytujemy arkusz XSL
$xsl
=
new
DOMDocument
(
'1.0'
,
'UTF-8'
)
;
$xsl
-
>
load
(
'users.xsl'
)
;
// Podczepiamy arkusz XSL
$proc
=
new
XSLTProcessor;
$proc
-
>
importStyleSheet
(
$xsl
)
;
// Wyświetlamy kod HTML wygenerowany na podstawie pliku XML i arkusza XSL
echo
$proc
-
>
transformToXML
(
$xml
)
;
?>
01/2008
Narzędzia
56
XSLT
www.phpsolmag.org
57
Rozwiązaniem problemu kompatybilno-
ści jest natomiast metoda druga, polegająca
na przeniesieniu ciężaru generowania stro-
ny na serwer (server-side). Przeglądarka od-
wiedzającego dostaje w takim przypadku go-
towy kod HTML, z którego interpretacją nie
może już mieć problemu. Rozwiązanie to jest
wręcz przeciwstawne do metody pierwszej i
to co jest plusem w jednej z nich staje się mi-
nusem w drugiej. W metodzie drugiej poja-
wia się więc problem obciążenia serwera, co
trzeba mieć na uwadze, szczególnie przy du-
żej liczbie odwiedzin serwisu.
Metoda trzecia natomiast nie różni się pod
względem sposobu generowania kodu wyj-
ściowego od metody drugiej. W tym przy-
padku dochodzi jeszcze automatyczne ge-
nerowanie dokumentu XML (który w meto-
dzie numer 2 jest wczytywany z pliku), co po-
woduje dodatkowy narzut obciążenia, z któ-
rym serwer musi się uporać w przyzwoitym
czasie.
Zarówno w metodzie drugiej, jak i trzeciej,
nie dokonujemy żadnych optymalizacji pod
względem obciążenia serwera. Każde odświe-
żenie strony wywołuje ponownie proces ge-
nerowania kodu, co nie jest najlepszym wyj-
Listing 5. Plik users_database_final.php posiadający omawiane optymalizacje
<?
php
// Sprawdzamy, czy przeglądarka obsługuje XSLT
$xslt
=
(
strpos
(
$_SERVER
[
'HTTP_USER_AGENT'
]
,
'gecko'
)
)
?
true : false;
// Sprawdzamy datę ostatniego wygenerowania pliku XML
if
(
file_exists
(
'users.xml'
)
)
{
// Pliki są wystarczająco nowe, by z nich skorzystać
if
(
time
()
<
filemtime
(
'users.xml'
)
+ 300
)
{
if
(
!
$xslt
)
echo
file_get_contents
(
'users.html'
)
;
else
{
header
(
"Content-type: text/xml; charset=utf-8"
)
;
echo
file_get_contents
(
'users.xml'
)
;
}
return
;
}
}
// Pliki nie zostały stworzone lub są stare
// Podajemy podstawowe informacje o połączeniu z bazą danych
// oraz ustawiamy kodowanie znaków
$mysqli
=
new
mysqli
(
"localhost"
,
"nazwa_uzytkownika"
,
"haslo"
,
"nazwa_tabeli"
)
;
$mysqli
-
>
set_charset
(
"utf8"
)
;
// Pobieramy informacje o użytkownikach
$result
=
$mysqli
-
>
query
(
"SELECT * FROM `users`"
)
;
// Tworzymy dokument XML
$xml
=
new
DomDocument
(
'1.0'
,
'UTF-8'
)
;
$xml
-
>
appendChild
(
$xml
-
>
createProcessingInstruction
(
'xml-stylesheet'
,
'href="users.xsl" type="text/xsl"'
)
)
;
// Tworzymy główny węzeł
$users
=
$xml
-
>
createElement
(
'users'
)
;
$users
=
$xml
-
>
appendChild
(
$users
)
;
// Pobieramy jednego użytkownika i dodajemy informacje o nim
do pliku XML
while
(
$row
=
$result
-
>
fetch_assoc
())
{
// Tworzymy gałąź 'user' zawierającą informacje o konkretnym
użytkowniku
$user
=
$xml
-
>
createElement
(
'user'
)
;
$user
=
$users
-
>
appendChild
(
$user
)
;
// Dodajemy wszystkie informacje, tj. nick, wiek, ranga i
liczba postów
foreach
(
$row
as
$fieldName
=
>
$fieldValue
)
{
$child
=
$xml
-
>
createElement
(
$fieldName
,
$fieldValue
)
;
$child
=
$user
-
>
appendChild
(
$child
)
;
}
}
// Zamykamy zasoby bazy danych
$result
-
>
close
()
;
$mysqli
-
>
close
()
;
// Zapisujemy kod XML do pliku users.xml
$xmlString
=
$xml
-
>
SaveXML
()
;
file_put_contents
(
'users.xml'
,
$xmlString
)
;
// Brak obsługi XSLT, generujemy kod wyjściowy
if
(
!
$xslt
)
{
// Wczytujemy arkusz XSL
$xsl
=
new
DOMDocument;
$xsl
-
>
load
(
'users.xsl'
)
;
// Podczepiamy arkusz XSL
$proc
=
new
XSLTProcessor;
$proc
-
>
importStyleSheet
(
$xsl
)
;
// Zapisujemy wygenerowany kod HTML do pliku users.html
$result
=
$proc
-
>
transformToXML
(
$xml
)
;
file_put_contents
(
'users.html'
,
$result
)
;
}
// XSLT jest obsługiwane
else
{
header
(
"Content-type: text/xml; charset=utf-8"
)
;
$result
=
$xmlString
;
}
// Wyświetlamy stronę
echo
$result
;
?>
01/2008
Narzędzia
58
XSLT
www.phpsolmag.org
59
ściem. Oczywiście nie jesteśmy na nie skaza-
ni -- możemy dokonać cache’owania, co zresz-
tą będzie naszym celem nieco później.
Kolejnym wyjściem z tej sytuacji jest po-
łączenie metody pierwszej i drugiej. Może-
my więc rozpoznawać przeglądarkę użyt-
kownika, i na podstawie tej informacji wy-
bierać odpowiednią metodę generowania na-
szej strony. Dzięki temu zarówno pozbędzie-
my się problemu niekompatybilności oraz
znacznie odciążymy serwer (Firefox i Inter-
net Explorer posiadają znakomitą większość
rynku przeglądarek, a obsługują one w peł-
ni XSLT), a po wprowadzeniu systemu cache-
’owania zmniejszymy obciążenie do całkiem
znośnej wartości.
Wszystkie te czynności dokonamy w dal-
szej części artykułu. Skoro jednak jesteśmy
już przy omawianiu zalet i wad, warto po-
równać sens stosowania XSLT ze standardo-
wą metodą: HTML + CSS.
XSLT czy HTML?
Nieporównywalną przewagą transformacji
XSL nad ręcznym pisaniem pliku HTML
jest całkowite oddzielenie treści od warstwy
prezentacji. Dzięki temu, że nasze dane są
w formacie XML, a nie w postaci mieszan-
ki treści właściwej z tagami HTML, możemy
dowolnie modyfikować strukturę strony nie
dotykając nawet skryptów PHP. Stworzenie
systemu skórek (theme'ów) staje się wtedy
bardzo łatwe i wygodne. Przemyślana kon-
strukcja plików XML umożliwi nam nawet
całkowite oddzielenie danych od serwisu in-
ternetowego. W takiej sytuacji możemy wy-
korzystywać je np. w aplikacji desktopowej,
niezależnie od aktualnej struktury i wyglą-
du strony internetowej.
Działa to w obie strony –równie dobrze to
aplikacja desktopowa może generować pli-
ki XML i umieszczać je na serwerze, któ-
re to zostają następnie wykorzystane przez
serwis internetowy. Możliwości wykorzy-
stania transformacji XSL jest tak wiele, jak
wiele jest różnych zastosowań samych pli-
ków XML.
Kolejną zaletą jest fakt, że XSLT posiada
możliwości podobne do tych znanych z języ-
ków funkcyjnych. Zawiera on takie struktu-
ry jak instrukcja warunkowa, pętla, instruk-
cja
choose
(podobna do
switch
znanej m.in.
z PHP), dzięki czemu za pomocą jednego,
mądrze skonstruowanego arkusza XSL mo-
żemy np. generować różne podstrony ser-
wisu internetowego. W dodatku, XSLT nie
ogranicza nas w żaden sposób pod wzglę-
dem formatowania kodu HTML za pomocą
arkuszy stylów CSS.
Niestety, stosowanie XSLT pociąga za so-
bą dodatkowy narzut tak w postaci obciąże-
nia serwera, jak i pracy przy tworzeniu ser-
wisu. Ten pierwszy problem w dość dużym
stopniu uda się nam zniwelować, jednak ob-
ciążenie będzie zawsze większe niż w przy-
padku zastosowania "czystego" HTML. Dla-
tego też, mimo ogromnych zalet, XSLT z re-
guły nie nadaje się do małych, prostych ser-
wisów internetowych. Napisanie kilku pli-
ków HTML potrwa po prostu krócej niż
zaimplementowanie całego systemu obsłu-
gującego transformacje XSL po stronie ser-
wera i klienta. Ważna jest więc decyzja, czy
tworzony przez nas serwis internetowy bę-
dzie naprawdę korzystał z zalet XSLT.
Znamy więc trzy metody używania trans-
formacji XSL. Wady i zalety tych metod też
już poznaliśmy. Teraz gdy mamy już solid-
ne fundamenty w tematyce XSLT, może-
my omówić bardziej skomplikowane kwe-
stie dotyczące optymalizacji i kompatybil-
ności rozwiązania. W dalszej części tego ar-
tykułu zajmiemy się rozbudową ostatnie-
go przykładu (wykorzystującego bazę da-
nych). Dodamy do niego dwie nowe cechy
–automatyczny wybór metody generowania
strony zależnie od przeglądarki użytkowni-
ka oraz prosty system cache'owania danych
XML i HTML.
Optymalizacje
W celu ograniczenia obciążenia serwera po-
stanowiliśmy wdrożyć do naszego ostatnie-
go przykładu prosty system cache'owania
oraz system automatycznego wyboru meto-
dy generowania kodu zależnie od przeglądar-
ki użytkownika. Listing 5. przedstawia zmo-
dyfikowaną wersję pliku users_database.php
– wzbogaconą o te dwa elementy. Jako że jest
to najbardziej skomplikowany kod w tym ar-
tykule, omówimy go sobie krok po kroku.
Skrypt zaczynamy od zdefiniowania
zmiennej
$xslt
. Do naszych potrzeb wystar-
czy, że sprawdzimy ciąg
HTTP_USER_AGENT
pod względem frazy gecko –- w ten spo-
Listing 6. Składnia instrukcji warunkowej xsl:choose
<
xsl:choose
>
<
xsl:when test=
"wyrażenie1"
>
<!-- przypadek pierwszy -->
<
/xsl:when
>
<
xsl:when test=
"wyrażenie2"
>
<!-- przypadek drugi -->
<
/xsl:when
>
<
xsl:otherwise
>
<!-- przypadek domyślny -->
<
/xsl:otherwise
>
<
/xsl:choose
>
Listing 7. Przykład użycia instrukcji warunkowej xsl:choose
<
xsl:choose
>
<
xsl:when test=
"age < 18"
>
<
td
><
xsl:value-of select=
"age"
/
>
(niepełnoletni)
<
/td
>
<
/xsl:when
>
<
xsl:when test="age
>
60">
<
td
><
xsl:value-of select=
"age"
/
>
(senior)
<
/td
>
<
/xsl:when
>
<
xsl:otherwise
>
<
td
><
xsl:value-of select=
"age"
/
>
<
/td
>
<
/xsl:otherwise
>
<
/xsl:choose
>
Instalacja XSLT w PHP
Aby móc korzystać z możliwości języ-
ka XSLT w PHP, musimy mieć zainstalowa-
ną bibliotekę
libxslt
(http://xmlsoft.org/
XSLT/) oraz PHP5 uruchomione z dyrekty-
wą –
with-xsl
. W przypadku, gdy korzy-
stamy z wykupionego konta na serwerze
wirtualnym, a przykłady zawarte w tym ar-
tykule nie działają poprawnie, musimy po-
prosić administrację o aktywowanie XSLT.
Drugim wyjściem jest instalacja serwera na
własnym komputerze.
Do tego celu polecamy XAMPP – darmo-
wy pakiet zawierający Apache, PHP, My-
SQL, Perl i inne oprogramowanie serwe-
rowe. XAMPP jest bardzo prosty w in-
stalacji (dostępny zarówno na platfor-
mę Windows, jak i Linux), a jego aktu-
alna wersja standardowo dostarcza ob-
sługę XSLT. Instrukcje instalacji tego pa-
kietu (i inne informacje) znajdują się na
stronie http://www.apachefriends.org/en/
xampp.html.
01/2008
Narzędzia
58
XSLT
www.phpsolmag.org
59
sób zidentyfikujemy m.in. Firefoksa. Rów-
nie dobrze moglibyśmy jednak dokonać w
tym miejscu odwołania do funkcji, w któ-
rej sprawdzalibyśmy owy ciąg pod względem
wielu fraz (przechowywanych np. w tabli-
cy) charakterystycznych dla poszczególnych
przeglądarek.
W następnym bloku kodu dokonujemy
sprawdzenia daty ostatniej modyfikacji pli-
ku users.xml. Jeśli owa modyfikacja miała
miejsce wcześniej niż 5 minut temu (za tą
wartość odpowiada liczba
300
–jest to ilość
sekund, jakie dodajemy do daty modyfikacji
i porównujemy z aktualnym czasem; wszyst-
ko jest tutaj liczone za pomocą unixowego
znacznika czasu), dokonujemy ponowne-
go generowania pliku XML, a następnie ko-
du HTML (tak jak w poprzednim przykła-
dzie). Warto zwrócić w tym miejscu uwa-
gę na kod:
$xml->appendChild($xml->createProcessingIns
truction(
'xml-stylesheet', 'href="users.xsl"
type="text/xsl"'
)
);
znajdujący się trochę powyżej środkowej
części pliku. Te dwie linijki dodają do two-
rzonego dokumentu XML odnośnik wska-
zujący na arkusz XSL – dotychczas nie by-
ło to nam potrzebne, gdyż kod wyjścio-
wy był generowany przez PHP. Teraz gdy
rozważamy także drugą opcję (polegająca
na dostarczeniu przeglądarce kodu XML
i XSL w celu samodzielnego wygenerowa-
nia kodu strony), potrzebny jest nam od-
powiedni odnośnik (jeśli nie wiesz o jakim
odnośniku mówimy, spójrz na Listing 1., li-
nijka 2.).
Dalsze modyfikacje w stosunku do ko-
du z Listingu 6. zaczynają się od ko-
du
file_put_contents
('users.xml',
$xmlString
), gdzie zapisujemy dane XML
do pliku users.xml (lub aktualizujemy je-
go zawartość, w przypadku gdy ten plik już
istnieje). Dalsze instrukcje zależą już od te-
go, czy wykryliśmy obsługę XSLT u użyt-
kownika, czy nie. W tym drugim przypad-
ku mamy trochę więcej do zrobienia, gdyż
musimy wygenerować kod HTML, zapisać
go do pliku oraz przypisać go do zmiennej
$result
. W sytuacji, gdy XSLT jest obsługi-
wane, zamiast tego wszystkiego przypisuje-
my zmiennej
$result
kod XML. Wartość
tej zmiennej zostaje ostatecznie wysłana do
użytkownika.
Znamy już więc różne metody wykorzy-
stania transformacji XSL. Znamy wady i za-
lety każdego rozwiązania. Wiemy już co zro-
bić, aby nasz serwis wykorzystujący XSLT
był bardziej wydajny. Znamy też niektóre
elementy języka XSLT. Aby jednak poznać
jego podstawy w zadowalającej ilości, musi-
my jeszcze omówić kilka pominiętych wcze-
śniej aspektów.
Elementy XSLT
Poznaliśmy już takie elementy jak
stylesheet
,
template
,
for-each
i
value-
of
. Omówimy jeszcze 2 elementy (powią-
zane z instrukcjami warunkowymi). Jest ich
oczywiście dużo więcej, jednak w tym, bądź
co bądź, wprowadzającym artykule ogra-
niczymy się do tych najważniejszych. Dla
żądnych wiedzy czytelników dostarczamy
garść odnośników umieszczonych w ram-
ce W Sieci.
xsl:if
xsl:if –
jest to instrukcja warunkowa pełnią-
ca tą samą rolę co
if znane z innych języków
funkcyjnych. Prototyp tej instrukcji prezentuje
się następująco:
<xsl:if test="wyrażenie">
<!-- zawartość
-->
</xsl:if>
gdzie
wyrażenie
to warunek, który ma być
spełniony. Przykład odnoszący się do naszego
kodu XML mógłby wyglądać następująco:
<xsl:if test="age < 18">
<td><xsl:value-of select="age"/>
(niepełnoletni)</td>
</xsl:if>
Efektem powyższej instrukcji będzie słów-
ko niepełnoletni umieszczone przy użytkow-
nikach niemających 18 lat. Ciąg
<
; znaczy
oczywiście mniejszy niż i jest równoważne ze
znakiem "<" (tego ostatniego jednak z oczywi-
stych powodów nie możemy używać w doku-
mentach XML).
xsl:choose
xsl:choose
– to kolejna instrukcja warunko-
wa, ta jednak jest podobna do
switch
z PHP.
Można (a nawet trzeba) jej używać z eleme-
tami
xsl:when
oraz
xsl:otherwise
, działają-
cymi jak (odpowiednio)
case
i
default
w in-
strukcji
switch
. Składnię tego elementu pre-
zentuje Listing 6.
Element xsl
:otherwise
jest nieobowiązkowy, a ilość
xsl:when
do-
wolna (musi być oczywiście przynajmniej je-
den taki element). Rozbudujmy trochę po-
przedni przykład sprawdzający wiek użyt-
kownika, aby utrwalić zasadę działania tej in-
strukcji warunkowej. Przykład użycia
xsl:
switch
prezentuje Listing 7. Jeśli urucho-
mimy ten przykład zauważymy, że druga in-
strukcja (sprawdzająca, czy użytkownik ma
więcej niż 60 lat) nigdy się nie wykona. Jest to
absolutnie prawidłowe. Co więcej, gdybyśmy
nie mieli instrukcji
xsl:otherwise
, a żadna z
xsl:when
nie zostałaby spełniona, kod po pro-
stu nie zostałby wykonany, a my nie uzyskali-
byśmy żadnego efektu.
Podsumowanie
Transformacje XSL kryją w sobie duże możli-
wości. Wiele aspektów omówiliśmy już w tym
artykule, jednak równie dużo pozostaje jesz-
cze do odkrycia. Celem artykułu było wpro-
wadzenie czytelnika w świat XSLT, zapozna-
nie go z metodami jego stosowania, omówie-
nie zalet i wad, a przede wszystkim zachęce-
nie do dalszej nauki. Czytelnicy zaintereso-
wani tym tematem znajdą dodatkowe infor-
macje w ramce W Sieci. Najlepszą metodą
nauki jest eksperymentowanie, dlatego gorą-
co zachęcamy do własnoręcznej modyfikacji
przykładów.
KAROL GUSAK
Autor jest studentem Informatyki na Politechni-
ce Białostockiej. Od kilku lat tworzy hobbystycz-
nie strony internetowe w PHP, a od pewnego czasu
również aplikacje w C++.
Kontakt z autorem: groadin@gmail.com
W Sieci
• http://www.zvon.org/xxl/XSLTutorial/Output_pol/contents.html#id1 – Bardzo dobry
kurs (ang tutorial) XSLT, w całości po polsku;
• http://developer.mozilla.org/pl/docs/XSLT – Kompendium wiedzy o XSLT, szczególnie
warta polecenia jest polska dokumentacja elementów XSLT;
• http://zvon.org/xxl/XSL-Ref/Tutorials/index.html – Obszerny kurs XSLT, po angielsku;
• http://www.w3schools.com/xpath/xpath_intro.asp – Bardzo jasno napisany kurs języka
XPath, po angielsku;
• http://developer.mozilla.org/pl/docs/XPath – Polska dokumentacja osi i funkcji Xpath;
• http://webcity.pl/webcity/simplexml_nadchodzi – Interesujący artykuł przedstawiający
podstawy użytkowania SimpleXML, po polsku;
• http://www.php.net/simplexml – Oficjalny opis modułu SimpleXML, w języku angiel-
skim;
• http://developer.mozilla.org/pl/docs/DOM – Centrum informacji na temat ogólnie poję-
tego DOM, po polsku;
• http://www.php.net/dom/ – Dokumentacja modułu PHP DOM wraz z przykładami wy-
korzystania, po angielsku;
• http://www.w3schools.com/schema/schema_intro.asp – Kurs XML Schema Definition
(XSD), w języku angielskim.