2531


9

Struktury publikacji WWW

Czytelnik poznał już podstawy korzystania z XML-a z poziomu języka Java. Omówione zostały in­terfejsy SAX i DOM, umożliwiające manipulację i tworzenie danych XML. Czytelnik poznał rów­nież JDOM, udostępniający bardziej naturalny dla programistów Javy sposób korzystania z da­nych XML. Skoro Czytelnik wie już, jak używać języka XML z poziomu programów, pora zająć się konkretnymi aplikacjami. W następnych sześciu rozdziałach przedstawione zostaną najistot­niej­­sze zastosowania języka XML i, co najważniejsze, omówione zostaną sposoby implemen­to­wa­nia tych apli­kacji w Javie. Są dosłownie setki, a wkrótce będą tysiące ważnych zastosowań języka XML, ale tutaj opiszemy tylko te najważniejsze — te, które mogą zrewolucjonizować proces tworzenia opro­gramowania.

Jako pierwsze zostaną omówione aplikacje będące przedmiotem najgorętszych dyskusji w społe­cznościach XML-a i Javy — struktury publikacji WWW. Jak to już zostało wspomniane, moż­liwość tworzenia prezentacji z zawartości jest raczej przereklamowana — dużo ważniejsza jest przenośność danych oferowana przez XML. Nie zmienia to jednak faktu, że XML świetnie nadaje się również do generowania wartości prezentacyjnej. Jest to cecha szczególnie istotna w apli­ka­cjach WWW.

Za pięć lat praktycznie dowolna duża aplikacja będzie albo całkowicie wykorzystywała moż­li­wości WWW, albo będzie przynajmniej udostępniała „webowy” interfejs. Użytkownicy domagają się coraz bogatszych zestawów funkcji, a działy marketingowe — coraz większej elastyczności w wyglądzie i zachowaniu aplikacji. Powstał nowy zawód — artysta WWW; to nie to samo co webmaster — nie musi dobrze znać Perla, ASP, JavaScriptu czy innych języków skryptowych. Cały dzień nic nie robi, tylko tworzy, modyfikuje i projektuje dokumenty HTML. Gwałtowne zmia­ny na rynku wymagają często kompletnej przebudowy witryny nawet raz w tygodniu, więc takie stanowisko jest bardzo potrzebne. Style kaskadowe (CSS) okazały się tutaj bardzo pomocne, ale i tak utrzymanie spójności wielu stron wymaga bardzo dużo czasu. Taką sytuację na siłę można by zaakcep­tować, ale na pewno żaden programista nie chciałby spędzić całego życia na wprowa­dza­niu zmian w stronach HTML.

Wraz z popularyzacją programów Javy uruchamianych po stronie serwera, ten problemstał się bardziej dokuczliwy. Twórcy serwletów długie godziny spędzają wyłącznie na poprawianiu instrukcji out.println() zwracających dane HTML. Ta sytuacja doprowadziła do powstania specy­fi­ka­cji Java Server Pages (JSP); jednakże JSP nie stanowi rozwiązania — przenosi jedynie ciężar na pro­gramistę HTML-a, który cały czas musi unikać wprowadzania zmian w zagnieżdżonym w stro­nach kodzie Javy. Co więcej, w JSP nie ma obiecanego jednoznacznego oddzielenia warstwy da­nych i prezentacji. Oczekiwano więc sposobu generowania czystych danych i — później — nakładania jednolitego stylu o określonej porze (generowanie statyczne) lub bezpośrednio w czasie działania (dynamiczne generowanie zawartości).

Czytelnik już wie, że powyższe problemy rozwiązują technologie XSL i XSLT. Jest jednak pe­wien problem — aby generować zawartość, szczególnie dynamicznie, trzeba dysponować odpo­wie­dnim mechanizmem. Co z tego, że na serwerze mamy setki dokumentów XML, jeśli nie ma mechanizmu umożliwiającego przekształcenie ich do potrzebnej postaci. Jeśli dodamy do tego po­trzebę istnienia serwletów i innych elementów znajdujących się po stronie serwera, umożli­wia­ją­ two­rzenie wynikowych danych XML, to otrzymujemy zespół wymagań określający właśnie struk­turę publikacji WWW. W niniejszym rozdziale przyjrzymy się takim właśnie strukturom. Czy­telnik będzie mógł przekonać się, że dzięki nim zniknie potrzeba „ślęczenia nad HTML-em”. „Artyści WWW” staną się specjalistami od XML-a i XSL-a, co na pewno wyjdzie im na dobre, zaś wygląd i zachowanie aplikacji będzie można zmienić w dowolnej chwili i w dowolny sposób.

