07-08.pdf

(400 KB) Pobierz
Czerpanie z XML-a
7
W poprzednim rozdziale Czytelnik nauczył się tworzyć arkusze stylów XSL dla posiadanych do-
kumentów XML. W niniejszym rozdziale temat ten będzie kontynuowany. Czytelnik dowie się,
jak dokument i arkusz stylów są przetwarzane i przekształcane na dane wyjściowe. Podobnie jak
w poprzednich rozdziałach, tym razem przyjrzymy się poznanym strukturom języka XML z pun-
ktu widzenia Javy. Omówimy procesory XSLT, interfejsy API Javy do obsługi wejścia XML
w formacie drzewiastym oraz powiemy, czym różnią się te interfejsy od opisywanego już SAX-a.
Najpierw przeanalizujemy sposób, w jaki wykonywane są w komputerze transformacje. Stworzy-
my w ten sposób „wirtualny plac zabaw”, gdzie będziemy mogli eksperymentować z własnymi
konstrukcjami XSL i XSLT. Spróbujemy również dodać nieco bardziej złożone formatowanie
do arkusza stylów, który stworzyliśmy w ostatnim rozdziale. Ponadto zaczniemy dokładniej anali-
zować sposób działania procesora XSLT; na końcu szczegółowo omówimy, jakiego rodzaju i forma-
tu danych wejściowych oczekuje taki procesor. Tym samym rozpoczniemy dyskusję o obiektowym
modelu dokumentu (DOM) — alternatywnym względem SAX-a sposobie uzyskiwania dostępu do
danych XML. Na koniec odejdziemy od tematu parserów, procesorów i interfejsów API, spróbuje-
my natomiast poskładać wszystkie elementy „układanki XML” w jedną całość. Będzie to wstęp do
pozostałej części książki — spróbujemy bardziej przekrojowo opisać różne typy aplikacji XML
i sposoby wykorzystania wzorców projektowych i struktur XML do własnych potrzeb.
Przed lekturą dalszej części książki Czytelnik powinien zrozumieć nie tylko tematykę niniejszego
rozdziału, ale także to, jakich tematów ten rozdział
nie
porusza. Czytelnik nie znajdzie tutaj opisu
tworzenia procesora XSLT (podobnie jak wcześniej nie znalazł receptury tworzenia parsera XML).
Opisywane tutaj zagadnienia są bardzo ważne — w zasadzie kluczowe — do korzystania z proce-
sora XSLT; to także świetny wstęp do ewentualnego zaangażowania się w rozbudowę istniejących
procesorów XSLT, takich jak Xalan grupy Apache. Jednakże parsery i procesory to programy nie-
zwykle złożone i próba wyjaśnienia ich wewnętrznych mechanizmów zajęłaby resztę książki,
a może i całą następną! My natomiast zajmiemy punkt widzenia programisty aplikacji lub ar-
chitekta programów w Javie; postaramy się wykorzystać istniejące już narzędzia i w razie koniecz-
ności rozbudować je do własnych potrzeb. Innymi słowy, zanim zabierzemy się za programowanie
procesorów, powinniśmy nauczyć się ich używać!
C:\Users\a_czajka\Dropbox\Informatyka\książki
informatyczne\Java i XML\07-08.DOC
strona
155
156
Rozdział 7. Czerpanie z XML-a
Uzyskiwanie danych wyjściowych
Jeśli Czytelnik śledził przykłady z ostatniego rozdziału, powinien być już przygotowany na prze-
kazanie arkusza i dokumentu XML do procesora. W przypadku większości procesorów jest to
dość prosta czynność. Zgodnie z przyjętą taktyką korzystania z najlepszych w branży produktów
typu open source, użyjemy procesora Apache Xalan (można go pobrać i uzyskać o nim informacje
pod adresem
http://xml.apache.org).
Nad Xalanem pracują najtęższe umysły — programiści firm
Lotus, IBM, Sun, Oracle i innych. Ponadto procesor ten świetnie współpracuje z opisywanym we
wcześniejszych rozdziałach parserem Apache Xerces. Jeśli jednak Czytelnik posiada już inny proce-
sor, to także nie powinien mieć problemów ze znalezieniem informacji, dotyczących uruchamiania
przykładów opisywanych w tym rozdziale, a wynik działania programu powinien być identyczny
lub bardzo podobny do uzyskiwanego w książce.
Najpierw spróbujemy uruchomić procesor XSLT z wiersza poleceń. Często robi się to na potrzeby
testowania, usuwania błędów i tworzenia zawartości dokumentów w trybie offline. Warto pamię-
tać, że w wielu „poważnych” witrynach WWW zawartość tworzona jest właśnie offline, często
w godzinach nocnych lub raz w tygodniu, dzięki czemu w czasie żądania pobrania strony nie ma
spadku wydajności związanego z dynamicznym przetwarzaniem XML-a na HTML lub inny język
znaczników. Uruchamiany w ten sposób procesor pomoże nam również w przeanalizowaniu róż-
nych warstw transformacji XML. Dokumentacja używanego procesora powinna zawierać instru-
kcje dotyczące sposobu uruchamiania go z wiersza poleceń. W przypadku procesora Apache Xalan
polecenie ma następującą postać
D:\prod\JavaXML> java org.apache.xalan.xslt.Process
-IN [Dokument XML]
-XSL [Arkusz stylu XSL]
-OUT [Plik wyjściowy]
Xalan, jak każdy inny procesor, umożliwia podanie także wielu innych opcji w wierszu poleceń,
ale my będziemy korzystali głównie z tych trzech powyższych. Xalan domyślnie korzysta z par-
sera Xerces, a więc w ścieżce dostępu do klas będą musiały się znaleźć zarówno klasy parsera, jak
i procesora. W wierszu poleceń można zażądać zmiany parsera XML, ale w Xalanie obsługa par-
sera Xerces jest najbardziej zaawansowana. Jeśli przekształcanie odbywa się w powyższy sposób,
nie trzeba odwoływać się do arkusza stylu z poziomu dokumentu; procesor XSLT sam zastosuje
arkusz stylu podany w wierszu poleceń. Wewnętrzne deklaracje arkuszy stylów zostaną użyte do-
piero w rozdziale 9.,
Struktury publikacji WWW.
Tak więc do zbudowania polecenia uruchamia-
jącego nasz procesor potrzebujemy nazwy dokumentu XML i arkusza XSL (w tym przypadku
znajdującego się w podkatalogu). Ponieważ w wyniku mamy uzyskać plik HTML, jako plik wyjś-
ciowy podajemy
contents.html:
D:\prod\JavaXML> java org.apache.xalan.xslt.Process
-IN contents.xml
-XSL XSL/JavaXML.html.xsl
-OUT contents.html
Uruchomienie takiego polecenia w odpowiednim katalogu spowoduje, że Xalan rozpocznie proces
transformacji. Uzyskamy wynik podobny do tego przedstawionego w przykładzie 7.1.
Przykład 7.1. Przekształcanie pliku XML za pomocą procesora Apache Xalan
D:\prod\JavaXML> java org.apache.xalan.xslt.Process
-IN contents.xml
-XSL XSL/JavaXML.html.xsl
-OUT contents.html
C:\Users\a_czajka\Dropbox\Informatyka\książki
informatyczne\Java i XML\07-08.DOC
strona
156
Pobieranie danych wejściowych
========== Parsing file:D:/prod/JavaXML/XSL/JavaXML.html.xsl =========
Parse of file:D:/prod/JavaXML/XSL/JavaXML.html.xsl took 1161 milliseconds
========= Parsing contents.xml ==========
Parse of contents.xml took 311 milliseconds
=============================
Transforming...
transform took 300 milliseconds
XSLProcessor: done
157
Po ukończeniu przetwarzania powinno być możliwe otworzenie uzyskanego pliku
contents.html
w edytorze lub przeglądarce WWW. Jeśli Czytelnik postępował zgodnie z instrukcjami w ostatnim
rozdziale, to w przeglądarce powinna zostać wyświetlona strona widoczna na rysunku 7.1.
Rysunek 7.1. Strona HTML uzyskana po transformacji danych XML
Teraz Czytelnik wie już, jak wprowadzać zmiany i testować dane wynikowe plików XML i arkuszy
XSL. Procesor Xalan uruchomiony z wiersza poleceń posiada także pożyteczną funkcję odnajdy-
wania błędów w plikach XML lub XSL i podawania numerów wierszy, w których one wystąpiły
— to jeszcze bardziej upraszcza usuwanie błędów i testowanie plików.
Pobieranie danych wejściowych
Poza powodami, o których już wspomnieliśmy, jest jeszcze jedna istotna przyczyna, dla której nie
będziemy zajmować się omawianiem wewnętrznych mechanizmów procesora — dane wejściowe
i wyjściowe procesora są o wiele bardziej zajmujące! Widzieliśmy już, jak można przetwarzać do-
kument przyrostowo za pomocą interfejsów i klas SAX. W procesie tym w prosty sposób decy-
dujemy, co zrobić z napotkanymi elementami, jak obsłużyć określone atrybuty i jakie czynności
powinny zostać podjęte w przypadku napotkania błędów. Jednakże korzystanie z takiego modelu
w pewnych sytuacjach rodzi również problemy. Jedną z takich sytuacji jest przekazywanie danych
wejściowych dla procesora XSLT.
C:\Users\a_czajka\Dropbox\Informatyka\książki
informatyczne\Java i XML\07-08.DOC
strona
157
158
Rozdział 7. Czerpanie z XML-a
SAX działa sekwencyjnie
Model sekwencyjny oferowany przez interfejs SAX nie umożliwia uzyskania swobodnego dostępu
do dokumentu XML. Innymi słowy, korzystając z SAX-a pobieramy informacje o dokumencie XML
wtedy, kiedy robi to parser — i podobnie jak parser informacje te tracimy. Kiedy pojawia się ele-
ment 2., to nie można uzyskać dostępu do informacji w elemencie 4., ponieważ nie został on
jeszcze przetworzony. Natomiast kiedy pojawi się element 4., to nie możemy powrócić do elemen-
tu 2. Oczywiście, mamy prawo zachować informacje napotkane w procesie przetwarzania, ale za-
kodowanie tego typu przypadków specjalnych może być bardzo trudne. Przeciwną skrajnością jest
stworzenie reprezentacji dokumentu XML w pamięci. Wkrótce okaże się, że parser DOM postępuje
właśnie w ten sposób; tak więc wykonywanie tego w interfejsie SAX byłoby bezcelowe, a praw-
dopodobnie także wolniejsze i bardziej kłopotliwe.
SAX a elementy siostrzane
Innym zadaniem trudnym do wykonania w interfejsie SAX jest przechodzenie z elementu na ele-
ment „w poziomie”. Dostęp do elementów poprzez SAX jest w dużym stopniu hierarchiczny i se-
kwencyjny. Uzyskujemy dostęp do krańcowego elementu węzła, potem przechodzimy z powrotem
„w górę” drzewa i znów schodzimy do innego elementu na dole hierarchii. Nie ma przejrzystego
odniesienia do „poziomu” hierarchii, na którym aktualnie się znajdujemy. Identyfikację poziomów
można co prawda wdrożyć poprzez wprowadzenie wyszukanych liczników, ale ogólnie SAX nie
jest do tego typu operacji przystosowany. Nie ma zaimplementowanego pojęcia elementu siostrza-
nego, następnego elementu na tym samym poziomie; nie ma też możliwości sprawdzenia, które
elementy są zagnieżdżone w których.
Procesor XSLT musi znać elementy siostrzane danego elementu; co ważniejsze, musi znać jego
elementy potomne. Spójrzmy na taki fragment szablonu XSL:
<xsl:template match:"elementMacierzysty">
<!-- Tutaj zawartość drzewa wynikowego -->
<xsl:apply-templates select="elementPotomny1|elementPotomny2" />
<!-- Tutaj dalsza zawartość drzewa wynikowego -->
</xsl:template>
Szablony nakładane są poprzez konstrukcję
xsl:apply-templates,
ale to nakładanie odby-
wa się na konkretnym zestawie węzłów, pasującym do podanego wyrażenia XPath. W powyższym
przykładzie szablon powinien być nałożony jedynie na
elementPotomny1
lub
elementPo-
tomny2
(są one rozdzielone operatorem LUB wyrażeń XPath, czyli kreską poziomą). Ponadto,
ponieważ wykorzystujemy ścieżkę względną, wspomniane elementy muszą być bezpośrednio
potomne względem elementu
elementMacierzysty.
Określenie i zlokalizowanie tych węz-
łów w reprezentacji dokumentu XML oferowanej przez SAX byłoby niezwykle trudne. Dzięki hie-
rarchicznej reprezentacji dokumentu w pamięci czynność ta jest bardzo łatwa — i jest to kolejny
powód, dla którego tak często korzysta się z modelu DOM jako wejścia dla procesorów XSLT.
Przyczyny korzystania z SAX-a
Wszystkie te „wady” SAX-a skłaniają zapewne Czytelnika do zastanawiania się, dlaczego w ogóle
korzysta się z interfejsu SAX. Warto więc tutaj przypomnieć, że powyższe problemy odnoszą się
do konkretnego zastosowania danych XML, w tym przypadku przetwarzania poprzez XSL. Otóż
„wady” te są jednocześnie... zaletami SAX-a! Czy to nie wydaje się zagmatwane? Wkrótce okaże
się, że nie tak bardzo.
C:\Users\a_czajka\Dropbox\Informatyka\książki
informatyczne\Java i XML\07-08.DOC
strona
158
Obiektowy model dokumentu (DOM)
159
Wyobraźmy sobie, że przetwarzamy spis treści czasopisma
National Geographic
w postaci danych
XML. Dokument taki często osiąga 500 wierszy długości, czasem więcej. Teraz wyobraźmy sobie
indeks książki O'Reilly w postaci pliku XML. Setki słów z numerami stron, odsyłaczami itd. Wszy-
stko to przykłady w miarę małych, spójnych aplikacji XML. W miarę wzrostu dokumentu XML
rośnie obszar zajmowanej przez niego pamięci, jeśli korzystamy z drzewa DOM. Weźmy teraz
pod uwagę sytuację, w której dokument XML staje się tak wielki, że jego reprezentacja w modelu
DOM zaczyna wpływać na wydajność aplikacji. I wyobraźmy jeszcze sobie, że te same wyniki
można uzyskać poprzez przetworzenie dokumentu wejściowego sekwencyjnie, za pomocą SAX-a
— przy wykorzystaniu jednej dziesiątej lub jednej setnej zasobów systemowych.
Powyższy przykład obrazuje, że podobnie jak w Javie istnieje wiele sposobów wykonania tego
samego zadania, tak i w różny sposób można uzyskać dane dokumentu XML. W wielu scenariu-
szach SAX stanowi lepszy wybór — oferuje szybkie przetwarzanie i przekształcanie. W innych
przypadkach zwycięża DOM — zapewnia prosty, przejrzysty interfejs danych określonego forma-
tu. To my, programiści, musimy zastanowić się nad celem budowania aplikacji i wybrać odpowie-
dnią metodę (albo opracować sposób współdziałania obydwu metod). Jak zwykle umiejętność
podjęcia właściwej decyzji wynika ze znajomości dostępnych rozwiązań. Mając to na uwadze,
przyjrzyjmy się takiemu właśnie nowemu rozwiązaniu.
Obiektowy model dokumentu (DOM)
W przeciwieństwie do interfejsu SAX, obiektowy model dokumentu wywodzi się z kręgów kon-
sorcjum W3C. SAX to oprogramowanie będące własnością publiczną, stanowiące owoc długich
dyskusji na liście adresowej
XML-dev.
Natomiast DOM jest samym w sobie standardem, tak jak
XML. DOM nie został również opracowany wyłącznie dla Javy; jego zadaniem jest reprezentacja
zawartości i modeli dokumentów we wszystkich językach i narzędziach programistycznych. Ist-
nieją interfejsy DOM dla JavaScriptu, Javy, CORBA i innych języków. Jest to więc specyfikacja
neutralna językowo i platformowo.
Kolejna różnica polega na tym, że DOM jest dostarczany jako „poziomy”, a nie wersje. DOM
Level One (DOM poziomu pierwszego) ma status przyjętego zalecenia W3C, a pełną specyfikację
możemy przejrzeć pod adresem
http://www.w3.org/TR/REC-DOM-Level-1/.
Level One opisuje
funkcje i sposób nawigacji po zawartości dokumentu. Dokument w modelu DOM nie musi być
dokumentem XML — może to być HTML bądź dowolny inny rodzaj zawartości! Level Two
(DOM poziomu drugiego), ukończony w roku 2000, uzupełnia Level One o moduły i opcje dla
poszczególnych modeli zawartości, takich jak XML, XSL czy CSS (kaskadowe arkusze stylów).
W ten sposób „uzupełniane są luki” pozostawiane przez bardziej ogólne narzędzia Level One. Bie-
żący dokument kandydujący do oficjalnego zalecenia W3C znajduje się pod adresem
http://www.-
w3.org/TR/DOM-Level-2/.
Trwają już prace nad modelem Level Three (DOM poziomu trzeciego),
udostępniającym kolejne narzędzia dla specyficznych typów dokumentów — np. procedury obsłu-
gi sprawdzania poprawności dla XML-a.
DOM a Java
Aby móc korzystać z modelu DOM w określonym języku programowania, należy zastosować
interfejsy i klasy oraz zaimplementować sam model DOM. Ponieważ wykorzystywane metody nie
są określone w samej specyfikacji DOM (specyfikacja ta charakteryzuje jedynie model dokumen-
tu), konieczne było opracowanie interfejsów języka reprezentujących konceptualną strukturę mo-
delu DOM — zarówno dla Javy, jak i innych języków. Interfejsy te umożliwiają manipulację
dokumentami w sposób określony właśnie w specyfikacji DOM.
C:\Users\a_czajka\Dropbox\Informatyka\książki
informatyczne\Java i XML\07-08.DOC
strona
159
Zgłoś jeśli naruszono regulamin