Struktura publikacji WWW (ang. web publishing framework) stanowi rozwiązanie wszystkich opi­sywanych wyżej problemów. Tak jak serwer WWW odpowiada na żądanie pobrania pliku, stru­ktura publikacji WWW odpowiada na żądanie publikowanej wersji pliku. Publikowany plik (ang. published file) to plik przekształcony za pomocą XSLT, stworzony na poziomie aplikacji lub przekształcony z innego formatu (np. PDF). Żądający nie widzi danych, z których powstał taki plik; nie musi również jawnie żądać wykonania publikacji. Często z identyfikatora URI (np. http://nasz­Host.com/publish) wynika, że w serwerze WWW uruchomiony jest mechanizm publikacji. Jak moż­na podejrzewać, sama koncepcja jest dużo prostsza niż faktyczna implementacja, a wybranie odpowiedniej struktury publikacji dla własnych potrzeb to wcale nie łatwe zadanie.

Wybór struktury

Czytelnik z pewnością zaczyna już doceniać znaczenie struktur publikacji. Rozwiązań jest jednak bardzo wiele. Język Java oferuje prosty sposób współpracy z rozmaitymi narzędziami XML wyko­rzystywanymi w strukturach publikacji. Serwlety Javy umożliwiają natomiast prostą obsługę żą­dań i odpowiedzi WWW. Ale lista struktur publikacji jest krótka, a lista tych dobrych i stabilnych — jeszcze krótsza. Jednym z najlepszych zasobów informacji o tego typu oprogramowaniu jest lista XML Software dostępna pod adresem http://xmlsoftware.com/publishing. Ta lista zmienia się tak często, że nie warto jej tutaj przytaczać. Tym niemniej istnieje szereg istotnych kryteriów, któ­rymi programista powinien się kierować przy wyborze struktury publikacji — i właśnie one zo­sta­ną tutaj omówione.

Stabilność

Obecnie programiści mają problemy ze znalezieniem produktu w wersji o numerze wyższym niż 2.x. Mało tego — ze świecą trzeba szukać struktury publikacji nawet drugiej generacji! Oczywiście, wyż­szy numer wersji nie jest jeszcze gwarancją stabilności, ale często odzwierciedla ilość czasu, wy­siłków i rzetelność testowania, jakiemu poddano daną strukturę. System publikacji XML to na tyle no­wa technologia, że rynek zalewany jest produktami w wersjach 1.0 i 1.1 — często po prostu nie­wy­star­czająco stabilnymi do praktycznego użycia.

O stabilności produktu mogą również świadczyć inne, stabilne produkty tego samego producenta. Często producent wypuszcza cały pakiet narzędzi; jeśli inne narzędzia nie obsługują interfejsów SAX 2.0 i DOM Level 2 albo wszystkie są w wersjach 1.0 lub 1.1, to strukturę publikacji po­chodzącą z takiego pakietu najlepiej na razie wykluczyć z wyboru i poczekać, aż nieco „dojrzeje” i będzie zgodna z nowszymi standardami XML. Należy również unikać technologii przeznaczo­nych dla konkretnej platformy — jeśli struktura publikacji została scalona z konkretnym systemem (np. Windows), to nie jest to już „czyste” rozwiązanie w Javie. Pamiętajmy, że struktura publikacji ma obsługiwać klientów ze wszystkich platform; dlaczego więc mamy zadowalać się produktem, który nie może zostać uruchomiony na dowolnej platformie?

Integracja z innymi narzędziami i interfejsami XML

Oprócz stabilności, struktura publikacji musi również obsługiwać różne parsery i procesory XML. Jeśli jest związana z konkretnym parserem lub procesorem, to tak naprawdę jest to XML-owa wersja Microsoftu — ograniczamy się do jednej konkretnej implementacji technologii. Struktury publikacji mogą dobrze „integrować się” z parserem konkretnego producenta, ale zawsze należy sprawdzić, czy w razie potrzeby parser można zmienić. Jeśli mamy jakiś ulubiony procesor (albo musimy korzystać z procesora przejętego po kimś razem z projektem), trzeba upewnić się, czy struktura z nim współpracuje.

Obsługa interfejsów SAX i DOM to bezwzględna konieczność. Warto też szukać takiej struktury, której producent monitoruje specyfikacje XML Schema, XLink, XPointer i inne technologie XML. Od takiego producenta można oczekiwać poprawek struktury mających na celu obsłużenie tych nowych technologii; ponadto mamy gwarancję, że takiej publikacji nie będziemy musieli zmieniać przez długi czas. Należy śmiało pytać o to, kiedy zostanie uruchomiona obsługa nowej spe­cyfikacji.

Wdrożenia w środowiskach produkcyjnych

Jedną z najważniejszych przesłanek ułatwiających wybór struktury publikacji jest fakt zastoso­wa­nia jej w aplikacjach produkcyjnych. Jeśli producent nie potrafi pokazać nam przynajmniej kilku aplikacji referencyjnych lub serwisów wykorzystujących określoną strukturę, to całkiem możliwe, że... po prostu takie nie istnieją. Producenci (oraz programiści z „branży” open source) uwielbiają chwalić się miejscami, w których ich aplikację można zobaczyć w działaniu. Jeśli wyczuwamy tutaj pewne wahanie, to być może aplikacja jest jeszcze zupełnie pionierska — a przecież nie o to nam chodzi.

Podejmujemy decyzję

Kiedy już Czytelnik rozpatrzy wszystkie powyższe kryteria, wybór struktury publikacji nie będzie szczególnie trudny — tylko niewiele rozwiązań jest zgodnych z postawionymi wymaganiami, a do­chodzą przecież jeszcze wymogi naszej konkretnej aplikacji. W czasie pisania tej książki struktury publikacji obsługujące najświeższe wersje SAX-a, DOM-a i JAXP-a, wdrożone przynajmniej w je­d­nej aplikacji produkcyjnej i mające za sobą przynajmniej trzy znaczące poprawki kodu, można było policzyć na palcach jednej ręki. Nie wymieniamy ich tutaj, bo — co tu dużo mówić — po pół roku mogą już nie istnieć, mogą też zostać zupełnie zmienione. Krajobraz struktur publikacji zmienia się tak gwałtownie, że próba rekomendacji tego czy tamtego produktu może raczej przeszkodzić niż pomóc.

Jednakże jedna struktura publikacji nieustannie się sprawdza i jest szczególnie doceniana przez programistów Javy i XML-a. Struktura ta jest szczególnie istotna dla programistów pracujących na zasadach open source oraz piszących w Javie. Chodzi o projekt Apache Cocoon, zapoczątkowany przez Stefano Mazzocchiego — od samego „poczęcia” niezwykle solidną strukturę publikacji. Została opracowana dość dawno, kiedy większość z nas próbowała rozgryźć, co to w ogóle jest ten XML. Cocoon, struktura publikacji oparta w całości na Javie, wchodzi już w drugą fazę rozwoju. Stanowi część projektu Apache XML i domyślnie obsługuje Apache Xerces i Apache Xalan. Po­zwala na użycie dowolnego standardowego parsera XML i wykorzystuje niezwykle popularną ar­chi­tekturę serwletów Javy. Jest wykorzystywana w wielu serwisach produkcyjnych (w wersji 1.x) i sprawuje się świetnie. Dlatego właśnie — a także znów konsekwentnie wybierając oprogra­mo­wa­nie open source — w tej książce wybieramy Apache Cocoon.

W poprzednich rozdziałach kwestia wyboru parsera i procesora XML była w znacznym stopniu otwartą; przykłady wymagałyby tylko niewielkich modyfikacji w przypadku korzystania z innych implementacji. Jednakże struktury publikacji WWW nie zostały znormalizowane — każda z nich implementuje różne funkcje i konwencje. Dlatego opisane w niniejszym rozdziale przykłady wy­ko­rzystujące Apache Cocoon nie są przenośne; jednakże popularność koncepcji i wzorców projektowych zastosowanych w Apache Cocoon usprawiedliwiają poświęcenie całego rozdziału tej właśnie strukturze. Jeśli Czytelnik wybiera inną strukturę publikacji, to powinien przynajmniej przejrzeć opisane tutaj przykłady — ogólne koncepcje są na pewno przenośne, nawet jeśli kod będzie działał tylko w jednej implementacji.

Instalacja

We wcześniejszych rozdziałach instrukcja instalacji ograniczała się do wskazania strony WWW, z której należało pobrać oprogramowanie, oraz do przypomnienia o konieczności dodania odpo­wiedniego pliku jar do ścieżki dostępu do klas. Instalacja struktury publikacji, takiej jak Cocoon, nie jest już tak banalnym zadaniem, dlatego cała procedura została opisana szczegółowo. Jeśli chcemy uzyskać najświeższą wersję struktury, powinniśmy pobrać ją z systemu współbieżnych wer­sji CVS. Będzie to kod prosto z repozytorium kodów źródłowych, a nie publikowana rzadziej wersja „oficjalna”. Oprogramowanie CVS można pobrać spod adresu http://www.cyclic.com/cyc­lic-pages/howget.html.

W tej książce zajmiemy się wersją 1.x struktury Cocoon. Kiedy książka będzie w sprzedaży, wersja beta 2.0 będzie już prawdopodobnie dostępna (według informacji na stronie http://xml.apa­che.org/cocoon/cocoon2.html w czasie tłumaczenia książki Cocoon 2.0 był wciąż w fazie „alfa” i twórcy stanowczo odradzali jego użycie w aplikacjach produkcyjnych — przyp. tłum.); jednak z powodu dużych zmian planowanych w tej nowej generacji tutaj skupimy się na wersjach 1.x, obecnie używanych najpowszechniej. Na końcu rozdziału zostaną pokrótce omówione nowe fun­k­cje, jakie pojawią się w Cocoon 2.

Jeśli w czasie instalacji czytelnik napotka problemy, może skorzystać z zasobów online. Projekt Cocoon gości na stronach projektu Apache XML, pod adresem http://xml.apache.org. Dostępne są tam listy adresowe (http://xml.apache.org/mail.html), a także bardzo przydatne odpowiedzi na naj­częściej zadawane pytania FAQ (http://xml.apache.org/cocoon/faqs.html). Nie trzeba obawiać się zadawania pytań — instalacja złożonych struktur publikacji to niełatwe zadanie, a zawsze istnieje duża szansa, że ktoś już przez to przebrnął i może służyć radą.

Korzystanie z narzędzia Ant

Weterani systemów uniksowych i Linuksa znają na pamięć poniższe polecenia wykonywane przy kompilacji oprogramowania:

/home/bmclaugh (mejis)> ./configure

/home/bmclaugh (mejis)> make

/home/bmclaugh (mejis)> make install

Współpraca kodu źródłowego i programów make oraz autoconf ma długie tradycje. Ale make nie współpracuje zbyt dobrze z kodem w Javie — użytkownicy Windows muszą korzystać z do­dat­ko­wych narzędzi przy kompilacji na tej platformie --> [Author:AJ] ; uruchomienie dokumentacji Javadoc i innych dodatkowych poleceń wymaga długiego procesu konfiguracji; kompilacja RMI (rmic) jest także złożona itd. Rozwiązanie świetnie spisujące się w przypadku Perla, skryptów powłoki czy kodu C, w zetknięciu z Javą traci na użyteczności.

Na szczęście James Duncan Davidson (związany z projektami Jakarta, JAXP i specyfikacją serw­letów) nie poprzestał na narzekaniu na make. Zapoczątkował projekt znany obecnie pod nazwą Ant i stanowiący część projektu Apache Jakarta. Ant to narzędzie do budowania oprogramowania oparte na Javie. Jego konfiguracja oparta jest na XML-u i jest to narzędzie niezależne od plat­for­my. Kompilacje RMI, Javadoc, polecenia zewnętrzne — wszystko to jest obsługiwane w tym jed­nym środowisku. Do „zbudowania” źródeł Cocoon posłuży nam właśnie Ant.

Nowa wersja narzędzia Ant została zawarta w pakiecie Cocoon, w katalogu lib/. Ant można również pobrać ze strony Jakarty, http://jakarta.apache.org. Sposób użycia Anta w przypadku opro­gramowania Cocoon został zawarty w tym ostatnim; informacje bardziej ogólne znaleźć moż­na pod wymienionym adresem projektu Jakarta.

Uzyskanie pakietu Cocoon

Kiedy narzędzie Ant mamy już pod ręką, możemy pobrać źródła Cocoon 1.x. Oprócz możliwości pobrania ich ze stron projektu Apache XML (http://xml.apache.org), najświeższą wersję, wypo­sa­żo­ną we wszystkie nowe funkcje, znaleźć można także w systemie CVS. Jeśli Czytelnik dopiero zaczyna używać oprogramowania Cocoon, może skorzystać z pakietu przygotowanego do pobra­nia; jednak teraz już Czytelnik zna kod Javy i XML-a, więc może warto pobrać zupełnie naj­śwież­szą wersję 1.x.dev z repozytorium CVS. Można to zrobić w następujący sposób:

cvs -d :pserver:anoncvs@xml.apache.org:/home/cvspublic login

Password: ******* (Haslo: 'anoncvs')

cvs -d :pserver:anoncvs@xml.apache.org:/home/cvspublic checkout xml-cocoon

W katalogu xml-cocoon pojawi się najnowsza wersja oprogramowania Cocoon. Zawiera ona plik sterujący kompilacją przez Anta, wszystkie wymagane biblioteki i właściwe źródła. Wystarczy te­raz przejść do tego katalogu i już można rozpocząć budowanie struktury Cocoon.

Budowanie struktury Cocoon

Znajdujemy się w katalogu głównym oprogramowania Cocoon. Aby zbudować strukturę w syste­mie Windows, należy wpisać następujące polecenie:

D:\dev\xml-cocoon> build.bat

natomiast w systemach Unix i Linux:

$ sh build.sh

Podkatalog lib/ zawiera wszystkie biblioteki konieczne do zbudowania projektu Cocoon. Skrypty in­sta­lacyjne dodadzą każdy plik jar tego katalogu do ścieżki dostępu do klas, zawierającej naj­nowsze wersje Apache Xerces, Apache Xalan i innych programów niezbędnych do prawidłowego działania Cocoon 1.x. Nawet jeśli Czytelnik już ma te biblioteki (Xerces czy Xalan), zalecane jest zastosowanie tych dostarczonych z Cocoon — producent gwarantuje ich współpracę z wersją po­braną z CVS-u. Po skończeniu instalacji ścieżka dostępu do klas będzie obejmowała następujące biblioteki:

Skrypt budujący informuje następnie narzędzie Ant, że projekt ma zostać zainstalowany z wy­ko­rzystaniem pliku build.xml, znajdującego się w bieżącym katalogu. Po jego wykonaniu Czytelnik powinien uzyskać następujący wynik:

Cocoon Build System

-------------------

Building with classpath lib/ant_1_1.jar:lib/bsf.jar:lib/bsfengines.jar:lib/fop_0_13_0.jar:lib/ servlet_2_2.jar:lib/stylebook-1.0-b2.jar:lib/turbine-pool.jar:lib/ xalan_1_2_D02.jar:lib/xerces_1_2.jar:/usr/local/jdk1.2.2/lib/tools.jar:

Starting Ant...

Buildfile: build.xml

init:

------------------- Cocoon 1.8 [1999-2000] ---------

prepare:

[mkdir] Created dir: /home/adam/cocoon-1.8/build

prepare-projectx:

prepare-xt:

prepare-ecma:

prepare-ldap:

prepare-src:

[mkdir] Created dir: /home/adam/cocoon-1.8/build/src

[mkdir] Created dir: /home/adam/cocoon-1.8/build/classes

[copydir] Copying 126 files to /home/adam/cocoon-1.8/build/src

compile:

[javac] Compiling 108 source files to /home/adam/cocoon-1.8/build/classes

[javac] Copying 18 support files to /home/adam/cocoon-1.8/build/classes

package:

[jar] Building jar: /home/adam/cocoon-1.8/build/cocoon.jar

BUILD SUCCESSFUL

Total time: 3 minutes 14 seconds

Uzyskany wynik może się nieco różnić numerami wersji lub liczbą plików, ale nie powinny wy­stąpić żadne błędy; jeśli wystąpiły, należy poprawić ścieżkę dostępu do klas zgodnie z komuni­ka­tami zgłaszanymi przez program i ponownie uruchomić skrypt budujący. Po zakończeniu procesu cała dystrybucja Cocoon powinna się znaleźć w jednym pliku cocoon.jar w podkatalogu build/. Należy również sprawdzić, czy posiadamy przykładowy plik właściwości dostarczany z pro­je­ktem, cocoon.properties, w katalogu bin/. Jeśli go tam nie ma, być może znajduje się w pod­ka­talogu build/classes/org/apache/cocoon/.

Z pomocą Anta można także wygenerować dokumentację Javadoc i wykonać inne zadania zwią­za­ne z projektem. Wykonuje się je poprzez określenie celu (ang. target) polecenia budującego. Ce­le to słowa kluczowe dostarczane jako argumenty programu Ant; kompletna lista obsługiwanych celów dla oprogramowania Cocoon znajduje się w pliku build.xml. Celem do utworzenia doku­mentacji jest docs, a dla Javadoc — javadocs. Na przykład, aby zbudować dokumentację, należy wykonać polecenie:

Building with classpath lib/ant_1_1.jar:lib/bsf.jar:lib/bsfengines.jar:lib/fop_0_13_0.jar:lib/ servlet_2_2.jar:lib/stylebook-1.0-b2.jar:lib/turbine-pool.jar:lib/ xalan_1_2_D02.jar:lib/xerces_1_2.jar:/usr/local/jdk1.2.2/lib/tools.jar:

Starting Ant...

Buildfile: build.xml

init:

------------------- Cocoon 1.8 [1999-2000] ---------

prepare-docs:

[replace] Replacing ./xdocs/dtd/ --> dtd/

[replace] Replacing ./xdocs/dtd/ --> dtd/

docs:

[mkdir] Created dir: /home/adam/cocoon-1.8/build/docs

...

W ten sposób pełna dokumentacja projektu znajdzie się w podkatalogu build/docs/. Po przy­go­towaniu projektu można przejść do konfigurowania mechanizmu serwletów pod kątem korzystania z niego.

Konfiguracja mechanizmu serwletów

Trzeba poinformować mechanizm serwletów o oprogramowaniu Cocoon oraz wskazać, które żą­da­nia ma do tego oprogramowania przekazywać. Skonfigurujemy Cocoon do współpracy z me­cha­nizmem serwletów Jakarta Tomcat — jest to implementacja referencyjna interfejsu Java Servlet API 2.2. Czytelnik powinien potrafić uzyskać podobne wyniki także w innych mecha­niz­mach serwletów.

Struktura Cocoon działa na poziomie mechanizmu serwletów, a nie jako kolejny serwlet. Dlatego trzeba dodać Cocoon oraz współpracujące z nim mechanizmy do ścieżki dostępu do klas samego mechanizmu serwletów, a nie do określonej strefy serwletów czy kontekstu. Kopiujemy pliki jar Cocoon, Xerces, Xalan i FOP do podkatalogu lib/ głównego katalogu instalacyjnego Tomcat. Na­stęp­nie biblioteki te dodajemy do ścieżki dostępu do klas mechanizmu serwletów; w tym celu w mechanizmie Tomcat edytujemy plik inicjalizacyjny. W systemie Windows jest to plik <TOMCAT_HOME>/bin/tomcat.bat, a w systemach Unix <TOMCAT_HOME>/bin/tomcat.sh. W plikach tych znajdziemy wiersze ustawiające ścieżkę dostępu do klas odczytywane przez Tom­cat w czasie uruchamiania. Należy tam dodać ścieżki dostępu do klas Cocoon i programów towa­rzy­szących — tak, by odczytywane były przed innymi wpisami w tym pliku. W systemie Windows wpisy te wyglądają następująco:

set CLASSPATH=.

set CLASSPATH=%TOMCAT_HOME%\classes

rem Klasy i biblioteki Cocoon

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\xerces_1_2.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\xalan_1_2_D02.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\fop_0_13_0.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\cocoon.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\webserver.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\jasper.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\xml.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\servlet.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\tools.jar

a w systemach uniksowych:

set CLASSPATH=.

# Klasy i biblioteki Cocoon

CLASSPATH=${CLASSPATH}:${TOMCAT_HOME}/lib/xerces_1_2.jar

CLASSPATH=${CLASSPATH}:${TOMCAT_HOME}/lib/xalan_1_2_D02.jar

CLASSPATH=${CLASSPATH}:${TOMCAT_HOME}/lib/fop_0_13_0.jar

CLASSPATH=${CLASSPATH}:${TOMCAT_HOME}/lib/cocoon.jar

for i in ${TOMCAT_HOME}/lib/* ; do

CLASSPATH=${CLASSPATH}:$i

done

Ważne jest, aby klasy Cocoon poprzedzały pozostałe klasy Tomcat, a w szczególności xml.jar. Xerces, Xalan i Cocoon wykorzystują interfejs SAX 2 i DOM Level 2, zaś parser Sun Project X zawarty w xml.jar — jeszcze nie. Jeśli ta klasa i jej wersje SAX-a i DOM-a zostaną znalezione jako pierwsze, wystąpi błąd w strukturze publikacji Cocoon.

Po dodaniu bibliotek trzeba jeszcze „poinformować” Cocoon o położeniu jego pliku właściwości (po­tem Czytelnik dowie się, do czego faktycznie służy ten plik). Należy skopiować plik cocoon.properties z katalogu Cocoon do <TOMCAT_HOME>/conf/. W tym samym katalogu jest umieszczony plik web.xml, opisujący właściwości i odwzorowania globalne serwletów w mecha­niz­mie. Tutaj należy wskazać konfigurację struktury Cocoon. Wpisujemy tam następujące dane:

<servlet>

<servlet-name>

org.apache.cocoon.Cocoon

</servlet-name>

<servlet-class>

org.apache.cocoon.Cocoon

</servlet-class>

<init-param>

<param-name>

properties

</param-name>

<param-value>

/usr/lib/jakarta-tomcat/conf/cocoon.properties

</param-value>

</init-param>

</servlet>

<servlet-mapping>

<servlet-name>

org.apache.cocoon.Cocoon

</servlet-name>

<url-pattern>

*.xml

</url-pattern>

</servlet-mapping>

Nie ma znaczenia, w którym miejscu pliku zostanie wstawiony powyższy fragment, o ile tylko nie naruszy to zagnieżdżenia elementów (ostateczny plik musi być poprawnym plikiem XML). Należy także zmienić na właściwą ścieżkę dostępu do pliku cocoon.properties, będącą wartością para­me­tru properties. Parametr ten jest przekazywany przez mechanizm serwletów do serwleta Co­coon, co umożliwia poprawną jego konfigurację. Parametr servlet-mapping informuje mechanizm, że żądania kończące się rozszerzeniem .xml mają być przeadresowywane do struktury Cocoon. Po wprowadzeniu zmian należy wykonać restart serwera Tomcat i sprawdzić, czy w czasie uru­cha­mia­nia nie występują żadne błędy.

Jeśli wszystko zostało skonfigurowane poprawnie, można wyświetlić w przeglądarce stronę http:// <nazwa-hosta>:<port>/Cocoon.xml. Jeśli nie wystąpiły żadne błędy, czytelnik powinien ujrzeć stro­nę podobną do tej na rysunku 9.1 (w zależności od rodzaju przeglądarki może się różnić formatowanie tabeli).

Jeśli wystąpiły jakieś błędy, Czytelnik powinien ujrzeć komunikaty definiujące problem. Zazwy­czaj kłopoty wynikają z nieobecności wymaganych klas w ścieżce dostępu do klas, w niepra­wi­dłowym określeniu położenia pliku właściwości lub w niemożności jego odczytania przez serwlet. Ewentualne błędy naprawić i ponownie uruchomić mechanizm. Po uzyskaniu żądanego efektu Czy­telnik jest gotów do wypróbowania działania struktury Cocoon i skonfigurowania jej w taki spo­sób, by obsługiwała różne typy żądań.

Korzystanie ze struktury publikacji

Korzystanie z dobrej struktury publikacji w rodzaju Cocoon nie wymaga jakichś specjalnych in­strukcji — nie jest to złożona aplikacja, której obsługi trzeba się najpierw nauczyć. Wszystko właś­ciwie sprowadza się do wpisania prostego adresu URL do standardowej przeglądarki WWW. Generowanie dynamicznych stron HTML z XML-a, przeglądanie danych XML przekształconych na format PDF, a nawet aplikacje VRML generowane z XML-a — wszystko to uzyskać można poprzez wpisanie adresu URL pliku XML do przeglądarki; resztą zajmie się już Cocoon.

0x01 graphic

Rysunek 9.1. Strona konfiguracji Cocoon

Przeglądanie plików XML przekonwertowanych na HTML

Mając poprawnie działającą strukturę publikacji, możemy za jej pomocą wyświetlić posiadane pliki XML. Wraz z oprogramowaniem Cocoon dostarczane są przykładowe pliki XML i towa­rzy­szą­ce im arkusze stylów XSL (w podkatalogu samples/). My jednak mamy już własnoręcznie utwo­rzone pliki XML i XSL, a więc spróbujmy przekształcić fragment spisu treści XML za pomo­cą arkusza stylów XSL utworzonego w rozdziale 6. Plik XML powinien nosić nazwę contents.xml (można go również pobrać ze strony WWW niniejszej książki). Należy skopiować go do katalogu głównego dokumentów mechanizmu serwletów. W przypadku domyślnej instalacji Tomcata jest to katalog <TOMCAT_ROOT>/webapps/ROOT/. Dokument odwołuje się do arkusza stylów XSL/ JavaXML.html.xsl, a więc trzeba jeszcze w katalogu głównym utworzyć katalog XSL i skopiować tam arkusz utworzony w rozdziale 6. Należy sprawdzić, czy definicja DTD w dokumencie XML jest opatrzona komentarzami (pamiętajmy, sprawdzanie poprawności rzadko ma sens w zasto­so­wa­niu produkcyjnym), a także zamienić encję OReillyCopyright na HTML, tak jak to zo­sta­ło opisane w rozdziale 6. Cocoon obsługuje sprawdzanie poprawności i encje zewnętrzne, ale na razie nie należy zaprzątać sobie głowy zbyt wieloma szczegółami.

Teraz można już załadować plik, wpisując adres http://<nazwa-hosta>:<port>/contents.xml. Jeśli Czytelnik wprowadził modyfikacje opisywane w rozdziale 6., przekształcony plik XML powinien wyglądać tak jak na rysunku 9.2.

0x01 graphic

Rysunek 9.2. Plik XML z rozdziału 6. po przekształceniu

Pliki PDF utworzone z danych XML

Do tej pory mówiliśmy niemal wyłącznie o przekształcaniu dokumentów XML na HTML; w po­zo­stałych przypadkach zakładaliśmy, że dane będą przesyłane pomiędzy dwoma aplikacjami. For­mat był całkowicie umowny, jako że zarówno aplikacja wysyłająca, jak i otrzymująca prze­kształcały dane XML za pomocą określonej definicji DTD lub schematu. Jednakże struktura pu­bli­ka­cji ofe­ru­je o wiele więcej możliwości. Nie tylko obsługiwane jest przekształcanie na liczne języki znacz­ni­ków; dostępne są również biblioteki przekształcające XML na niektóre formaty nie wykorzystujące znaczników. Najbardziej popularną i stabilną biblioteką tej kategorii jest Formatting Objects Processor (FOP) grupy Apache XML, który pokrótce został już omówiony w rozdziale 6. Pozwala on na przekształcanie dokumentów XML na pliki PDF, których oglądanie umożliwia opro­gra­mo­wa­nie Adobe Acrobat (http://www.adobe.com).

Trudno przecenić możliwość przekształcania danych XML na dokumenty PDF; szczególnie w ser­wisach operujących na dokumentach, takich jak firmy drukarskie czy wydawnictwa, technologia ta może zrewolucjonizować operacje na danych. Poniższy przykład przedstawia dokument XML opisujący fragment oryginalnej, angielskiej wersji rozdziału 1. niniejszej książki (przykład 9.1).

Przykład 9.1. Wersja XML rozdziału 1.

<?xml version="1.0"?>

<?cocoon-process type="xslt"?>

<?xml-stylesheet href="XSL/JavaXML.fo.xsl" type="text/xsl"?>

<book>

<cover>

<title>Java and XML</title>

<author>Brett McLaughlin</author>

</cover>

<contents>

<chapter id="chapterOne">

</title>

<paragraph>XML. These three letters have brought shivers to

almost every developer in the world today at some point in the

last two years. While those shivers were often fear at another

acronym to memorize, excitement at the promise of a new technology,

or annoyance at another source of confusion for today's

developer, they were shivers all the same. Surprisingly, almost every

type of response was well merited with regard to XML. It is another

acronym to memorize, and in fact brings with it a dizzying array of

companions: XSL, XSLT, PI, DTD, XHTML, and more. It also brings with

it a huge promise-what Java did for portability of code, XML claims

to do for portability of data. Sun has even been touting the

rather ambitious slogan "Java + XML = Portable Code + Portable

Data" in recent months. And yes, XML does bring with it a

significant amount of confusion. We will seek to unravel and

demystify XML, without being so abstract and general as to be

useless, and without diving in so deeply that this becomes just

another droll specification to wade through. This

is a book for you, the Java developer, who wants to understand the

hype and use the tools that XML brings to the table.</paragraph>

<paragraph>Today's web application now faces a wealth of problems

that were not even considered ten years ago. Systems that are

distributed across thousands of miles must perform quickly and

flawlessly. Data from heterogeneous systems, databases, directory

services, and applications must be transferred without a single

decimal place being lost. Applications must be able to communicate

not only with other business components, but other business systems

altogether, often across companies as well as technologies. Clients

are no longer limited to thick clients, but can be web browsers that

support HTML, mobile phones that support Wireless Application

Protocol (WAP), or handheld organizers with entirely different markup

languages altogether. Data, and the transformation of that data, has

become the crucial centerpiece of every application being developed

today.</paragraph>

</chapter>

</contents>

</book>

Czytelnik wie już, jak przekształcać taki dokument na dokument HTML. Ale przekształcenie ca­łe­go rozdziału książki do tego formatu dałoby w wyniku ogromny dokument HTML, bardzo trudny w odczycie; potencjalny Czytelnik na pewno wolałby otrzymać dokument PDF. Z drugiej strony, jeśli generujemy statycznie PDF, to musimy zapewnić, że zmiany wprowadzone w rozdziale zo­sta­ną odzwierciedlone w nowym pliku PDF. Przechowywanie pliku w jednolitym formacie XML umożliwia prostą jego aktualizację (za pomocą dowolnego edytora XML), formatowanie do SGML-a w celu wydrukowania, przesyłanie do innych firm i aplikacji oraz dołączanie do innych książek lub kompendiów. Jeśli dodamy do tego prostotę użytkowania (wystarczy wpisać w prze­glą­darce adres URL), to otrzymujemy kompletny system publikacji.

Nie będziemy szczegółowo omawiali obiektów formatujących i interfejsu FOP — definicja takich obiektów znajduje się w specyfikacji XSL pod adresem http://www.w3.org/TR/xsl/. W przykładzie 9.2 pokazano arkusz stylu XSL, który umożliwia przekształcenie danych XML na dokument PDF.

Przykład 9.2. Arkusz XSL konwertujący dane z przykładu 9.1 na dokument PDF

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

xmlns:fo="http://www.w3.org/1999/XSL/Format">

<xsl:template match="book">

<xsl:processing-instruction name="cocoon-format">

type="text/xslfo"

</xsl:processing-instruction>

<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">

<fo:layout-master-set>

<fo:simple-page-master

page-master-name="right"

margin-top="75pt"

margin-bottom="25pt"

margin-left="100pt"

margin-right="50pt">

<fo:region-body margin-bottom="50pt"/>

<fo:region-after extent="25pt"/>

</fo:simple-page-master>

<fo:simple-page-master

page-master-name="left"

margin-top="75pt"

margin-bottom="25pt"

margin-left="50pt"

margin-right="100pt">

<fo:region-body margin-bottom="50pt"/>

<fo:region-after extent="25pt"/>

</fo:simple-page-master>

</fo:layout-master-set>

<fo:page-sequence>

<fo:sequence-specification>

<fo:sequence-specifier-alternating

page-master-first="right"

page-master-odd="right"

page-master-even="left"/>

</fo:sequence-specification>

<fo:static-content flow-name="xsl-after">

<fo:block text-align-last="centered" font-size="10pt">

<fo:page-number/>

</fo:block>

</fo:static-content>

<fo:flow>

<xsl:apply-templates/>

</fo:flow>

</fo:page-sequence>

</fo:root>

</xsl:template>

<xsl:template match="cover/title">

<fo:block font-size="36pt" text-align-last="centered"

space-before.optimum="24pt">

<xsl:apply-templates/>

</fo:block>

</xsl:template>

<xsl:template match="author">

<fo:block font-size="24pt" text-align-last="centered"

space-before.optimum="24pt">

<xsl:apply-templates/>

</fo:block>

</xsl:template>

<xsl:template match="chapter">

<xsl:apply-templates/>

</xsl:template>

<xsl:template match="chapter/title">

<fo:block font-size="24pt" text-align-last="centered"

space-before.optimum="24pt">

<xsl:apply-templates/>

</fo:block>

</xsl:template>

<xsl:template match="paragraph">

<fo:block font-size="12pt" space-before.optimum="12pt"

text-align="justified">

<xsl:apply-templates/>

</fo:block>

</xsl:template>

</xsl:stylesheet>

Po utworzeniu obu powyższych plików i zapisaniu rozdziału jako plik chapterOne.xml oraz ar­ku­sza jako JavaXML.fo.xsl w katalogu XSL/, można obejrzeć wyniki transformacji w przeglądarce. Przeglądarka musi być wyposażona we wtyczkę (ang. plug-in) Adobe Acrobat Reader, co umoż­liwi bezpośrednie obejrzenie pliku w przeglądarce (inaczej trzeba byłoby go zachować i przejrzeć przy użyciu innego programu). Wynikowy dokument PDF przedstawiony jest na rysunku 9.3.

Styl zależny od przeglądarki

Oprócz jawnego określania typu transformacji (np. na format PDF), Cocoon umożliwia także prze­kształcanie w zależności od rodzaju żądania. Typowym przykładem takiego zachowania jest for­ma­­towanie zależne od programu klienta. W tradycyjnym środowisku WWW dokument XML może więc zostać przekształcony w różny sposób, zależnie od tego, czy klient korzysta np. z prze­glądarki Internet Explorer czy Netscape. Biorąc pod uwagę ostatnie przepychanki firm Netscape i Microsoft odnośnie wersji HTML-a i DHTML-a, jest to na pewno bardzo przydatna funkcja. Cocoon fabrycznie obsługuje wiele popularnych typów przeglądarek. Poniżej ptrzedstawiony jest koń­cowy fragment pliku cocoon.properties.

##########################################

# User Agents (Browsers) #

##########################################

# NOTE: numbers indicate the search order. This is very important since

# some words may be found in more than one browser description. (MSIE is

# presented as "Mozilla/4.0 (Compatible; MSIE 4.01; ...")

#

# for example, the "explorer=MSIE" tag indicates that the XSL stylesheet

# associated to the media type "explorer" should be mapped to those browsers

0x01 graphic

Rysunek 9.3. Dokument PDF powstały z przykładów 9.1 i 9.2

# that have the string "MSIE" in their "user-Agent" HTTP header.

browser.0 = explorer=MSIE

browser.1 = pocketexplorer=MSPIE

browser.2 = handweb=HandHTTP

browser.3 = avantgo=AvantGo

browser.4 = imode=DoCoMo

browser.5 = opera=Opera

browser.6 = lynx=Lynx

browser.7 = java=Java

browser.8 = wap=Nokia

browser.9 = wap=UP

browser.10 = wap=Wapalizer

browser.11 = mozilla5=Mozilla/5

browser.12 = mozilla5=Netscape6/

browser.13 = netscape=Mozilla

Słowa kluczowe znajdujące się po pierwszych znakach równości (np. explorer, opera, lynx, java, netscape) określają agenty użytkowników i kody, jakie są przez nie wysyłane wraz z żą­da­niem. Spróbujmy wykorzystać te właściwości w przykładowym pliku arkusza XSL, stoso­wa­nym w przypadku, gdy klientem jest Internet Explorer. Kopiujemy nasz oryginalny arkusz stylów JavaXML.html.xsl do JavaXML.explorer-html.xsl i wprowadzamy zmiany przedstawione w przy­kładzie 9.3.

Przykład 9.3. Arkusz stylu dla przeglądarki Internet Explorer

<?xml version="1.0"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

xmlns:JavaXML="http://www.oreilly.com/catalog/javaxml/"

version="1.0"

>

<xsl:template match="JavaXML:Book">

<html>

<head>

<title>

<xsl:value-of select="JavaXML:Title" /> (wersja dla Explorera)

</title>

</head>

<body>

<xsl:apply-templates select="*[not(self::JavaXML:Title)]" />

</body>

</html>

</xsl:template>

<xsl:template match="JavaXML:Contents">

<center>

<h2>Table of Contents (wersja dla Explorera)</h2>

<small>

Natychmiast pobierz <a href="http://www.netscape.com">Netscape</a>!

</small>

</center>

...

To oczywiście dość banalny przykład, ale dobrze obrazuje prostotę zmiany sposobu wyświetlania dokumentu i np. wysyłania innych danych do przeglądarki Internet Explorer 5.0, która szerzej ob­słu­guje DHTML niż Netscape Navigator. Konieczne jest jeszcze poinformowanie dokumentu XML, że jeśli typ agenta użytkownika pasuje do zdefiniowanego we właściwościach typu ex­plo­rer, to należy użyć innego arkusza XSL. Można to wykonać za pomocą instrukcji prze­twa­rza­nia przed­sta­wionej w przykładzie 9.4.

Przykład 9.4. Dokument XML odwołujący się do wielu arkuszy stylów w zależności od klienta

<?xml version="1.0"?>

<?xml-stylesheet href="XSL\JavaXML.html.xsl" type="text/xsl"?>

<?xml-stylesheet href="XSL\JavaXML.explorer-html.xsl" type="text/xsl"

media="explorer"?>

<?xml-stylesheet href="XSL\JavaXML.wml.xsl" type="text/xsl"

media="wap"?>

<?cocoon-process type="xslt"?>

Jeśli dokument obejrzymy za pomocą Netscape Navigatora, uzyskamy takie wyniki jak po­prze­dnio, a jeśli za pomocą Internet Explorera — uzyskamy dokument przekształcony za pomocą in­ne­go arkusza stylu (rysunek 9.4.).

WAP i WML

Potężne możliwości takich dynamicznych arkuszy stylów wiążą się również z wykorzystaniem urzą­dzeń bezprzewodowych. Oto znany już Czytelnikowi fragment pliku właściwości Cocoon:

browser.0 = explorer=MSIE

browser.1 = pocketexplorer=MSPIE

browser.2 = handweb=HandHTTP

browser.3 = avantgo=AvantGo

browser.4 = imode=DoCoMo

browser.5 = opera=Opera

browser.6 = lynx=Lynx

browser.7 = java=Java

browser.8 = wap=Nokia

browser.9 = wap=UP

browser.10 = wap=Wapalizer

browser.11 = mozilla5=Mozilla/5

browser.12 = mozilla5=Netscape6/

browser.13 = netscape=Mozilla

0x01 graphic

Rysunek 9.4. „Explorerowa” wersja wygenerowanej strony HTML

Wyróżnione wpisy pozwalają wykryć agenta bezprzewodowego, np. telefon z dostępem do In­ter­netu. Cocoon, tak jak wcześniej rozpoznawał przeglądarkę, teraz wysyła arkusz stylu odpowiedni dla urządzenia WAP. Do tej pory nie przywiązywaliśmy dużej wagi do poniższego fragmentu na­szego pliku XML, określającego arkusz stylu używanego w przypadku takiego urządzenia:

<?xml-stylesheet href="XSL\JavaXML.html.xsl" type="text/xsl"?>

<?xml-stylesheet href="XSL\JavaXML.explorer-html.xsl" type="text/xsl"

media="explorer"?>

<?xml-stylesheet href="XSL\JavaXML.wml.xsl" type="text/xsl"

media="wap"?>

<?cocoon-process type="xslt"?>

Teraz jednak omówimy go szczegółowo. W urządzeniach WAP wykorzystywany jest zazwyczaj język Wireless Markup Language (WML). Jest to odmiana HTML-a, różniąca się sposobem re­pre­zentacji poszczególnych stron. Kiedy urządzenie bezprzewodowe wysyła żądanie pobrania pliku spod adresu URL, zwrócona treść musi być zawarta w znaczniku wml. W tym elemencie głównym definiuje się szereg kart (ang. cards) — każdą opisuje element WML card. Urządzenie pobiera wiele kart jednocześnie (określane są one mianem pliku kart (ang. deck of cards)), dzięki czemu nie musi ponownie odwoływać się do serwera w celu wyświetlenia kolejnych ekranów. W przy­kładzie 9.5 pokazano przykładową stronę XML wykorzystującą takie konstrukcje.

Przykład 9.5 Prosta strona WML

<wml>

<card id="index" title="Strona domowa">

<p align="left">

<i>Menu główne</i><br />

<a href="#tytul">Strona tytułowa</a><br />

<a href="#mojaStrona">Moja strona</a><br />

</p>

</card>

<card id="tytul" title="Moja strona tytułowa">

Witam na mojej stronie domowej!<br />

Tak miło was tu gościć.

</card>

<card id="mojaStrona" title="Hello World">

<p align="center">

Hello World!

</p>

</card>

</wml>

Na żądanie treści WML zwrócona zostałaby odpowiedź w postaci --> menu i dwóch ekranów [Author:AJ] za­war­tości, dostępnych poprzez odsyłacze z menu. Pełna specyfikacja WML 1.1 dostępna jest pod adre­sem http://updev.phone.com/dev/ts/; wcześniej trzeba się nieodpłatnie zarejestrować pod adresem http://updev.phone.com. Z tej witryny można również pobrać oprogramowanie UP.SDK, emulu­ją­ce urządzenie bezprzewodowe. Wystarczy w nim wpisać adres http://<nazwa-hosta>:<port>/con­tents.xml i obejrzeć wynik działania arkusza XSL dla urządzenia WAP.

Ponieważ wyświetlacze telefonów są bardzo małe, będziemy chcieli wyświetlić jedynie podzbiór informacji zawartych w naszym spisie treści. W przykładzie 9.6 przedstawiono arkusz wyświe­tla­jący trzy karty w WML-u. Pierwsza to menu z odsyłaczami do dwóch pozostałych. Druga karta to wynik generacji spisu treści z dokumentu contents.xml. Trzecia to prosty ekran z prawami au­tor­skimi. Arkusz stylów zachowujemy jako JavaXML.wml.xsl w podkatalogu XSL/ katalogu głów­ne­go serwera.

Przykład 9.6. Arkusz XSL umożliwiający wyświetlenie spisu treści w urządzeniu WAP

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

xmlns:JavaXML="http://www.oreilly.com/catalog/javaxml/"

exclude-result-prefixes="JavaXML"

>

<xsl:template match="JavaXML:Ksiazka">

<xsl:processing-instruction name="cocoon-format">

type="text/wml"

</xsl:processing-instruction>

<wml>

<card id="index" title="{JavaXML:Tytul}">

<p align="center">

<i><xsl:value-of select="JavaXML:Tytul" /></i><br />

<a href="#contents">Spis</a><br/>

<a href="#copyright">Copyright</a><br/>

</p>

</card>

<xsl:apply-templates select="JavaXML:Spis" />

<card id="copyright" title="Copyright">

<p align="center">

Copyright 2000, O&apos;Reilly &amp; Associates

</p>

</card>

</wml>

</xsl:template>

<xsl:template match="JavaXML:Spis">

<card id="contents" title="Spis">

<p align="center">

<i>Spis</i><br />

<xsl:for-each select="JavaXML:Rozdzial">

<xsl:number value="position()" format="1: " />

<xsl:value-of select="JavaXML:Naglowek" /><br />

</xsl:for-each>

</p>

</card>

</xsl:template>

</xsl:stylesheet>

Poza nowymi znacznikami WML, powyższy przykład nie powinien sprawiać Czytelnikowi żad­nych trudności. Wprowadzono nową funkcję XSL, position() oraz nowy element xsl:num­ber. W ten sposób w pętli xsl:for-each dodawana jest numeracja:

1: Wprowadzenie

2: Pisanie w XML-u

...

Dodano także instrukcje przetwarzania dla struktury Cocoon, w której cel określono jako cocoon-format. Przesyłane dane, type="text/wml", instruują Cocoon, że arkusz stylu ma być wy­świetlony z nagłówkiem zawartości w postaci text/wml (a nie text/html lub text/plain, jak to się dzieje standardowo). I jeszcze jeden istotny dodatek w postaci atrybutu w elemencie głów­nym arkusza:

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

xmlns:JavaXML="http://www.oreilly.com/catalog/javaxml/"

exclude-result-prefixes="JavaXML"

>

Domyślnie każda deklaracja przestrzeni nazw XML inna niż przestrzeń XSL jest dodawana do elementu głównego danych wyjściowych transformacji. W naszym przykładzie element główny da­nych wyjściowych, wml, zostałby opatrzony następującą deklaracją przestrzeni nazw:

<wml xmlns:JavaXML="http://www.oreilly.com/catalog/javaxml/">

...

</wml>

Spowodowałoby to błąd przeglądarki WAP, jako że xmlns:JavaXML nie jest dozwolonym atry­butem elementu wml. Przeglądarki tego typu nie są tak tolerancyjne jak przeglądarki HTML i re­szta zawartości po prostu nie zostałaby wyświetlona. Jednakże my musimy zadeklarować przestrzeń nazw, aby arkusz XSL mógł dopasować szablon dla dokumentu wejściowego — a to właśnie wykonujemy poprzez przestrzeń JavaXML. Problem można rozwiązać poprzez dodanie atrybutu exclude-result-prefixes do elementu xsl:stylesheet. Przedrostek przestrzeni nazw określony w tym atrybucie nie będzie dodawany do danych wyjściowych — a tego właśnie sobie ży­czymy. Teraz dane wyjściowe będą „otoczone” znacznikami:

<wml>

...

</wml>

Taki zapis przeglądarka WAP rozumie doskonale. Jeśli pobraliśmy przeglądarkę UP.SDK, mo­że­my wpisać w niej adres naszego spisu treści i obejrzeć wynik (do wyświetlenia stron WAP tłumacz wykorzystał emulator Deck-It firmy PyWeb, który można nieodpłatnie pobrać ze strony http://PyWeb.com; przeglądarka UP.SDK w czasie tłumaczenia nie była dostępna w wersji dla systemu Linux — przyp.tłum.). Na rysunku 9.5 widoczne jest menu główne wyświetlane wtedy, gdy pliku contents.xml zażąda poprzez Cocoon urządzenie WAP.

Na rysunku 9.6 widzimy wygenerowany spis treści, dostępny po odwiedzeniu odsyłacza „Spis”, pokazanego na poprzednim rysunku.

Więcej informacji o standardach WML i WAP można znaleźć na stronach http://www.phone.comhttp://www.wapforum.org; oba te miejsca są obszernymi źródłami wiedzy o urządzeniach bez­prze­wodowych.

Teraz już Czytelnik powinien dość dobrze orientować się, jak różne dane wyjściowe można uzys­kać dzięki oprogramowaniu Cocoon. Niewielki wysiłek, jakiś dodatkowy arkusz stylu — i już ten sam dokument można serwować w wielu formatach rozmaitym klientom. To między innymi dla­tego struktury publikacji są tak potężnym narzędziem. Bez XML-a i podobnego oprogramowania, dla każdego typu klienta trzeba byłoby tworzyć oddzielny serwis. Skoro jednak znamy już moż­li­wości struktury Cocoon, przejdźmy do omówienia sposobu dynamicznego tworzenia i dostoso­wa­nia danych wejściowych transformacji przy użyciu oprogramowania Cocoon.

XSP

XSP to Extensible Server Pages, czyli rozszerzalne strony serwera. To chyba najważniejsza no­winka mająca swoje źródła w projekcie Cocoon. Z pewnością Czytelnik spotkał się już z terminem Java Server Pages (JSP). JSP to (w skrócie) znaczniki i zagnieżdżony kod Javy wstawiany do, skądinąd zupełnie zwyczajnej, strony HTML. Po otrzymaniu żądania takiej strony zawarty w niej kod

0x01 graphic

Rysunek 9.5. Główne menu WML

0x01 graphic

Rysunek 9.6. Spis treści WML

jest wykonywany, a wynik wstawiany bezpośrednio do danych wynikowych HTML. Te­ch­no­logia ta zawładnęła Javą i ASP, upraszczając programowanie w Javie po stronie serwera i umoż­li­wia­jąc separację danych wyjściowych i procesów logicznych. Jednakże nie uniknięto pewnych istotnych problemów. Po pierwsze, JSP tak naprawdę nie oddziela zawartości i prezentacji. Problem ten już był sygnalizowany w książce — zmiana bannera, koloru fontu czy rozmiaru tekstu wymaga mo­dy­fi­kacji JSP (wraz z wpisanymi odwołaniami do Javy i JavaBean). Zawartość (czyste dane) miesza się z prezentacją, podobnie jak w statycznym HTML-u. Po drugie, nie ma możliwości przekon­wer­towania JSP na jakikolwiek inny format lub użycia go do komunikacji pomiędzy aplikacjami — JSP stworzono głównie do prezentacji danych wyjściowych.

XSP stanowi remedium na oba te problemy. Po pierwsze, XSP to właściwie zwykły XML. W przy­kładzie 9.7 przedstawiona jest strona XSP.

Przykład 9.7. Przykładowa strona XSP

<?xml version="1.0"?>

<?cocoon-process type="xsp"?>

<?cocoon-process type="xslt"?>

<?xml-stylesheet href="myStylesheet.xsl" type="text/xsl"?>

<xsp:page language="java"

xmlns:xsp="http://www.apache.org/1999/XSP/Core"

>

<xsp:logic>

private static int numHits = 0;

private synchronized int getNumHits() {

return ++numHits;

}

</xsp:logic>

<page>

<title>Licznik odwiedzin</title>

<p>Pobierano mnie <xsp:expr>getNumHits()</xsp:expr> razy.</p>

</page>

</xsp:page>

Utrzymano zgodność ze wszystkimi konwencjami XML; chwilowo element xsp:logic od­czy­tu­jemy jako „zakaz wstępu” dla parsera — element ten zostanie omówiony w dalszej części roz­działu. Poza tym cały dokument to zwykłe dane XML zawierające parę nowych elementów. Jest tu nawet odwołanie do arkusza stylu, który nie zawiera żadnych nowości (przykład 9.8).

Przykład 9.8. Arkusz stylu XSL dla przykładu 9.7

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

>

<xsl:template match="page">

<xsl:processing-instruction name="cocoon-format">

type="text/html"

</xsl:processing-instruction>

<html>

<head>

<title><xsl:value-of select="title"/></title>

</head>

<body>

<xsl:apply-templates select="*[not(self::title)]" />

</body>

</html>

</xsl:template>

<xsl:template match="p">

<p align="center">

<xsl:apply-templates />

</p>

</xsl:template>

</xsl:stylesheet>

Zatem XSP w prosty sposób likwiduje więc pierwszy problem związany z JSP — umożliwia od­dzielenie zawartości od prezentacji. Dzięki takiej separacji programista może zająć się generacją treści (strona XSP może być statyczna, ale może być także generowana z serwletu lub innego kodu Ja­vy), zaś autorzy XML i XSL zajmują się prezentacją i stylami poprzez modyfikację arkusza stylu. W podobny sposób rozwiązywana jest druga bolączka JSP — ponieważ przetwarzanie XSP wyko­ny­wane jest przed zastosowaniem arkuszy stylów, wynikowy dokument XML może zostać prze­two­rzony na dowolny inny format. Strona XSP może więc być przekazywana pomiędzy aplikacjami równie łatwo, jak wykorzystywana w prezentacji.

Tworzenie strony XSP

Teraz, kiedy Czytelnik poznał już XSP, spróbujmy stworzyć własną stronę w tym standardzie. Da­lej jako przykład będziemy stosowali utworzony już wcześniej dokument XML. Zamiast po prostu wyświetlać nasz dokument, załóżmy, że autor chciałby pokazywać go redaktorowi w miarę pisa­nia. Oprócz tekstu książki redaktor powinien widzieć komentarze autora; komentarze te nie są jednak przeznaczone dla oczu zwykłego czytelnika — na przykład dotyczą formatowania i stylu. Najpierw dodajmy taki komentarz do stworzonego wcześniej pliku chapterOne.xml.

<contents>

<chapter id="chapterOne">

<title>Chapter 1: Introduction</title>

<paragraph>XML. These three letters have brought shivers to

almost every developer in the world today at some point in the

last two years. While those shivers were often fear at another

acronym to memorize, excitement at the promise of a new technology,

or annoyance at another source of confusion for today's

developer, they were shivers all the same. Surprisingly, almost every

type of response was well merited with regard to XML. It is another

acronym to memorize, and in fact brings with it a dizzying array of

companions: XSL, XSLT, PI, DTD, XHTML, and more. It also brings with

it a huge promise-what Java did for portability of code, XML claims

to do for portability of data. Sun has even been touting the

rather ambitious slogan "Java + XML = Portable Code + Portable

Data" in recent months. And yes, XML does bring with it a

significant amount of confusion. We will seek to unravel and

demystify XML, without being so abstract and general as to be

useless, and without diving in so deeply that this becomes just

another droll specification to wade through. This

is a book for you, the Java developer, who wants to understand the

hype and use the tools that XML brings to the table.</paragraph>

<authorComment>Czy ten akapit jest poprawnie sformatowany, czy

rozdzielamy go na dwa oddzielne akapity? Mike, poinformuj mnie

o swojej decyzji w tym zakresie.</authorComment>

<paragraph>Today's web application now faces a wealth of problems

that were not even considered ten years ago. Systems that are

distributed across thousands of miles must perform quickly and

flawlessly. Data from heterogeneous systems, databases, directory

services, and applications must be transferred without a single

decimal place being lost. Applications must be able to communicate

not only with other business components, but other business systems

altogether, often across companies as well as technologies. Clients

are no longer limited to thick clients, but can be web browsers that

support HTML, mobile phones that support Wireless Application

Protocol (WAP), or handheld organizers with entirely different markup

languages altogether. Data, and the transformation of that data, has

become the crucial centerpiece of every application being developed

today.</paragraph>

</chapter>

</contents>

</book>

Po wstawieniu do dokumentu takiego komentarza dodajmy odpowiedni wpis w arkuszu stylów, JavaXML.fo.xsl.

<xsl:template match="paragraph">

<fo:block font-size="12pt" space-before.optimum="12pt"

text-align="justified">

<xsl:apply-templates/>

</fo:block>

</xsl:template>

<xsl:template match="authorComment">

<fo:block font-size="10pt" font-style="italic" color="blue"

space-before.optimum="12pt"

text-align="justified">

<xsl:apply-templates/>

</fo:block>

</xsl:template>

Po wprowadzeniu powyższego wpisu komentarze będą nieco mniejsze niż reszta tekstu, niebieskie i pisane kursywą. Teraz nasz dokument XML należy przekształcić na stronę XSP (jak w przy­kła­dzie 9.9) — dodając wymagane instrukcje przetwarzania dla struktury Cocoon i otaczając ele­men­ty nowym elementem głównym, xsp:page.

Przykład 9.9. Wersja XSP przykładu 9.1

<?xml version="1.0"?>

<?cocoon-process type="xsp"?>

<?cocoon-process type="xslt"?>

<?xml-stylesheet href="XSL/JavaXML.fo.xsl" type="text/xsl"?>

<xsp:page

language="java"

xmlns:xsp="http://www.apache.org/1999/XSP/Core"

xmlns:JavaXML="http://www.oreilly.com/catalog/javaxml/"

>

<book>

<cover>

<title>Java i XML</title>

<author>Brett McLaughlin</author>

</cover>

<!-- Zawartość rozdziału -->

</book>

</xsp:page>

Zanim zajmiemy się kodem XSP odpowiedzialnym za wyświetlenie komentarza, zbudujmy prostą stronę HTML umożliwiającą określenie, czy odwiedzający jest redaktorem książki. W prawdziwej aplikacji na tej stronie odbywałoby się uwierzytelnianie i określanie roli użytkownika; w naszym przypadku użytkownik będzie mógł określić się jako autor, edytor lub po prostu ciekawski czy­telnik i podać hasło. Odpowiednia strona HTML przedstawiona jest w przykładzie 9.10. Zapiszmy ją jako entry.html w katalogu głównym serwera WWW.

Przykład 9.10. Interfejs HTML do wyboru „roli” użytkownika

<html>

<head>

<title>Witamy na stronie roboczej wersji Java i XML</title>

</head>

<body>

<h1 align="center"><i>Java i XML</i> wersja robocza</h1>

<center>

<form action="/chapterOne.xml" method="POST">

Wybierz:

<select name="userRole">

<option value="author">Jestem autorem</option>

<option value="editor">Jestem redaktorem</option>

<option value="reader">Jestem czytelnikiem</option>

</select>

<br />

Wpisz haslo:

<input type="password" name="password" size="8" />

<br /><br />

<input type="submit" value="Do czytania!" />

</form>

</center>

</body>

</html>

Należy zauważyć, że formularz HTML przekazujemy bezpośrednio do strony XSP. W tym przy­kładzie strona XSP działa jak serwlet. Chcemy, aby odczytała parametry żądania, określiła, jaki rodzaj użytkownika został podany, przeprowadziła uwierzytelnianie za pomocą hasła i wyświetliła (lub nie) komentarz. Zacznijmy od zdefiniowania zmiennej typu boolean; będzie ona zawierała wynik porównania podanego hasła z właściwym. Następnie sprawdzimy wartość tej zmiennej i jeś­li ta wartość to true, wyświetlimy element authorComment:

<xsp:page

language="java"

xmlns:xsp="http://www.apache.org/1999/XSP/Core"

xmlns:JavaXML="http://www.oreilly.com/catalog/javaxml/"

>

<book>

<cover>

<title>Java and XML</title>

<author>Brett McLaughlin</author>

</cover>

...

is a book for you, the Java developer, who wants to understand the

hype and use the tools that XML brings to the table.</paragraph>

<xsp:logic>

boolean authorOrEditor = false;

// Tu sprawdzimy, czy to autor, czy redaktor.

if (authorOrEditor) {

<xsp:content>

<authorComment>Czy ten akapit jest poprawnie sformatowany, czy

rozdzielamy go na dwa oddzielne akapity? Mike, poinformuj mnie o

swojej decyzji w tym zakresie.</authorComment>

</xsp:content>

}

</xsp:logic>

<paragraph>Today's web application now faces a wealth of problems

that were not even considered ten years ago. Systems that are

...

Czytelnik nie powinien mieć żadnych trudności — poza znacznikami specyficznymi dla XSP defi­niu­jemy tylko zmienną i sprawdzamy jej wartość. Jeśli zmienna ma wartość true, element aut­horComment jest dodawany do danych wyjściowych XSP; w przeciwnym razie — nie. Interesujące jest to, że otaczamy faktyczne dane wyjściowe XML zawarte w xsp:logic elementem xsp: page. To gwarantuje, że procesor XSP nie będzie próbował interpretować żadnych elementów ani tekstu wewnątrz tego bloku jako struktury XSP. I znów widać tutaj przewagę standardu XSP nad JSP — ten sam kod w tym ostatnim standardzie wyglądałby następująco:

<%

if (authorOrEditor) {

%>

<authorComment>Czy ten akapit jest poprawnie sformatowany, czy

rozdzielamy go na dwa oddzielne akapity? Mike, poinformuj mnie o

swojej decyzji w tym zakresie.</authorComment>

<%

}

%>

Jest to mniej zrozumiała struktura — blok JSP kończy się, zanim jeszcze element authorComment się zaczyna; następnie po elemencie dołączany jest kolejny blok, zamykający nawias otwarty w bloku pierwszym. Bardzo łatwo pomylić sposoby kodowania lub zapomnieć o „zamykających” blokach JSP; XSP wymusza zamknięcie każdego otwartego elementu (standardowe poprawne formatowanie XML-a), a jeden blok kodu odpowiada jednemu elementowi.

Po wprowadzeniu struktur logicznych należy już tylko zinterpretować parametry żądania. Do tego celu służy wbudowana zmienna XSP request, ktora „naśladuje” obiekt HttpServlet­Re­quest. Kod po wprowadzeniu poniższych modyfikacji odczytuje wartość parametrów userRole i password (jeśli istnieją); wartość ta następnie jest porównywana z rolami, które mają prawo do obejrzenia komentarza (autor i redaktor). Jeśli dopasowanie się powiedzie, sprawdzane jest jeszcze hasło. Jeśli hasło odpowiada kluczowi podanej roli, zmienna boolowska jest włączana (wartość true), a element authorComments stanowi część danych wyjściowych XML:

<xsp:logic>

boolean authorOrEditor = false;

// Poniżej sprawdzimy, czy to autor czy redaktor

<![CDATA[

String[] roleValues = request.getParameterValues("userRole");

String[] passwordValues = request.getParameterValues("password");

if ((roleValues != null) && (passwordValues != null)) {

String userRole = roleValues[0];

String password = passwordValues[0];

if (userRole.equals("author") && password.equals("brett")) {

authorOrEditor = true;

} else

if (userRole.equals("editor") && password.equals("mike")) {

authorOrEditor = true;

}

]]>

}

if (authorOrEditor) {

<xsp:content>

<authorComment>Czy ten akapit jest poprawnie sformatowany, czy

rozdzielamy go na dwa oddzielne akapity? Mike, poinformuj mnie o

swojej decyzji w tym zakresie.</authorComment>

</xsp:content>

}

</xsp:logic>

Czytelnik winien zauważyć, że spory fragment instrukcji logicznych został ujęty w znacznik CDATA. Trzeba pamiętać, że XSP zawsze jest przetwarzane jako XML i musi być zgodne z zasadami tego standardu; ale cudzysłowy i „ampersandy” (symbole &apm;) używane we fragmentach w Javie nie są dozwolone w XML-u; zamiast więc znosić ich specjalne znaczenie i wprowadzać ogromne za­mieszanie, należy użyć znacznika CDATA, w którym można sobie spokojnie pisać w Javie. Bez niego kod wyglądałby następująco:

<xsp:logic>

boolean authorOrEditor = false;

String[] roleValues =

request.getParameterValues(&quot;userRole&quot;);

String[] passwordValues = request.getParameterValues(&quot;password&quot;);

if ((roleValues != null) &amp;&amp; (passwordValues != null)) {

String userRole = roleValues[0];

String password = passwordValues[0];

if (userRole.equals("author") &amp;&amp;

password.equals("brett")) {

authorOrEditor = true;

} else

if (userRole.equals("editor") &amp;&amp;

password.equals("mike")) {

authorOrEditor = true;

}

}

...

</xsp:logic>

Teraz można przetestować stronę „wejściową” i dokument PDF powstały z danych XML. Po „skie­rowaniu” przeglądarki na stronę http://<nazwa-hosta>:<port>//entry.html Czytelnik powi­nien uzyskać wynik podobny do tego na rysunku 9.7.

0x01 graphic

Rysunek 9.7. „Wejściowa” strona HTML

Wybieramy rolę autora i podajemy hasło „brett” albo rolę redaktora i hasło „mike”. W obu przy­padkach uzyskamy dokument PDF przedstawiony na rysunku 9.8.

0x01 graphic

Rysunek 9.8. Wygenerowany dokument PDF z komentarzami

Trzeba już tylko odizolować instrukcje logiczne od samej zawartości. Podobnie jak w JSP mo­ż­li­we jest włączanie obiektów JavaBean i tym samym oddzielanie zawartości i prezentacji od logiki aplikacji, XSP umożliwia tworzenie bibliotek znaczników. Później, za pomocą znaczników XML, uruchamiany jest odpowiedni kod znajdujący się wewnątrz takiej biblioteki.

Biblioteki znaczników XSP

Oprócz wyświetlenia komentarzy, należy również zaznaczyć, że oglądany rozdział to wersja ro­bo­cza; oprócz tego powinna zostać wyświetlona data zmian w wersji roboczej (która zostanie „za­mro­żo­na” po ukończeniu rozdziału). Zamiast dopisywać kod Javy ładujący bieżącą datę, można stworzyć do tego celu własną bibliotekę znaczników. Przy okazji Czytelnik dowie się, jak stworzyć element XSP pobierający numer i tytuł rozdziału, a następnie formatujący odpowiedni nagłówek. Za pomocą tej funkcji można obsłużyć również wspomnianą operację na dacie. Najpierw konieczne jest utworzenie biblioteki znaczników dostępnej z naszej strony XSP. Większa część takiej biblioteki oparta jest na arkuszu stylu XSL. Zaczniemy od szkieletu pokazanego w przykładzie 9.11, który po prostu przekazuje wszystkie otrzymane dane na wyjście. Szkielet ten zachowamy w podkatalogu XSL/, w pliku JavaXML.xsp.xsl. Trzeba pamiętać o dołączeniu deklaracji przestrzeni nazw Ja­va­XML, ponieważ wykorzystamy ją do dopasowania elementów na naszych stronach XSP.

Przykład 9.11. Arkusz logiki XSP

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

xmlns:xsp="http://www.apache.org/1999/XSP/Core"

xmlns:JavaXML="http://www.oreilly.com/catalog/javaxml/"

>

<xsl:template match="xsp:page">

<xsp:page>

<xsl:copy>

<xsl:apply-templates select="@*"/>

</xsl:copy>

<xsl:apply-templates/>

</xsp:page>

</xsl:template>

<xsl:template match="@*|*|text()|processing-instruction()">

<xsl:copy>

<xsl:apply-templates

select="@*|*|text()|processing-instruction()"/>

</xsl:copy>

</xsl:template>

</xsl:stylesheet>

Dopasowując znacznik xsp:page gwarantujemy, że wszystkie elementy zostaną dopasowane i ob­służone wewnątrz tego arkusza stylu (czy też, zgodnie z nazewnictwem XSP, arkusza logiki). Te­raz dodajemy metody Javy do wywołania przez szablony wewnątrz arkusza:

<xsl:template match="xsp:page">

<xsp:page>

<xsl:copy>

<xsl:apply-templates select="@*"/>

</xsl:copy>

<xsp:structure>

<xsp:include>java.util.Date</xsp:include>

<xsp:include>java.text.SimpleDateFormat</xsp:include>

</xsp:structure>

<xsp:logic>

private String getDraftDate() {

return (new SimpleDateFormat("MM/dd/yyyy"))

.format(new Date());

}

private String getTitle(int chapterNum, String chapterTitle) {

return "Chapter " + chapterNum + ": " + chapterTitle;

}

</xsp:logic>

<xsl:apply-templates/>

</xsp:page>

</xsl:template>

Wprowadzono tutaj szereg nowych elementów XSP. Po pierwsze, element xsp:structure ota­cza elementy xsp:include. Te ostatnie działają podobnie jak include w języku Java — udo­stępniają określone klasy Javy, których można teraz używać za pomocą niekwalifikowanych nazw (zamiast pełnych nazw pakietów). Następnie definiujemy i implementujemy dwie metody — jedna tworzy tytuł rozdziału z numeru i tekstowej postaci tytułu, a druga zwraca bieżącą datę w postaci sformatowanej zmiennej String. Metody te dostępne są z poziomu dowolnego elementu w tym arkuszu logiki.

Teraz należy zdefiniować element określający, kiedy dane XSP mają zastąpić element XML. Już zde­finiowaliśmy przestrzeń nazw JavaXML w elemencie głównym dokumentu, a więc używamy jej w elementach naszej biblioteki znaczników. Dodajemy następujący szablon:

<!-- Tworzenie sformatowanego tytułu -->

<xsl:template match="JavaXML:draftTitle">

<xsp:expr>getTitle(<xsl:value-of select="@chapterNum" />,

"<xsl:value-of select="@chapterTitle" />")

</xsp:expr> - <xsp:expr>getDraftDate()</xsp:expr>

</xsl:template>

<xsl:template match="@*|*|text()|processing-instruction()">

<xsl:copy>

<xsl:apply-templates

select="@*|*|text()|processing-instruction()"/>

</xsl:copy>

</xsl:template>

</xsl:stylesheet>

Kiedy w dokumencie odwołującym się do takiej biblioteki znaczników użyjemy elementu Java­XML:draftTitle, do wyniku metody getTitle() zostanie dołączony łącznik (-), a na­stęp­nie wartość zwracana przez getDate(). Element JavaXML:draftTitle również wymaga zadeklarowania dwóch atrybutów: numeru rozdziału i tytułu w postaci tekstowej. Procesor XSP otrzymuje informację, że wywołujemy zdefiniowaną metodę, poprzez ujęcie wywołania tej me­to­dy w znaczniki <xsp:expr>. Aby zaznaczyć, że drugi argument (tytuł rozdziału) jest zmienną String, ujmujemy go w cudzysłowy. Ponieważ tytuł rozdziału powinien być traktowany jako int, zostawiamy go bez cudzysłowów.

Po stworzeniu arkusza logiki XSP (można go również pobrać ze strony WWW niniejszej książki) trzeba go udostępnić strukturze Cocoon. Można to zrobić na dwa sposoby. Pierwszy z nich polega na określeniu położenia pliku (w postaci URI), aby mógł zostać odnaleziony przez mechanizm serw­letów (a więc również przez Cocoon). Na przykład, aby dodać w ten sposób arkusz XSP do zasobów Cocoon, należy wpisać następujący wiersz do pliku cocoon.properties. Wersja uniksowa:

processor.xsp.logicsheet.context.java = resource://org/apache/cocoon/processor/xsp/library/java/context.xsl

processor.xsp.logicsheet.cookie.java = resource://org/apache/cocoon/processor/xsp/library/java/cookie.xsl

processor.xsp.logicsheet.global.java = resource://org/apache/cocoon/processor/xsp/library/java/global.xsl

processor.xsp.logicsheet.request.java = resource://org/apache/cocoon/processor/xsp/library/java/request.xsl

processor.xsp.logicsheet.response.java = resource://org/apache/cocoon/processor/xsp/library/java/response.xsl

processor.xsp.logicsheet.session.java = resource://org/apache/cocoon/processor/xsp/library/java/session.xsl

processor.xsp.logicsheet.util.java = resource://org/apache/cocoon/processor/xsp/library/java/util.xsl

processor.xsp.logicsheet.sql.java = resource://org/apache/cocoon/processor/xsp/library/sql/sql.xsl

processor.xsp.logicsheet.fp.java = resource://org/apache/cocoon/processor/xsp/library/fp/fp.xsl

processor.xsp.logicsheet.JavaXML.java = file:///usr/local/jakarta-tomcat/webapps/ROOT/XSL/JavaXML.xsp.xsl

Wersja Windows:

processor.xsp.logicsheet.context.java = resource://org/apache/cocoon/processor/xsp/library/java/context.xsl

processor.xsp.logicsheet.cookie.java = resource://org/apache/cocoon/processor/xsp/library/java/cookie.xsl

processor.xsp.logicsheet.global.java = resource://org/apache/cocoon/processor/xsp/library/java/global.xsl

processor.xsp.logicsheet.request.java = resource://org/apache/cocoon/processor/xsp/library/java/request.xsl

processor.xsp.logicsheet.response.java = resource://org/apache/cocoon/processor/xsp/library/java/response.xsl

processor.xsp.logicsheet.session.java = resource://org/apache/cocoon/processor/xsp/library/java/session.xsl

processor.xsp.logicsheet.util.java = resource://org/apache/cocoon/processor/xsp/library/java/util.xsl

processor.xsp.logicsheet.sql.java = resource://org/apache/cocoon/processor/xsp/library/sql/sql.xsl

processor.xsp.logicsheet.fp.java = resource://org/apache/cocoon/processor/xsp/library/fp/fp.xsl

processor.xsp.logicsheet.JavaXML.java = file:///C:/java/jakarta-tomcat/webapps/ROOT/XSL/JavaXML.xsp.xsl

Takie rozwiązanie wystarcza na potrzeby testowania, ale arkusze logiczne są wtedy silnie „zwią­za­ne” z mechanizmem serwletów, a dodawanie nowych jest kłopotliwe (konieczne jest wpisywanie kolejnych wierszy w pliku właściwości). Alternatywna metoda ładowania arkuszy logiki polega na określeniu zasobu w ścieżce dostępu do klas mechanizmu serwletów. Arkusze logiki dodawane są do pliku jar, a plik ten — do ścieżki dostępu do klas. W ten sposób w pliku powstaje centralna baza własnych arkuszy logiki XSP użytkownika. W podkatalogu XSL/ wykonujemy następujące po­lecenie, które spowoduje utworzenie pliku jar, zawierającego nasz arkusz logiki:

jar cvf logicsheets.jar JavaXML.xsp.xsl

Utworzone w ten sposób archiwum logicsheets.jar przenosimy do katalogu <TOMCAT_HO­ME>/lib/ — tam, gdzie znajdują się pozostałe biblioteki Cocoon. Teraz musimy dodać tę bibliotekę do ścieżki dostępu do klas serwera Tomcat; edytujemy plik tomcat.sh lub tomcat.bat zlokalizowany w katalogu <TOMCAT_HOME>/bin/. W systemie Unix plik ten ma wyglądać następująco:

set CLASSPATH=.

# Klasy i biblioteki Cocoon

CLASSPATH=${CLASSPATH}:${TOMCAT_HOME}/lib/xerces_1_2.jar

CLASSPATH=${CLASSPATH}:${TOMCAT_HOME}/lib/xalan_1_2_D02.jar

CLASSPATH=${CLASSPATH}:${TOMCAT_HOME}/lib/fop_0_13_0.jar

CLASSPATH=${CLASSPATH}:${TOMCAT_HOME}/lib/cocoon.jar

CLASSPATH=${CLASSPATH}:${TOMCAT_HOME}/lib/logicsheets.jar

for i in ${TOMCAT_HOME}/lib/* ; do

CLASSPATH=${CLASSPATH}:$i

done

CLASSPATH=${CLASSPATH}:${TOMCAT_HOME}/lib/tools.jar

Natomiast w Windows:

set CLASSPATH=.

set CLASSPATH=%TOMCAT_HOME%\classes

rem Klasy i biblioteki Cocoon

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\xerces_1_2.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\xalan_1_2_D02.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\fop_0_13_0.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\cocoon.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\logicsheets.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\webserver.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\jasper.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\xml.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\servlet.jar

set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\tools.jar

Teraz informujemy Cocoon, gdzie ma, szukać przestrzeni nazw JavaXML na stronach XSP. Edy­tu­­jemy plik cocoon.properties, który wcześniej umieściliśmy w katalogu <TOMCAT_HOME>/conf. Odnajd­u­je­my część mówiącą o zasobach XSP i dodajemy odwołanie do nowego arkusza logiki:

processor.xsp.logicsheet.context.java = resource://org/apache/cocoon/processor/xsp/library/java/context.xsl

processor.xsp.logicsheet.cookie.java = resource://org/apache/cocoon/processor/xsp/library/java/cookie.xsl

processor.xsp.logicsheet.global.java = resource://org/apache/cocoon/processor/xsp/library/java/global.xsl

processor.xsp.logicsheet.request.java = resource://org/apache/cocoon/processor/xsp/library/java/request.xsl

processor.xsp.logicsheet.response.java = resource://org/apache/cocoon/processor/xsp/library/java/response.xsl

processor.xsp.logicsheet.session.java = resource://org/apache/cocoon/processor/xsp/library/java/session.xsl

processor.xsp.logicsheet.util.java = resource://org/apache/cocoon/processor/xsp/library/java/util.xsl

processor.xsp.logicsheet.sql.java = resource://org/apache/cocoon/processor/xsp/library/sql/sql.xsl

processor.xsp.logicsheet.fp.java = resource://org/apache/cocoon/processor/xsp/library/fp/fp.xsl

processor.xsp.logicsheet.JavaXML.java = resource://JavaXML.xsp.xsl

Ponieważ nasz arkusz logiki nie jest zagnieżdżony w podkatalogach pliku logicsheets.jar, jako ścieżkę dostępu wystarczy określić tutaj nazwę pliku. Po tych wszystkich operacjach restartujemy mechanizm serwletów — plik cocoon.properties zostanie ponownie załadowany, a arkusz logiki udostępniony do użycia. Ponieważ żądania obsługuje mechanizm Cocoon, każda strona XSP, na któ­rej zadeklarowano użycie JavaXML, będzie miała dostęp do arkusza logiki określonego jako biblioteka JavaXML. Tak więc do naszej strony XSP musimy dodać deklarację przestrzeni nazw JavaXML:

<?xml version="1.0"?>

<?cocoon-process type="xsp"?>

<?cocoon-process type="xslt"?>

<?xml-stylesheet href="XSL/JavaXML.fo.xsl" type="text/xsl"?>

<xsp:page

language="java"

xmlns:xsp="http://www.apache.org/1999/XSP/Core"

xmlns:JavaXML="http://www.oreilly.com/catalog/javaxml/"

>

<book>

...

Skoro biblioteka znaczników jest już udostępniona, dodajemy element JavaXML:draftTitle do na­sze­go dokumentu XML, chapterOne.xml:

<contents>

<chapter id="chapterOne">

<title>

<JavaXML:draftTitle chapterNum="1"

chapterTitle="Introduction"

/>

</title>

Zakodowany „na stałe” tytuł rozdziału zamieniamy na element zdefiniowany w naszej bibliotece znaczników. W ten sposób zostanie wygenerowany tytuł i numer rozdziału oraz data wersji ro­bo­czej. Teraz można już zobaczyć efekt naszej pracy, wpisując adres dokumentu do przeglądarki WWW.

To, oczywiście, proste przykłady zastosowania standardu XSP. Ale już tutaj widać potężne moż­liwości XSP — tytuł może przybrać inną postać po ukończeniu rozdziału bez konieczności mo­dyfikacji zawartości czy warstwy prezentacyjnej strony, a jedynie arkusza XSP. Logika aplikacji jest odseparowana od zawartości i prezentacji. Do tego wszystkiego można jeszcze dołączyć lo­gikę biznesową za pomocą komponentów Javy uruchamianych po stronie serwera, np. Enterprise JavaBeans. Zastosowanie standardu XSP to rozwiązanie bardziej elastyczne niż JSP połączony z HTML-em — poszczególne komponenty nie są związane ze sobą tak ściśle. Standard XSP ma stanowić kluczowy element powstającej wersji 2.0 Cocoon.

Cocoon 2.0 i dalej

Kolejna wersja Cocoon, o numerze 2.0 stanowi ogromny krok naprzód w porównaniu z wersjami wcześniejszymi. Cocoon 1.x, w którym przede wszystkim przetwarza się XML za pośrednictwem interfejsu XSL, jest wciąż w szerokim stopniu ograniczony. Po pierwsze, oprogramowanie to na razie nie przyczynia się do znacznego zmniejszenia kosztów utrzymania dużych serwisów. Doku­ment XML może zostać przekształcony w różne formy prezentacji, ale i tak na serwerze musi istnieć spora liczba dokumentów. Konieczne jest więc korzystanie z długich identyfikatorów URI

(np. /content/publishing/books/javaxml/contents.xml), wielu odwzorowań wirtualnych ścieżek (/ja­vaxml odwzorowane na /content/publishing/books/javaxml/) albo z połączenia obu. Co więcej, wciąż nie jest łatwo odseparować prezentację od zawartości i logiki aplikacji.

W projekcie Cocoon 2 skoncentrowano się na rozdzieleniu tych różnych warstw — ma to przy­czynić się do zmniejszenia kosztów zarządzania witryną; całość ma skupiać się wokół standardu XSP. Plan witryny (o którym za chwilę) spowoduje, że użytkownik nie będzie widział różnicy pomiędzy stronami XSP, XML i statycznymi HTML. Wprowadzone zostaną również istotne zmia­ny w kompilacji i zarządzaniu pamięcią; Cocoon 2 będzie o tyle bardziej zaawansowany od Cocoon 1.x, o ile Cocoon 1.x był bardziej zaawansowany od zwykłego serwera WWW.

Odwzorowania w mechanizmie serwletów

Istotna zmiana w Cocoon 2 polega na tym, że nie będzie już trzeba stosować prostego odwzo­ro­wy­wania dokumentów XML. Odwzorowanie takie spisuje się nieźle w modelu 1.x, ale zarządzanie dokumentami innymi niż XML zrzucane jest na barki webmastera — osoby niekoniecznie zwią­za­nej z administratorem odpowiedzialnym za dokumenty XML. Cocoon 2 ma umożliwić zarzą­dza­nie całą witryną. Główny serwlet Cocoon (org.apache.cocoon.servlet.CocoonServlet w modelu 2.0) jest zazwyczaj odwzorowywany na identyfikator URI, np. /Cocoon. Możliwe jest także odwzorowanie na katalog główny całego serwera (czyli /) i tym samym sterowanie całą wi­tryną. Adres URL przyjmuje postać wynikającą z takiego odwzorowania, np. http://mojHost.com/ Co­coon/mojaStrona.xml lub http://mojHost.com/Cocoon/mojaDynamicznaStrona.xsp.

Przy takim odwzorowaniu nawet statyczne dokumenty HTML można grupować z dokumentami XML. Możliwe jest więc centralne zarządzanie wszystkimi plikami umieszczonymi na serwerze. Jeśli dokumenty HTML i XML pojawią się w jednym katalogu, nie będzie kłopotu z ich oddzielną obsługą ani z tworzeniem identyfikatorów URI. Cocoon 2 będzie obsługiwał HTML oraz dane wszelkiego innego typu; po odwzorowaniu głównego katalogu serwera na Cocoon cała struktura publikacji staje się niewidoczna dla klienta.

Plan witryny

Kolejną ważną nowością w Cocoon 2 jest plan witryny (ang. sitemap). W strukturze Cocoon plan witryny stanowi centralne miejsce administracji serwisem. Na podstawie tego planu Cocoon decy­du­je o tym, jak przetwarzać otrzymany identyfikator URI. Na przykład, kiedy otrzymuje żądanie w rodzaju http://mojaWitrynaCocoon.com/Cocoon/javaxml/chapterOne.html, serwlet Cocoon bada żądanie i określa, że faktycznie żądano /javaxml/chapterOne.html. Załóżmy jednak, że chapter­One.html nie ma być odwzorowywany na statyczny plik HTML, ale na wynik transformacji dokumentu XML (jak w naszych wcześniejszych przykładach). Tu właśnie przydaje się plan wi­tryny. Spójrzmy na plan witryny w przykładzie 9.12.

Przykład 9.12. Przykładowy plan witryny w Cocoon 2.0

<sitemap>

<process match="/javaxml/*.html">

<generator type="file" src="/docs/javaxml/*.xml">

<filter type="xslt">

<parameter name="stylesheet" value="/styles/JavaXML.html.xsl"/>

</filter>

<serializer type="html"/>

</process>

<process match="/javaxml/*.pdf">

<generator type="file" src="/docs/javaxml/*.xml">

<filter type="xslt">

<parameter name="stylesheet" value="/styles/JavaXML.pdf.xsl"/>

</filter>

<serializer type="fop"/>

</process>

</sitemap>

0x01 graphic

Definicja DTD planu witryny jest już na ukończeniu, ale w trakcie testowania beta mo­gą zostać wprowadzone zmiany. Powyższy przykład należy traktować jako zarys moż­li­wości Cocoon 2, a nie faktycznie działający kod.

Cocoon dopasowuje identyfikator URI /javaxml/chapterOne.html do instrukcji planu witryny /ja­vaxml/*.html. Następnie określa, że jest to faktyczny plik i że odnaleziony on zostanie po użyciu odwzorowania /docs/javaxml/*.xml, tłumaczonego na /docs/javaxml/chapterOne.xml (naz­wa pliku, którą chcemy przetworzyć). Następnie stosowany jest filtr XSLT; wykorzystywany ar­kusz stylu, JavaXML.html.xsl, jest także określany w planie witryny. Wynik transformacji wyświetlany jest użytkownikowi. Co więcej, plik XML może być plikiem XSP, przetwarzanym przed kon­wer­sją na XML.

Według tego samego schematu generowany jest plik PDF z żądania http://mojaWitry­na­Co­coon.com/Cocoon/javaxml/chapterOne.pdf — wystarczy tylko dodać parę wierszy do planu wit­ry­ny (patrz wyżej). Oznacza to również, że instrukcje przetwarzania w indywidualnych dokumentach można usunąć, co stanowi istotną zmianę w stosunku do Cocoon 1.x. Stosowanie arkuszy stylów i przetwarzania odbywa się na podstawie położenia katalogu. Wystarczy stworzyć dokument XML i umieścić go w katalogu /docs/javaxml (zgodnie z powyższym przykładem), a dokument ten będzie można pobrać jako HTML lub PDF. Zmiana arkuszy stylów wykorzystywanych w doku­mentach jest również banalna — w poprzedniej wersji był to proces kłopotliwy. Zamiast zmie­niać każdy dokument XML, wystarczy zmienić jeden wiersz w planie witryny.

Plan witryny jest wciąż w trakcie rozwoju i prawdopodobnie będzie jeszcze zmieniany. Aby przy­łączyć się do prac, należy zapisać się na listy adresowe cocoon-users@xml.apache.org i cocoon-dev@xml.apache.org. Pod adresem http://xml.apache.org można znaleźć szczegółowe informacje o całym projekcie Cocoon.

Producenty i procesory

Ostatnim istotnym ulepszeniem w strukturze Cocoon 2 jest wprowadzenie wstępnie kompilo­wa­nych i skoncentrowanych wokół zdarzeń producentów i procesorów (ang. producers, processors). W strukturze Cocoon producent obsługuje transformację żądania URI na strumień danych XML. Procesor pobiera następnie strumień wejściowy (obecnie w postaci dokumentu XML w drzewie DOM) i wysyła dane wyjściowe możliwe do odczytania przez klienta. Nie omówiliśmy tych komponentów w modelu Cocoon 1.x, ponieważ w modelu 2.0 ulegną one bardzo dużym zmianom; te, które używane są obecnie, staną się prawdopodobnie bezużyteczne i trzeba będzie je przepisać.

W Cocoon 2 zrezygnowano z używania w tych strukturach modelu DOM na rzecz bardziej skon­centrowanego wokół zdarzeń SAX-a (a nawet JDOM-a!), „opakowanego” strukturą DOM. Do tej pory producent musiał generować dokument XML w pamięci i odpowiadająca mu struktura DOM mogła rozrosnąć się do wielkich rozmiarów. To powodowało wyczerpanie zasobów systemowych,


szczególnie w tak skomplikowanych zadaniach jak złożone transformacje czy obsługa obiektów formatujących (generowanie PDF). Dlatego DOM będzie teraz tylko „interfejsem” do zdarzeń SAX, a producenty i procesory zyskają na wydajności.

Producenty i procesory będą kompilowane z innych formatów. Na przykład arkusze XSL można skompilować do procesorów, a strony XSP — do producentów. To jeszcze bardziej zwiększa wy­dajność i zdejmuje ciężar przetwarzania z klienta. Tutaj i wszędzie indziej wykorzystywany bę­dzie podział na poszczególne komponenty — nowy Cocoon będzie dzięki temu bardziej elasty­czny i łatwy w rozbudowie. Najnowsze wiadomości dotyczące nowego projektu można znaleźć na stro­nie WWW Cocoon.

Co dalej?

W następnym rozdziale zostanie omówiona technologia umożliwiająca wykorzystanie XML-a ja­ko formatu danych w modelu żądań i odpowiedzi XML-RPC. Rozproszony system wywoływania zdalnych procedur XML-RPC umożliwia wykonywanie zadań na serwerze (lub serwerach) znaj­dujących się w innej części sieci. Do niedawna nie cieszył się on zbytnią popularnością, co spowodowane było przede wszystkim napływem technologii opartych na RMI i związanych z Javą (szczególnie EJB). Jednakże przy wykorzystaniu XML-a jako formatu danych, XML-RPC umoż­li­wia rozwiązanie wielu problemów.

--> Chodzi o ten sam procesor FOP (procesor obiektów formatujących), który został przedstawiony w rozdziale 6., Prze­kształcanie XML-a, przy okazji opisywania konwersji XML-a na formaty nietekstowe.

Stylebook obsługuje tworzenie bardzo złożonych dokumentów (w tym w HTML-u); służy do generowania dokumentacji i strony WWW Cocoon. Projekt Stylebook ma być zintegrowany z Cocoon w wersji 2.0.

W przykładach wykorzystano wersję 3.1, ale Cocoon wymaga tylko wersji 2.x tego interfejsu serwletów. Opcje kon­fi­gu­ra­cyjne nie powinny się zmienić w innych wersjach; innymi słowy, instrukcje podane w tym rozdziale powinny „działać” w dowolnej wersji 3.x Tomcata.

W najnowszych wersjach dla systemów uniksowych Tomcat sam odnajduje klasy skopiowane do lib/, dlatego podawanie ścieżek dostępu nie jest konieczne; trzeba jednak wtedy pamiętać, że pliki z tego katalogu będą odczytywane w kolej­ności zgodnej z kolejnością alfabetyczną nazw i w razie potrzeby odpowiednio zmienić te nazwy — przyp. tłum.

To oczywiście karygodne uproszczenie; JSP jest najpierw prekompilowane do postaci serwleta, a wyjście obsługuje Print­Writer. Więcej informacji o JSP znaleźć można w książce Java Servlet Programming Jasona Huntera (O'Reilly & Associates).

Co więcej, zdarzają się kłopoty (wersje 1.7.x) z załadowaniem arkusza wpisanego w postaci file://...; problemu tego mo­ż­na uniknąć stosując zapis w postaci resource://

238 Rozdział 9. Struktury publikacji WWW

Cocoon 2.0 i dalej 237

C:\Helion\Java i XML\jAVA I xml\09-08.doc — strona 238

C:\Helion\Java i XML\jAVA I xml\09-08.doc — strona 237

C:\Helion\Java i XML\jAVA I xml\09-08.doc — strona 203

W.D.: na tej platformie? (tłumacz: tak, zdecydowanie lepiej „na tej platformie”)

W.D.: motor serwletów? (tłumacz: nie, koniecznie proszę zostawić „mechanizm”; w całej książce stosowałem taki termin i jest to dość naturalne tłumaczenie „engine”)

??? (proszę tak zostawić, chodzi o „zawartość o objętości dwóch ekranów” — ale chyba ta pierwsza wersja jest lepsza, tłum.)

W.D.: por s29 w 45 Przykład 1.8

[Author:AJ]

Wyszukiwarka

Podobne podstrony:
2531
2531
2531
2531
2531
2531

więcej podobnych podstron