3084


13

Firma-firma

Czytelnik wie już dużo o XML-u. Poznał interfejsy SAX, DOM i JDOM, znajome mu są struktury publikacji i zaawansowane transformacje, jak również model XML-RPC; zna także zagadnienia związane z za­stosowaniem XML-a w procesach konfiguracji oraz z wykorzystaniem tego języka jako źródła da­nych; potrafi również tworzyć dane XML z programów w Javie. W niniejszym rozdziale zostanie omówiony bardzo modny temat, a mianowicie zastosowanie XML-a w aplikacjach typu firma-firma. Przedsiębiorstwa wkroczyły w erę internetową i właściwa komunikacja stała się naj­waż­niej­szym warunkiem prowadzenia handlu. Wiele firm przywiązuje większą wagę do procesów komu­ni­ka­cyjnych niż... do własnych produktów. Agresywne kampanie online i aplikacje e-biznesowe mogą przyczynić się do pokonania konkurencji, która może nawet oferować atrakcyjniejsze produkty. Ogromną rolę w pojęciu „firma-firma” odgrywa XML. Język ten stanowi standardowy sposób reprezentacji danych i właśnie dzięki niemu firmy wykorzystujące różne aplikacje, systemy i języ­ki programowania mają możliwość komunikowania się ze sobą.

W niniejszym rozdziale Czytelnik dowie się, w jaki sposób za pomocą XML-a można uzyskać taką właśnie możliwość porozumienia pomiędzy różnymi aplikacjami; na potrzeby rozdziału zo­sta­ną nawet stworzone wyimaginowane firmy. Tym razem XML nie posłuży do wymiany infor­ma­cji pomiędzy składnikami jednej aplikacji ani też jako źródło danych, ale do komunikacji pomiędzy róż­nymi aplikacjami. Najpierw zostanie zaprezentowana Biblioteka Publiczna NaNiby, której dostaw­cy będą mogli wprowadzać nowe tytuły w trybie online. Książki będą następnie dodawane do skład­nicy danych biblioteki do późniejszego wykorzystania. Niestety, w dzisiejszych czasach trudno o dobrych programistów Javy, a więc nasza biblioteka będzie opierała swoje działanie na programie CGI napisanym w Perlu. Nowe książki wpisywane online są sortowane przez skrypt właśnie w tym języku.

Będzie też druga firma, KsiegarniaTechniczna.com. W tej księgarni sprzedaje się w systemie on­li­ne — w porozumieniu z innymi dużymi księgarniami — książki o tematyce technicznej i kompute­ro­wej (takie jak ta). Ostatnio podpisano umowę z Biblioteką Publiczną NaNiby, zgodnie z którą fir­ma będzie uzyskiwała książki od tej biblioteki na specjalnych warunkach. KsiegarniaTechniczna.com opłaci koszty dostawy i administracyjne, zaś biblioteka zamówi dodatkowe egzemplarze książek po specjalnej, obniżonej cenie; te dodatkowe książki sprzeda następnie Ksiegar­niaTech­niczna.com. KsiegarniaTechniczna.com --> musi [Author:RG] mieć dostęp do danych wprowadzanych w Bibliotece Publicznej NaNiby przez dostawców, tak aby wiedzieć o nowych tytułach i móc je reklamować u siebie. Jednakże nie wiadomo, w jaki sposób uzyskać dostęp do danych systemu bi­blioteki opartego na Perlu. Co więcej, pomiędzy obiema firmami nie istnieją chronione połączenia sieciowe, a więc konieczne jest wykorzystanie zwyczajnego protokołu HTTP.

Czytelnik będzie mógł spojrzeć na te aplikacje z punktu widzenia klientów KsiegarniaTech­niczna.com. Księgarnia oferuje produkty osobom aktywnym w Internecie, a więc chce ogłaszać się w witrynach w rodzaju Netscape Netcenter; chce także, aby klienci mogli w prosty sposób uzys­kać informacje z ich witryny o nowych ofertach. Jednakże, podobnie jak w przypadku Biblioteki Publicznej NaNiby, --> KsiegarniaTechniczna.com nie posiada informacji o tym, jak to zrobić[Author:RG] . Przedstawiciele gru­py Netscape Netcenter poinformowali programistów księgarni, że na potrzeby takiego reklamowa­nia się najlepiej nadaje się RSS (Rich Site Summary). Ale programiści księgarni nawet nie wiedzą, czym jest RSS!

Zaczniemy od Biblioteki Publicznej NaNiby — przyjrzymy się, jak zbudowany jest ich system na­pisany w Perlu. Następnie przejdziemy do firmy KsiegarniaTechniczna.com, a jeszcze później do klientów tej księgarni. Zobaczymy, jak pomiędzy tymi wszystkimi stronami stworzyć komuni­ka­cję opartą na języku XML.

Biblioteka Publiczna NaNiby

Tworzenie systemu typu firma-firma rozpoczniemy od zbadania, jaki stan rzeczy zastaliśmy w bi­bliotece. Zanim jednak przejdziemy do samego kodu aplikacji, musimy poznać wymagania biblio­te­ki (aby nie tworzyć systemu, którego nie będzie można potem obsłużyć).

Określenie wymagań

Często dobre rozwiązanie nie oznacza jeszcze — w przypadku określonej firmy — rozwiązania zgo­dnego z wymaganiami. Świetnym przykładem jest tutaj Biblioteka Publiczna NaNiby — pro­blemy tej biblioteki i firmy KsiegarniaTechniczna.com można byłoby rozwiązać za pomocą serwletów Javy działających po obu stronach. Jednakże nie zostałyby wówczas zaspokojone wymagania biblio­te­ki. A więc najpierw należy przyjrzeć się właśnie wymaganiom:

Nie są to może jakieś zaporowe wymagania, ale na pewno zmuszają do ponownego przeanali­zo­wa­nia problemu. Nie wolno nam korzystać z Javy. Oczywiście, ponieważ ta książka jest o XML-u, Czytelnik może się domyślać, że dane o nowych książkach będą zapisywane w formacie XML, na­stępnie przekazywane klientom protokołem HTTP i wykorzystywane w dowolny sposób. Tak, i jest to o wiele lepsze rozwiązanie niż komunikacja pomiędzy serwletami; XML może zostać uży­ty w dowolnej firmie lub u dowolnego klienta i nie trzeba „przywiązywać” biblioteki (i wszystkich jej książek) do jednej, określonej firmy. I w ten sposób zostało nakreślone zadanie związane z aktualizacją systemu biblioteki — zachować wpisane informacje w postaci kodu XML, a następ­nie stworzyć klientom możliwość dostępu do tych danych poprzez protokół HTTP.

Wprowadzanie książek

Po pierwsze trzeba poznać istniejący interfejs, za pomocą którego dostawcy wprowadzają nowe książki do systemu. W przykładzie 13.1 pokazano, jak zbudowany jest sam statyczny formularz.

Przykład 13.1. Statyczny interfejs Biblioteki Publicznej NaNiby w HTML-u

<html>

<head>

<title>Biblioteka Publiczna NaNiby: Wprowadzanie książek</title>

<style>

<!--

body { font-family: Arial }

h1 { color: #000080 }

-->

</style>

</head>

<body link="#FFFF00" vlink="#FFFF00" alink="#FFFF00">

<table border="0" width="100%" cellpadding="0" cellspacing="0">

<tr>

<td width="15%" bgcolor="#000080" valign="top" align="center">

<b><i>

<font color="#FFFFFF" size="4">Opcje</font>

</i></b>

<p><b>

<font color="#FFFFFF">

<a href="/javaxml/foobar">Menu Główne</a>

</font>

</p></b>

<p><b>

<font color="#FFFFFF">

<a href="/javaxml/foobar/catalog.html">Katalog</a>

</font>

</b></p>

<p><b>

<i><font color="#FFFF00">Wprowadzanie książek</font></i>

</b></p>

<p><b>

<font color="#FFFFFF">

<a href="/javaxml/foobar/logout.html">Wylogowanie</a>

</font>

</p></td>

<td width="*" valign="top" align="center">

<h1 align="center">Biblioteka Publiczna NaNiby</h1>

<h3 align="center"><i>- Dodawanie książek -</i></h3>

<!-- Poniżej ścieżka do katalogu i skryptu CGI, którym zajmiemy się w następnej kolejności -->

<form method="POST" action="/cgi/addBook.pl">

<table border="0" cellpadding="5" width="100%">

<tr>

<td width="100%" valign="top" align="center" colspan="2">

Tytuł&nbsp;

<input type="text" name="title" size="20">

<hr width="85%" />

</td>

</tr>

<tr>

<td width="50%" valign="top" align="right">Autor&nbsp;

<input type="text" name="author" size="20">

</td>

<td width="50%" valign="top" align="left">Temat&nbsp;

<select size="1" name="subject">

<option>Beletrystyka</option>

<option>Biografie</option>

<option>Nauka</option>

<option>Przemysł</option>

<option>Komputery</option>

</select></td>

</tr>

<tr>

<td width="50%" valign="top" align="right">Wydawca&nbsp;

<input type="text" name="publisher" size="20">

</td>

<td width="50%" valign="top" align="left">ISBN&nbsp;

<input type="text" name="isbn" size="20">

</td>

</tr>

<tr>

<td width="50%" valign="top" align="right">Cena&nbsp;

<input type="text" name="price" size="20">

</td>

<td width="50%" valign="top" align="left">Stron&nbsp;

<input type="text" name="numPages" size="20">

</td>

</tr>

<tr>

<td width="100%" valign="top" align="center" colspan="2">

Opis&nbsp;

<textarea rows="2" name="description" cols="20"></textarea>

</td>

</tr>

</table>

<p>

<input type="submit" value="Dodaj książkę" name="addBook">

<input type="reset" value="Wyczyść formularz" name="reset">

<input type="button" value="Anuluj" name="cancel">

</p>

</form>

</td>

</tr>

</table>

</body>

</html>

Powyższy plik, zachowany jako addBooks.html, umożliwia wprowadzenie nowych książek przy­syłanych do biblioteki.

0x01 graphic

W tym rozdziale zostanie wydrukowany pełny kod wszystkich opisywanych przy­kła­dów, tak aby Czytelnik mógł sam stworzyć przykładową aplikację i dokładnie za­zna­jo­mić się z procesem uruchamiania komunikacji XML pomiędzy firmami. Możliwe jest też obejrzenie działających przykładów pod adresem http://www.newInstance.com. Stam­tąd, jak również spod adresu http://www.oreilly.com/catalog/javaxml/, można także pobrać przykładowe pliki. W tym rozdziale założono, że Czytelnik użyje nazw plików zgodnych z opisywanymi; w przeciwnym razie trzeba odpowiednio dostosować kod (miejsca wymagające takich zmian odpowiednio zaznaczono).

Po załadowaniu powyższego przykładu do przeglądarki, Czytelnik otrzyma wynik przypominający ten na rysunku 13.1. Tutaj nie będą omawiane pozostałe pozycje menu, ale przecież dostawca mo­że chcieć przejrzeć katalog biblioteki, przejść do menu głównego czy wylogować się — wszystkie te opcje muszą więc znaleźć się w zasięgu ręki.

0x01 graphic

Rysunek 13.1. Interfejs HTML biblioteki

Formularz taki pozwala dostawcy wprowadzić szczegółowe informacje o każdej książce prze­sy­ła­nej do biblioteki. Wprowadzane są następujące dane: tytuł, autor, wydawca, liczba stron, cena, nu­mer ISBN, opis, a także kategoria tematyczna książki.

Po wprowadzeniu informacji formularz przesyłany jest do skryptu CGI:

<form method="POST" action="/cgi/addBook.pl">

Skrypt ten ma następnie zwrócić dane XML. Najprościej byłoby załadować bibliotekę Perla do obsługi przetwarzania XML, np. Xerces-Perl; należy jednak pamiętać o tym, że jedno z wymagań brzmi: żadnych nowych bibliotek i oprogramowania. Takie ograniczenie może wydawać się głupie, ale trzeba pamiętać, że w wielu firmach oprogramowanie produkcyjne traktuje się w spo­sób bardzo mało elastyczny. Biblioteka Publiczna NaNiby ma „zaistnieć” w Internecie, ale nie mo­żemy przeznaczyć na to żadnych dodatkowych zasobów i środków.

Na szczęście naszym zadaniem jest tylko uzyskać dane XML. Można to zrobić w dość łatwy spo­sób — „brutalnie” generując pliki z informacjami wprowadzonymi do formularza. Ponieważ wszy­stkie dotychczasowe informacje i tak mają być zachowywane, zamiast tworzyć nowe pliki, wystarczy dołączyć nowe informacje do plików już istniejących. Dla programistów Javy napisanie --> odpowiedniego pro­gra­mu w Perlu jest banalnym zadaniem — cały kod został zamieszczony w przykładzie 13.2.[Author:RG]

Przykład 13.2. Skrypt Perl CGI generujący wpisy XML z wprowadzonych książek

#!/usr/local/bin/perl

$baseDir = "/usr/local/projects/javaxml/foobar/books/";

$filename = "books.txt";

$bookFile = $baseDir . $filename;

# Pobieramy dane od użytkownika.

use CGI;

$query = new CGI;

$title = $query->param('title');

$author = $query->param('author');

$subject = $query->param('subject');

$publisher = $query->param('publisher');

$isbn = $query->param('isbn');

$price = $query->param('price');

$numPages = $query->param('numPages');

$description = $query->param('description');

# Zachowujemy dane w pliku XML.

if (open(FILE, ">>" . $bookFile)) {

print FILE "<book subject=\"" . $subject . "\">\n";

print FILE " <title><![CDATA[" . $title . "]]></title>\n";

print FILE " <author><![CDATA[" . $author . "]]></author>\n";

print FILE " <publisher><![CDATA[" . $publisher . "]]></publisher>\n";

print FILE " <numPages>" . $numPages . "</numPages>\n";

print FILE " <saleDetails>\n";

print FILE " <isbn>" . $isbn . "</isbn>\n";

print FILE " <price>" . $price . "</price>\n";

print FILE " </saleDetails>\n";

print FILE " <description><![CDATA[" . $description . "]]></description>\n";

print FILE "</book>\n\n";

# Wysyłamy potwierdzenie użytkownikowi.

print <<"EOF";

Content-type: text/html

<html>

<head>

<title>Biblioteka Publiczna NaNiby: Potwierdzenie</title>

</head>

<body>

<h1 align="center">Książka została dodana</h1>

<p align="center">

Dziękujemy. Książka została dodana do Biblioteki.

</p>

</body>

</html>

EOF

} else {

print <<"EOF";

Content-type: text/html

<html>

<head>

<title>Biblioteka Publiczna NaNiby: Błąd</title>

</head>

<body>

<h1 align="center">Błąd przy dodawaniu książki.</h1>

<p align="center">

Książka NIE została wprowadzona do biblioteki.

</p>

</body>

</html>

EOF

}

close (FILE);

Powyższy program, zachowany jako addBook.pl, uruchamiany jest po wysłaniu formularza. Skrypt definiuje nazwę pliku, do którego mają zostać zapisane dane, a następnie przypisuje parametry po­brane z formularza zmiennym lokalnym:

$title = $query->param('title');

$author = $query->param('author');

$subject = $query->param('subject');

$publisher = $query->param('publisher');

$isbn = $query->param('isbn');

$price = $query->param('price');

$numPages = $query->param('numPages');

$description = $query->param('description');

Kiedy już wartości te są dostępne, skrypt otwiera plik zdefiniowany wcześniej w trybie do do­pi­sy­wa­nia (symbol >> poprzedzający nazwę pliku) i na jego końcu zapisuje dane sformatowane jako XML:

print FILE "<book subject=\"" . $subject . "\">\n";

print FILE " <title><![CDATA[" . $title . "]]></title>\n";

print FILE " <author><![CDATA[" . $author . "]]></author>\n";

print FILE " <publisher><![CDATA[" . $publisher . "]]></publisher>\n";

print FILE " <numPages>" . $numPages . "</numPages>\n";

print FILE " <saleDetails>\n";

print FILE " <isbn>" . $isbn . "</isbn>\n";

print FILE " <price>" . $price . "</price>\n";

print FILE " </saleDetails>\n";

print FILE " <description><![CDATA[" . $description . "]]></description>\n";

print FILE "</book>\n\n";

Temat wykorzystywany jest jako atrybut elementu znajdującego się wyżej w hierarchii (book), na­tomiast pozostałe informacje zostają wprowadzone jako poszczególne elementy. Ponieważ pola zawierające tytuł, nazwisko autora, opis i nazwę wydawcy książki mogą zawierać cudzysłowy, apo­stro­fy, „ampersandy” i inne znaki wymagające wstawienia ich w sekwencje unikowe, dane te zam­knie­my w sekcji CDATA, co zwolni nas z konieczności znoszenia specjalnych znaczeń tych znaków.

Ponadto powinniśmy zauważyć, że nie tworzymy deklaracji XML ani elementu głównego (w je­dnym pliku będą zawarte informacje o wielu książkach). Ponieważ sprawdzenie, czy plik istnieje, zapisanie deklaracji i elementu głównego, jeśli nie istnieje, a następnie zapisanie elementu koń­czą­cego (który po każdej nowej porcji informacji będzie musiał zostać nadpisany) jest nieco kłopo­tli­we, pozostawimy ten plik w takiej postaci, w jakiej jest — jako fragment dokumentu XML. Na przykład tak wyglądałby plik po wprowadzeniu dwóch książek:

<book subject="Computers">

<title><![CDATA[Java Servlet Programming]]></title>

<author><![CDATA[Jason Hunter]]</author>

<publisher><![CDATA[O'Reilly & Associates]]></publisher>

<numPages>528</numPages>

<saleDetails>

<isbn>156592391X</isbn>

<price>36.95</price>

</saleDetails>

<description><![CDATA[Doskonałe wprowadzenie do serwletów Javy i

różnych mechanizmów komunikacyjnych.]]></description>

</book>

<book subject="Fiction">

<title><![CDATA[Second Foundation]]></title>

<author><![CDATA[Isaac Asimov]]</author>

<publisher><![CDATA[Bantam Books]]></publisher>

<numPages>279</numPages>

<saleDetails>

<isbn>0553293362</isbn>

<price>5.59</price>

</saleDetails>

<description><![CDATA[Po zagarnięciu Pierwszej Fundacji tylko Druga Fundacja mogła zapobiec całkowitej destrukcji.]]></description>

</book>

Może nie jest to kompletny dokument XML, ale sam ten fragment jest sformatowany poprawnie i mógłby zostać wstawiony do dokumentu XML zawierającego już nagłówek i element główny. I tak właśnie zrobimy, kiedy za chwilę zajmiemy się mechanizmem wyświetlającym listę książek.

Reszta skryptu zwraca odpowiednie dane HTML w zależności od tego, czy dodawanie książki się powiodło, czy nie. W pierwszym przypadku dostawca zobaczy proste potwierdzenie, takie jak na rysunku 13.2.

0x01 graphic

Rysunek 13.2. Komunikat potwierdzający dodanie książki

Teraz można już wykorzystać ten fragment dokumentu do udzielania odpowiednich informacji stronom żądającym.

Wyświetlanie listy dostępnych książek

Do wyświetlenia listy nowych książek znów posłuży Perl. Załóżmy, że jakaś inna porcja aplikacji biblioteki okresowo odczytuje dane XML i aktualizuje katalog. Ten składnik aplikacji byłby odpowiedzialny również za usuwanie wpisów w naszym pliku, tak aby książki już wprowadzone do katalogu nie były klasyfikowane jako „nowe”. Zadanie dla naszego drugiego skryptu w Perlu jest więc następujące: odczytać fragment kodu XML i dodać dane do dokumentu wyświetlanego na ekranie. Jak już było wspomniane, konieczne jest także dodanie deklaracji XML i elementu głów­nego, „otaczającego” dostarczoną zawartość. Nowy skrypt (przykład 13.3) odczytuje plik utwo­rzony przez addBook.pl i wyświetla odpowiednią zawartość po otrzymaniu żądania przez HTTP.

Przykład 13.3. Skrypt Perl CGI wyświetlający dokument XML z nowymi książkami

#!/usr/local/bin/perl

$baseDir = "/usr/local/projects/javaxml/foobar/books/";

$filename = "books.txt";

$bookFile = $baseDir . $filename;

# Najpierw otwieramy plik.

open(FILE, $bookFile) || die "Could not open $bookFile.\n";

# Przekazujemy przeglądarce informacje o rodzaju przesyłanych danych.

print "Content-type: text/plain\n\n";

# Wyświetlamy nagłówek i element główny XML.

print "<?xml version=\"1.0\"?>\n";

print "<books>\n";

# Wyświetlamy książki.

while (<FILE>) {

print "$_";

}

# Zamykamy element główny.

print "</books>\n";

close(FILE);

Powyższy skrypt, zachowany jako supplyBooks.pl, przyjmie żądanie, odczyta plik stworzony przez addBook.pl i wyświetli dane XML po żądaniu HTTP. Przykładowy wynik (z dodanymi książkami) można obejrzeć na rysunku 13.3.

0x01 graphic

Rysunek 13.3. Wynik działania skryptu supplyBooks.pl

Jak widać, prostą aplikację w Perlu łatwo można zamienić w składnik, który potrafi dostarczyć uży­teczne informacje klientom — takim jak księgarnia KsiegarniaTechniczna.com. Zrobiliśmy to bez instalacji nowego oprogramowania, bez zmiany architektury systemu lub aplikacji i bez pi­sa­nia choćby jednej linijki kodu w Javie!

KsiegarniaTechniczna.com

Biblioteka Publiczna NaNiby umożliwia już uzyskanie dostępu do danych o nowych książkach w formacie XML. Teraz KsiegarniaTechniczna.com jest już bliska osiągnięcia zamierzonego celu — dostarczyć aktualne informacje swoim klientom. W firmie tej już dawno wykorzystuje się Javę do budowania aplikacji, co bardzo uprości proces uzyskiwania dostępu i korzystania z danych XML oferowanych przez bibliotekę — Java świetnie obsługuje XML, o czym zresztą przekonuje cała ni­niejsza książka. Najpierw chcemy umożliwić wyświetlanie w firmie KsiegarniaTechniczna.com danych dotyczących nowych książek, a następnie udostępnić te informacje klientom tej firmy.

Filtrowanie danych XML

W firmie KsiegarniaTechniczna.com mają być wyświetlane wyłącznie dane o książkach tech­nicz­nych. Jak zapewne Czytelnik pamięta, Biblioteka Publiczna NaNiby pozwalała na wprowadzanie książek o zróżnicowanej tematyce; KsiegarniaTechniczna.com akceptuje wyłącznie książki o pro­ble­matyce informatycznej. Na szczęście, odpowiednia informacja jest zawarta w atrybucie sub­ject elementu book. Najpierw należy więc odfiltrować wszystkie książki, których tematem nie jest „Computers”. Kiedy już uzyskamy w ten sposób książki o tematyce informatycznej, musimy je sformatować do postaci strony HTML, którą pokażemy klientom odwiedzającym witrynę firmy KsiegarniaTechniczna.com.

Tutaj nie będziemy korzystali ze strony statycznej, ponieważ strona z nowymi pozycjami musi zostać wygenerowana przy każdej próbie jej pobrania. Oczywiście, tym razem do obsługi takich żądań wykorzystamy serwlet. Do konwersji danych XML z biblioteki na postać HTML świetnie nadawałby się Apache Cocoon, ale pracownicy firmy KsiegarniaTechniczna.com muszą całe zada­nie wy­konać jak najszybciej i na razie nie chcą wprowadzać tak dużych zmian w istniejącym sys­te­mie. Wolą wykorzystać parsery i procesory XML, a dopiero w drugiej fazie wdrażania zain­sta­lować Cocoon. A więc trzeba obsłużyć konwersję XML-HTML, a oprócz tego jeszcze filtrowanie i dodawanie elementów prezentacyjnych (np. logo firmy czy pasek menu).

Ale jeśli Czytelnik przywoła całą wiedzę o XML-u i XSL-u, to być może przypomni sobie, że nawet bez Cocoona można przekształcać dokumenty XML na format HTML-a — za pomocą arkuszy XSL. W trakcie transformacji można również odfiltrować książki o tematyce innej niż kom­puterowa. Pamiętając o tym wszystkim, możemy już stworzyć arkusz stylu, który zostanie zastosowany do dokumentu przesłanego z Biblioteki Publicznej NaNiby. Początkowy fragment ta­kie­go arkusza, obsługujący generację dokumentu HTML, został zamieszczony w przykładzie 13.4.

Przykład 13.4. Arkusz stylu dla danych otrzymywanych z Biblioteki Publicznej NaNiby

<?xml version="1.0"?>

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

version="1.0"

>

<xsl:template match="books">

<html>

<head>

<title>Księgarnia Techniczna - Twój sklep z literaturą komputerową</title>

</head>

<body background="http://newInstance.com/javaxml/techbooks/images/background.gif"

link="#FFFFFF" vlink="#FFFFFF" alink="#FFFFFF">

<h1 align="center">

<font face="Arial" color="#00659C">

&lt;KsiegarniaTechniczna.com&gt;

</font>

</h1>

<p align="center">

<i><b>Twoje źródło książek o tematyce komputerowej i technicznej.</b></i>

</p>

<p align="center">

<b><font size="4" color="#00659C">

<u>Nowe pozycje</u>

</font></b>

</p>

<table border="0" cellpadding="5" cellspacing="5">

<tr>

<td valign="top" align="center" nowrap="nowrap" width="115">

<p align="center">

<font color="#FFFFFF"><b>

<a href="http://newInstance.com/javaxml/techbooks/">Strona główna</a>

</b></font>

</p>

<p align="center">

<font color="#FFFFFF"><b>

<a href="http://newInstance.com/javaxml/techbooks/current.html">Obecne pozycje</a>

</b></font>

</p>

<p align="center">

<b><font color="#FFFFFF">

<i>Nowe pozycje</i>

</font></b>

</p>

<p align="center">

<font color="#FFFFFF"><b>

<a href="http://newInstance.com/javaxml/techbooks/contact.html">Kontakt</a>

</b></font>

</p>

</td>

<td valign="top" align="left">

<table border="0" cellpadding="5" cellspacing="5">

<tr>

<td width="450" align="left" valign="top">

<p>

<b>

Witamy w firmie <font face="courier">KsiegarniaTechniczna.com</font>,

oferującej książki o tematyce komputerowej i technicznej.

Po lewej stronie zamieszczono najnowsze tytuły. Aby nabyć którąś z tych wspaniałych książek, wystarczy kliknąć odsyłacz &quot;Kup książkę!&quot; co spowoduje jej przeniesienie do koszyka. Miłych zakupów!

</b>

</p>

<p>

<b>

Można także przejrzeć nasze wcześniejsze tytuły, zajrzeć do informacji

o sklepie, albo skontaktować się z nami. Wszystkie niezbędne odsyłacze

znajdują się po lewej stronie. Dziękujemy za zakupy u nas!

</b>

</p>

</td>

<td align="left">

<!-- Tutaj tworzymy zawartość dla każdej nowej *komputerowej* książki -->

</td>

</tr>

</table>

</td>

</tr>

</table>

</body>

</html>

</xsl:template>

</xsl:stylesheet>

Co prawda nie zostały jeszcze odfiltrowane przychodzące dane XML (nie zostały również prze­kształcone), ale interfejs HTML przedstawiany użytkownikowi jest już gotowy. Często o wiele proś­ciej jest najpierw zająć się tymi „prezentacyjnymi drobiazgami”, a dopiero potem samą logiką transformacji.

0x01 graphic

Przy tworzeniu arkuszy XSL, szczególnie na potrzeby aplikacji WWW, należy zawsze testować wynik poprzez procesor XSLT, wywołując go z wiersza poleceń. W ten spo­sób zostanie zagwarantowane, że na każdym etapie tworzenia dokument przetwarzany jest zgodnie z oczekiwaniami. O wiele trudniej usuwać błędy w dużym, gotowym już arkuszu stylu. Informacje o tym, jak korzystać z procesora Apache Xalan z wiersza poleceń, zostały zawarte w rozdziale 7. W tym konkretnym przypadku można pobrać plik supplyBooks.pl za pomocą przeglądarki, zachować wynik jego działania w pliku XML i wtedy przetestować arkusz stylu.

Podobnie jak w przypadku aplikacji w Bibliotece Publicznej NaNiby, po lewej stronie tworzone jest menu z odsyłaczami do innych części aplikacji; umieszczony jest również krótki opis firmy i jej oferty. Natomiast po prawej stronie pozostawiliśmy miejsce na nowe pozycje książkowe.

Przed odfiltrowaniem zawartości trzeba dodać szablon wyświetlający zawartość HTML z jednego elementu book. Wpis będzie wyglądał mniej więcej tak:

<book subject="Computers">

<title><![CDATA[Running Linux]]></title>

<author><![CDATA[Matt Welsh]]</author>

<publisher><![CDATA[O'Reilly & Associates]]></publisher>

<numPages>630</numPages>

<saleDetails>

<isbn>1565921518</isbn>

<price>29.95</price>

</saleDetails>

<description><![CDATA[Zgodnie z tradycją tytułów O'Reilly, książka Running

Linux oferuje przejrzyste instrukcje krok po kroku, zawsze dostarczające

Czytelnikowi akurat tyle informacji, ile potrzeba.]]></description>

</book>

Takie dane należy przekształcić w kod HTML za pomocą następującego szablonu XSL:

<?xml version="1.0"?>

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

version="1.0"

>

<xsl:template match="books">

<!-- Interfejs użytkownika -->

</xsl:template>

<xsl:template match="book">

<table border="0" cellspacing="1" bgcolor="#000000">

<tr>

<td>

<table border="0" cellpadding="3" cellspacing="0">

<tr>

<td width="100%" bgcolor="#00659C" nowrap="nowrap" align="center">

<b><font color="#FFFFFF">

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

</font></b>

</td>

</tr>

<tr>

<td width="100%" align="center" nowrap="nowrap" bgcolor="#FFFFFF">

<font color="#000000"><b>

Autor: <xsl:value-of select="author" /><br />

Wydawca: <xsl:value-of select="publisher" /><br />

Stron: <xsl:value-of select="numPages" /><br />

Cena: <xsl:value-of select="saleDetails/price" /><br />

<br />

</b></font>

<xsl:element name="a">

<xsl:attribute name="href">/servlets/BuyBookServlet?isbn=

=<xsl:value-of select="saleDetails/isbn" />

</xsl:attribute>

<font color="#00659C">Kup książkę!</font>

</xsl:element>

</td>

</tr>

</table>

</td>

</tr>

</table>

<br />

</xsl:template>

</xsl:stylesheet>

Szablon dopasowuje element book, a następnie tworzy tabelę z nagłówkiem w jednym wierszu i za­wartością w drugim. Cała tabela umieszczona jest wewnątrz innej tabeli, dzięki czemu w prze­glądarce ta pierwsza tabela sprawia wrażenie otoczonej czarną ramką. Tytuł wstawiany jest do nagłówka tabeli, a informacje o książce (autor, wydawca, liczba stron i cena) do zawartości tabeli. Jest tam również odsyłacz do serwleta Javy BuyBookServlet, za pomocą którego można w pro­sty sposób zakupić daną książkę. Jako argument wywołania serwleta podawany jest numer ISBN tej książki.

0x01 graphic

W arkuszu XSL trzeba sprawdzić, czy wiersz opisujący użycie BuyBookServlet oraz wiersz z elementem xsl:value-of tworzą tak naprawdę jedną linijkę. W prze­ci­w­nym razie do wynikowego adresu URL mogłyby „przedostać się” spacje i znaki no­we­go wiersza i serwlet otrzymałby niepoprawne dane. W przedstawionym arkuszu stylów, w wyniku łamania tekstu w druku, te informacje zostały rozbite na dwa wiersze.

Teraz trzeba jeszcze zagwarantować, że nowy szablon zostanie zastosowany i że zostaną do niego przekazane wyłącznie książki o tematyce „Computers”. Wartość atrybutu subject poznamy po­przez odwołanie się do niego za pomocą symbolu @; filtrowanie nastąpi poprzez atrybut select elementu xsl:apply-templates:

</td>

<td align="left">

<!-- Tutaj tworzymy zawartość dla każdej nowej *komputerowej* książki -->

<xsl:apply-templates select="book[@subject='Computers']" />

</td>

</tr>

</table>

Odwołujemy się do wartości atrybutu i porównujemy go z łańcuchem znaków (w apostrofach
— to dlatego, że całe wyrażenie XPath znajduje się w cudzysłowach). Ponieważ „obrabiamy” atry­but elementu zagnieżdżonego, odwołujemy się do niego przez nazwę i otaczamy wyrażenie związane z jego atrybutem nawiasami kwadratowymi. W ten sposób gwarantujemy, że szablon zostanie zastosowany tylko na książkach o tematyce „Computers”. Po stworzeniu arkusza stylów można go zachować jako computerBooks.xsl i odwoływać się do niego poprzez serwlet Javy, który zostanie przedstawiony poniżej.

XSLT poprzez serwlet

Arkusz stylu jest gotowy. Potrzebny jest jeszcze kod w Javie, który spowoduje zastosowanie tego arkusza na danych z biblioteki. Dostęp do danych odbędzie się za pośrednictwem klasy Javy URL, poprzez którą wyślemy żądanie HTTP do systemu biblioteki. Po tym wszystkim pozostanie już tylko wykonać faktyczną transformację z poziomu programu. W przykładzie 13.5 przedstawiono kod serwleta ładującego dane XML z biblioteki i ukazującego, w którym miejscu znajdzie się kod przekształcający (wykonujący transformację).

Przykład 13.5. Serwlet Javy przekształcający informacje o książkach na postać kodu HTML

package com.techbooks;

import java.io.FileInputStream;

import java.io.InputStream;

import java.io.IOException;

import java.io.PrintWriter;

import java.net.URL;

import javax.servlet.*;

import javax.servlet.http.*;

public class ListBooksServlet extends HttpServlet {

/** Host, z którego pobierzemy listę książek */

private static final String hostname = "newInstance.com";

/** Port powyższego hosta */

private static final int portNumber = 80;

/** Plik (ścieżka URI) zawierający listę książek */

private static final String file = "/cgi/supplyBooks.pl";

/** Arkusz stylu, według którego przekształcimy XML */

private static final String stylesheet = "/home/client/java/newinstance/www/javaxml/techbooks/XSL/computerBooks.xsl";

public void service(HttpServletRequest req, HttpServletResponse res)

throws ServletException, IOException {

res.setContentType("text/html");

// Łączymy się w celu pobrania listy książek

URL getBooksURL = new URL("http", hostname, portNumber, file);

InputStream in = getBooksURL.openStream();

// Przekształcamy dane XML za pomocą arkusza stylu

}

}

Ten prosty serwlet wysyła żądanie HTTP do biblioteki i otrzymuje odpowiedź w języku XML w postaci strumienia InputStream. Strumień zostanie następnie wykorzystany jako parametr procesora XSLT oraz jako baza do przekształcenia przez arkusz stylu zdefiniowany w serwlecie jako statyczny.

Obecnie nie istnieje interfejs API Javy, który określałby, jak programowo wykonać tran­sfor­ma­cję XSLT; jednakże każdy producent procesora powinien udostępniać klasy umożliwiające uruchomienie przekształcania z kodu Javy. Tutaj ponownie zostanie wykorzystany procesor Apa­che Xalan; informacji o sposobie wywoływania metod transformacji w innym parserze należy za­sięgnąć u producenta.

W przypadku procesora Apache Xalan do opisanego celu służy klasa XSLTProcessor z pakietu org.apache.xalan.xslt. Jako parametry przyjmuje ona klasę XSLTInputSource repre­zen­tującą plik XML do przetwarzania, klasę XSLTInputSource reprezentującą arkusz stylu oraz XSLTResultTarget reprezentującą wynik transformacji. Wszystkie te klasy pomocnicze znajdują się również w pakiecie org.apache.xalan.xslt. Klasy te tworzy się w wygodny sposób, przekazując InputStream (do XSLTInputSource) lub OutputStream (do XSLT­ResultTarget). Nasz dokument ma postać obiektu InputStream, arkusz stylu „zapa­ku­je­my” w FileInputStream, zaś interfejs serwleta pozwala nam w prosty sposób uzyskać dostęp do obiektu ServletOutputStream poprzez metodę getOutputStream(), wywołaną na obiekcie HttpServletResponse. Na koniec trzeba jeszcze omówić sposób uzyskania egzem­pla­rza XSLTProcessor. Ponieważ do przetwarzania mogą być wykorzystane różne mecha­niz­my wewnętrzne, egzemplarza tej klasy nie tworzy się bezpośrednio, ale poprzez klasę XSLTP­ro­ces­sor­Factory, również znajdującą się w pakiecie org.apache.xalan.xslt. Czytelnik wie już, jak korzystać z klas typu „factory”, a więc pozostało tylko zaimportować wymagane klasy i dodać do serwleta wywołania metod przetwarzających:

package com.techbooks;

import java.io.FileInputStream;

import java.io.InputStream;

import java.io.IOException;

import java.io.PrintWriter;

import java.net.URL;

import javax.servlet.*;

import javax.servlet.http.*;

// Import komponentów procesora Xalan XSLT

import org.apache.xalan.xslt.XSLTInputSource;

import org.apache.xalan.xslt.XSLTProcessor;

import org.apache.xalan.xslt.XSLTProcessorFactory;

import org.apache.xalan.xslt.XSLTResultTarget;

public class ListBooksServlet extends HttpServlet {

/** Host, z którego pobierzemy listę książek */

private static final String hostname = "newInstance.com";

/** Port powyższego hosta */

private static final int portNumber = 80;

/** Plik (ścieżka URI) zawierający listę książek */

private static final String file = "/cgi/supplyBooks.pl";

/** Arkusz stylu, według którego przekształcimy XML */

private static final String stylesheet =

"/home/client/java/newinstance/www/javaxml/techbooks/XSL/computerBooks.xsl";

public void service(HttpServletRequest req, HttpServletResponse res)

throws ServletException, IOException {

res.setContentType("text/html");

// Łączymy się w celu pobrania listy książek

URL getBooksURL = new URL("http", hostname, portNumber, file);

InputStream in = getBooksURL.openStream();

try {

XSLTProcessor processor = XSLTProcessorFactory.getProcessor();

// Przekształcamy XML za pomocą arkusza stylu

processor.process(new XSLTInputSource(in),

new XSLTInputSource(new FileInputStream(stylesheet)),

new XSLTResultTarget(res.getOutputStream()));

} catch (Exception e) {

PrintWriter out = res.getWriter();

out.println("Błąd: " + e.getMessage());

out.close();

}

}

}

Procesor wysyła dane wyjściowe do ServletOutputStream, a więc nie trzeba nawet do­da­wać żadnych dodatkowych danych wynikowych, oczywiście poza przypadkami błędów! Teraz można zachować serwlet jako ListBooksServlet.java i po kompilacji będzie on dostępny poprzez mechanizm serwletów i przeglądarkę.

0x01 graphic

Jeśli Czytelnik stara się wykonywać opisywane przykłady, to przed uruchomieniem serwleta będzie musiał przedsięwziąć pewne kroki. Po pierwsze, musi ustanowić po­łą­cze­nie z Internetem albo dokonać zmian w przykładach, tak aby mogły być urucha­mia­ne lokalnie; serwlet obsługujący KsiegarniaTechniczna.com musi mieć dostęp do danych biblioteki. Po drugie, warto wpisać kilka książek o różnej tematyce do systemu biblio­te­ki poprzez interfejs HTML. W ten sposób Czytelnik będzie mógł zobaczyć, co do­kładnie robią aplikacje i jak ze sobą współpracują. Kiedy już dane znajdują się w bibliotece, a do samej biblioteki mamy dostęp, można uruchomić ListBooksServlet.

Uruchomiony serwlet wysyła żądanie pobrania danych z Biblioteki Publicznej NaNiby. Dane te (lista nowych książek) są następnie przekształcane i wyświetlane na ekranie jako HTML. Odpo­wiedź z serwleta powinna wyglądać podobnie do tej pokazanej na rysunku 13.4 — widzimy spis nowych książek i aktualne informacje o nich (dzięki zmianom w bibliotece!); mamy także odsy­ła­cze pozwalające na natychmiastowy zakup wybranej książki. Klienci firmy KsiegarniaTechni­cz­na.com w prosty sposób przeglądają nowe tytuły online; pozostaje jeszcze „wypchnąć” te infor­macje do klientów tak, aby nie musieli nawet wpisywać adresu URL. Rozwiązanie tego problemu znajduje się w dalszej części rozdziału.

Pobieranie a „wypychanie” informacji

Do tej pory aplikacje tworzyliśmy z założeniem, że klienci sami będą pobierali dane i zawartość. Innymi słowy, klient musiał wpisać adres URL w przeglądarce (jak przy liście nowych książek w witrynie KsiegarniaTechniczna.com), lub też aplikacja taka jak opisywany wyżej serwlet musiała wysłać żądanie HTTP pobrania danych XML (jak w bibliotece). Oczywiście, nie ma tutaj żadnego problemu — ale takie rozwiązanie nie zawsze jest najlepsze z marketingowego punktu widzenia. Klienci pobierający dane muszą pamiętać, gdzie kupować książki, a często po jednej wi­zycie nie powracają w dane miejsce przez dni, tygodnie i miesiące. Sporadyczne zakupy na pewno nie przynoszą takich dochodów jak transakcje nawet mniejsze, ale za to częstsze.

Dlatego KsiegarniaTechniczna.com chce mieć możliwość wypychania (ang. push) danych do klientów. Klient dowiaduje się o nowych pozycjach wydawniczych lub promocjach bez ko­niecz­ności wykonywania jakichkolwiek działań. Wynikiem są częstsze zakupy — klient nie musi sam pamiętać o odwiedzaniu strony. Ale w Internecie nie jest łatwo uzyskać takie wypychanie danych — sieć globalna to nie klient uproszczony, nie da się tak po prostu wyświetlić okienka „pop-up” z nowymi informacjami. Popularność zyskują natomiast „strony startowe” w rodzaju My Netscape firmy Netscape czy My Yahoo firmy Yahoo. W rozmowach z Netscape przedstawiciele firmy KsiegarniaTechniczna.com usłyszeli o technologii RSS — może to jest właśnie sposób uzyskania zaplanowanego celu?

0x01 graphic

Rysunek 13.4. Strona HTML powstała w wyniku pobrania listy książek

Rich Site Summary

Rich Site Summary (RSS) to szczególna odmiana języka XML. Posiada własną definicję DTD i de­finiuje pojęcie kanału. Kanał to sposób reprezentacji danych na określony temat. Zawiera tytuł i opis kanału, grafikę (logo) oraz szereg pozycji (ang. items) kanału. Każda pozycja to coś, co wiąże się z kanałem, ewentualnie produkt lub usługa. Ponieważ dozwolone elementy pozycji są raczej ogólne (tytuł, opis, odsyłacz), pozycją kanału może być niemal wszystko. Kanał RSS nie ma dostarczać kompletnej zawartości serwisu, lecz raczej „streszczenie” informacji o firmie lub usłu­dze, wyświetlane w postaci „portalowej”, ewentualnie jako pasek informacji na innej stronie WWW. Tak naprawdę poszczególne „widżety” w serwisie Netscape Netcenter to właśnie kanały RSS. Netscape udostępnia możliwość tworzenia nowych kanałów RSS, rejestrowanych w Net­center. Netscape posiada również wbudowany system wyświetlania kanałów w formacie HTML, które wte­dy świetnie spisują się jako strony startowe Netcenter.

Czytelnik może w tej chwili niepokoić się, czy RSS nie jest czasem dla firmy Netscape czymś ta­kim jak parser Microsoft XML dla firmy Microsoft — czymś zupełnie nieużytecznym w połą­czeniu z innymi narzędziami czy produktami innych firm. Rozwiązanie to na początku faktycznie było opracowywane pod kątem Netcenter; jednak dzięki strukturze języka XML technologia RSS może zostać wykorzystana przez dowolną aplikację potrafiącą „czytać” pliki DTD. Coraz więcej portali i aplikacji korzysta z RSS — przykładem może być projekt Apache Jetspeed (http://java.apa­che.org/jetspeed), mający na celu stworzenie systemu Enterprise Information Portal w „stylu” open source. Jetspeed wykorzystuje dokładnie ten sam format RSS co Netscape, ale w zupełnie inny sposób. Jest to możliwe dzięki temu, że RSS ma bardzo spójną gramatykę.

Wielu użytkowników korzysta ze stron „startowych” lub „domowych” — miejsc najczęściej od­wiedzanych w sieci. KsiegarniaTechniczna.com postanowiła stworzyć kanał RSS przedstawiający listę najnowszych książek i umożliwiający zainteresowanym natychmiastowy zakup określonego tytułu. To właśnie nazwać można „wypychaniem” danych — produkty takie jak Netcenter auto­ma­tycznie aktualizują zawartość kanału RSS tak często, jak życzy sobie tego klient.

Tworzenie dokumentu RSS XML

Po pierwsze, konieczne jest utworzenie pliku RSS. A to jest prostsze, niż można byłoby przy­pusz­czać — poza wpisaniem odwołania do właściwej DTD i trzymania się określonych w tej definicji zasad, nie ma tutaj nic skomplikowanego. W przykładzie 13.6 pokazano propozycję pliku RSS dla naszej księgarni.

Przykład 13.6. Przykładowy dokument RSS opisujący kanał firmy KsiegarniaTechniczna.com

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN"

"http://my.netscape.com/publish/formats/rss-0.91.dtd">

<rss version="0.91">

<channel>

<title>KsiegarniaTechniczna.com Nowe Tytuły</title>

<link>http://www.newInstance.com/javaxml/techbooks/</link>

<description>

Twoje źródło książek i materiałów o tematyce komputerowej.

</description>

<language>en-us</language>

<image>

<title>KsiegarniaTechniczna.com</title>

<url>

http://newInstance.com/javaxml/techbooks/images/techbooksLogo.gif

</url>

<link>http://newInstance.com/javaxml/techbooks</link>

<width>140</width>

<height>23</height>

<description>

Źródło książek technicznych.

</description>

</image>

<item>

<title>Java Servlet Programming</title>

<link>

http://newInstance.com/javaxml/techbooks/buy.xsp?isbn=156592391X

</link>

<description>

Doskonałe wprowadzenie do serwletów Javy i

różnych mechanizmow komunikacyjnych.

</description>

</item>

</channel>

</rss>

Element główny musi nazywać się rss; musi zostać także zdefiniowany atrybut version. Oprócz tego, wartość tego atrybutu musi odpowiadać wersji DTD, do której się odwołujemy. W ele­mencie głównym musi wystąpić dokładnie jeden element channel. Wewnątrz niego znajdują się natomiast elementy opisujące dany kanał (title, link, description i language). Z ka­nałem można również skojarzyć opcjonalny plik graficzny (oraz informacje o tym pliku). Następ­nie może wystąpić do 15 elementów item, z których każdy opisuje jedną pozycję związaną z kanałem. Każdy item posiada elementy title, link i description (ich znaczenia nie trzeba chyba wyjaśniać).

0x01 graphic

Tak jak w poprzednich przykładach, również tutaj w elementach link i url nie po­win­ny znaleźć się białe znaki — całość powinna mieć postać jednego wiersza. W dru­ku nie było to możliwe, dlatego wiersz został rozdzielony.

Można także dodać opcjonalne pole tekstowe i przycisk do wysyłania informacji, czego w tym przykładzie nie pokazano. Szczegółowy opis elementów i atrybutów znajduje się na stronie http:// my.netscape.com/publish/help/mnn20/quickstart.html.

Tworzenie plików RSS programowo nie jest trudne; procedura podobna jest do tej, jaka została wykorzystana przy generowaniu pliku HTML na potrzeby księgarni. Połowa pliku RSS (infor­ma­cje o kanale oraz o grafice) to treść statyczna; tylko elementy item są budowane dynamicznie. Ale kiedy już programista uruchamia edytor vi i zasiada do tworzenia kolejnego arkusza XSL, na biurku znajduje kartkę z kolejnym wymogiem: komputer, na którym znajdzie się kanał RSS, to inny serwer niż ten używany w ostatnim przykładzie; dostępne są na nim tylko bardzo stare wersje bibliotek Apache Xalan. Ponieważ na maszynie tej działają również pewne aplikacje wysokiej dys­pozycyjności (np. system naliczania należności), KsiegarniaTechniczna.com nie chce aktuali­zo­wać tych bibliotek, chyba że przy precyzyjnej kontroli efektów zmian (taki proces zajmuje tydzień). Na samym serwerze są jednak dostępne nowsze wersje bibliotek Xerces (ponieważ w sys­temie naliczania konieczne jest przetwarzanie XML-a), a więc dostępne są również interfejsy API Javy do obsługi XML-a. Oczywiście, dałoby się tutaj wykorzystać interfejsy SAX i DOM, ale po raz kolejny najlepszą metodą wydaje się JDOM. To za jego pomocą (przykład 13.7) dokonamy konwersji pliku XML z Biblioteki Publicznej NaNiby na format kanału RSS.

Przykład 13.7. Serwlet Javy konwertujący listę nowych książek na dokument kanału RSS

package com.techbooks;

import java.io.FileInputStream;

import java.io.InputStream;

import java.io.IOException;

import java.io.PrintWriter;

import java.net.URL;

import java.util.Iterator;

import java.util.List;

import javax.servlet.*;

import javax.servlet.http.*;

// JDOM

import org.jdom.Document;

import org.jdom.Element;

import org.jdom.JDOMException;

import org.jdom.input.Builder;

import org.jdom.input.SAXBuilder;

public class GetRSSChannelServlet extends HttpServlet {

/** Z tego hosta pobieramy listę książek */

private static final String hostname = "newInstance.com";

/** Numer portu powyższego hosta */

private static final int portNumber = 80;

/** Ścieżka URI prowadząca do dokumentu */

private static final String file = "/cgi/supplyBooks.pl";

public void service(HttpServletRequest req, HttpServletResponse res)

throws ServletException, IOException {

res.setContentType("text/plain");

PrintWriter out = res.getWriter();

// Łączymy się i pobieramy listę książek

URL getBooksURL = new URL("http", hostname, portNumber, file);

InputStream in = getBooksURL.openStream();

try {

// Żądamy implementacji SAX i korzystamy z domyślnego parsera.

Builder builder = new SAXBuilder();

// Tworzymy dokument.

Document doc = builder.build(in);

// Wyświetlamy XML.

out.println(generateRSSContent(doc));

} catch (JDOMException e) {

out.println("Error: " + e.getMessage());

} finally {

out.close();

}

}

/**

* <p>

* Tutaj generujemy dokument RSS XML, korzystając z dostarczonego

* obiektu JDOM <code>Document</code>.

* </p.

*

* @param doc <code>Document</code> dane wejściowe.

* @return <code>String</code> - plik wyjściowy RSS.

* @throws <code>JDOMException</code> w razie wystąpienia błędów.

*/

private String generateRSSContent(Document doc) throws JDOMException {

StringBuffer rss = new StringBuffer();

rss.append("<?xml version=\"1.0\"?>\n")

.append("<!DOCTYPE rss PUBLIC ")

.append("\"-//Netscape Communications//DTD RSS 0.91//EN\" ")

.append("\"http://my.netscape.com/publish/formats/rss-0.91.dtd\">\n")

.append("<rss version=\"0.91\">\n")

.append(" <channel>\n")

.append(" <title>Książki techniczne</title>\n")

.append(" <link>http://newInstance.com/javaxml/techbooks</link>\n")

.append(" <description>\n")

.append(" Twoje źródło książek i materiałów o tematyce komputerowej.\n ")

.append(" </description>\n")

.append(" <language>en-us</language>\n")

.append(" <image>\n")

.append(" <title>KsiegarniaTechniczna.com</title>\n")

.append(" <url>")

.append("http://newInstance.com/javaxml/techbooks/images/techbooksLogo.gif")

.append("</url>\n")

.append(" <link>http://newInstance.com/javaxml/techbooks</link>\n")

.append(" <width>140</width>\n")

.append(" <height>23</height>\n")

.append(" <description>\n")

.append(" Źródło książek technicznych.\n")

.append(" </description>\n")

.append(" </image>\n");

// Dodajemy element dla każdego nowego tytułu, w którym jako temat

// określono Computers.

List books = doc.getRootElement().getChildren("book");

for (Iterator i = books.iterator(); i.hasNext(); ) {

Element book = (Element)i.next();

if (book.getAttribute("subject")

.getValue().equals("Computers")) {

// Wyświetlamy pozycję.

rss.append("<item>\n")

// Dodajemy tytuł

.append(" <title>")

.append(book.getChild("title").getContent())

.append("</title>\n")

// Dodajemy odsyłacz umożliwiający kupno książki

.append(" <link>")

.append("http://newInstance.com/javaxml/techbooks/buy.xsp?isbn=")

.append(book.getChild("saleDetails")

.getChild("isbn")

.getContent())

.append("</link>\n")

.append(" <description>")

// Dodajemy opis

.append(book.getChild("description").getContent())

.append("</description>\n")

.append("</item>\n");

}

}

rss.append(" </channel>\n")

.append("</rss>");

return rss.toString();

}

}

Na tym etapie nauki ani jeden fragment powyższego kodu nie powinien już Czytelnika dziwić. Importujemy wymagane klasy JDOM i wejścia-wyjścia oraz uzyskujemy dostęp do aplikacji bi­blio­­teki publicznej dokładnie tak, jak w serwlecie ListBooksServlet. Wynikowy Input­Stream wykorzystywany jest do stworzenia obiektu JDOM Document, za pomocą parsera domyślnego (w JDOM 1.0 jest to Apache Xerces) oraz implementacji JDOM zbudowanej na bazie SAX-a:

// Żądamy implementacji SAX i korzystamy z domyślnego parsera

Builder builder = new SAXBuilder();

// Tworzymy dokument.

Document doc = builder.build(in);

Teraz przekazujemy Document do metody generateRSSContent(), która drukuje całą zawartość statyczną kanału. Metoda ta pobiera elementy book z biblioteki, przetwarza je kolejno i ignoruje te, w których jako subject określono coś innego niż „Computers”:

// Dodajemy element dla każdego nowego tytułu, w którym jako temat

// określono Computers.

List books = doc.getRootElement().getChildren("book");

for (Iterator i = books.iterator(); i.hasNext(); ) {

Element book = (Element)i.next();

if (book.getAttribute("subject")

.getValue().equals("Computers")) {

// Wyświetlamy pozycję.

}

}

Każdy element, który przejdzie pomyślnie powyższy test, dodawany jest do kanału RSS. Prawda, że nic nadzwyczajnego? Na rysunku 13.5 przedstawiono przykładowe dane zwracane przez serw­let, który zachowano jako plik GetRSSChannelServlet.java.

KsiegarniaTechniczna.com udostępniła w ten sposób informacje wszystkim usługodawcom, któ­rzy obsługują technologię RSS. Żeby jeszcze klienci mogli korzystać z takiego kanału, Ksiegar­niaTechniczna.com zarejestruje kanał w Netscape Netcenter.

Sprawdzanie poprawności kanału RSS

Po stworzeniu kanału należy sprawdzić jego poprawność. W ten sposób nie tylko zagwarantujemy, że dokument jest zgodny z wymogami określonymi przez definicję RSS DTD; będzie on również zgodny z pewnymi ograniczeniami narzucanymi przez Netscape, a niemożliwymi do określenia w definicji DTD (w przyszłości być może rozwiązaniem tego problemu będzie XML Schema). Firma Netscape oferuje mechanizm sprawdzania poprawności kanałów online, znajdujący się pod adresem http://my.netscape.com/publish/help/validate.tmpl. Po wpisaniu na tej stronie adresu na­sze­go kanału RSS (który może mieć postać serwleta, skryptu CGI lub pliku statycznego) odpowie­dni program sprawdzi jego poprawność. Na rysunku 13.6 przedstawiono stronę wyświetlaną po udanym sprawdzeniu poprawności.

Teraz można już zarejestrować nasz kanał w usłudze Netcenter.

0x01 graphic

Rysunek 13.5. Kanał RSS wygenerowany przez serwlet GetRSSChannelServlet

0x01 graphic

Rysunek 13.6. Potwierdzenie sprawdzania poprawności kanału RSS

Rejestracja kanału

Po sprawdzeniu poprawności --> opublikujemy kanał [Author:RG] w serwisie Netcenter (lub u innego usługo­dawcy). W tym celu wchodzimy na stronę http://my.netscape.com/publish. Należy podać nazwę konta Netcenter, ponieważ e-mail potwierdzający zostanie wysłany na adres podany przy zakładaniu takiego konta. Po podaniu adresu poprawnego kanału RSS, Netcenter dodaje go do systemu kanałów i wysyła e-mail. W wiadomości takiej zawarte są instrukcje dotyczące dodania odsyłacza do kanału RSS ze strony WWW (np. z KsiegarniaTechniczna.com, o czym za chwilę) oraz dotyczące dodania kanału do strony startowej Netcenter.

Korzystanie z kanału

Sprawdzenie poprawności i rejestracja kanału nie przedstawiały trudności. Otrzymany e-mail upraszcza nawet dodanie takiego kanału do strony startowej. Od tej pory nasz kanał RSS w postaci HTML będzie można oglądać jako fragment strony startowej Netcenter. --> Po każdym otwarciu [Author:AJ] tej strony startowej użytkownik zobaczy „ramkę” KsiegarniaTechniczna.com, w której znajdzie nowe tytuły i będzie mógł je natychmiast zakupić. To na pewno zwiększy przychody ze sprzedaży online.

Aby rozreklamować kanał, do stworzonego arkusza stylu można jeszcze dodać odsyłacz, który spo­woduje automatyczne dodanie kanału do strony startowej oglądającego. Tak więc jedna ope­racja pobrania danych może zaowocować codziennymi „wypchnięciami” oferty firmy. Oto sposób dodania odsyłacza do arkusza:

<p align="center">

<font color="#FFFFFF"><b>

<a href="http://newInstance.com/javaxml/techbooks/contact.html">Kontakt</a>

</b></font>

</p>

<br>

<p align="center">

<A HREF="http://my.netscape.com/addchanneltmpl?service=net.2209">

<IMG SRC="http://my.netscape.com/publish/images/addchannel.gif"

WIDTH="88" HEIGHT="31" BORDER="0" /></A>

</p>

</td>

<td valign="top" align="left">

<table border="0" cellpadding="5" cellspacing="5">

<tr>

<td width="450" align="left" valign="top">

<p>

<b>

Witamy w firmie <font face="courier">KsiegarniaTechniczna.com</font>,

oferującej książki o tematyce komputerowej i technicznej.

Po lewej stronie zamieszczono najnowsze tytuły. Aby nabyć

którąś z tych wspaniałych książek, wystarczy kliknąć odsyłacz &quot;Kup książkę!&quot; co spowoduje przeniesienie wybranej pozycji

do koszyka. Miłych zakupów!

</b>

</p>

Wprowadzenie takiego fragmentu (który otrzymujemy e-mailem z Netscape po rejestracji kanału) spowoduje dodanie elementu graficznego, odsyłającego prosto do strony, --> która dodaje [Author:RG] kanał do strony startowej użytkownika. Sformatowana strona HTML po wprowadzeniu zmiany wygląda tak, jak --> na rysunku 13.9[Author:AJ] .

0x01 graphic

Rysunek 13.9. Strona HTML z odwołaniem do kanału RSS Netscape

Przykładowy problem komunikacji typu firma-firma został rozwiązany. Punktem wyjścia była or­ga­nizacja pracująca w jednym języku i bez możliwości wykorzystania XML-a (Biblioteka Pu­blicz­na NaNiby wraz z jej skryptami w Perlu); w wyniku działań przedstawionych w tym rozdziale uzyskała ona możliwość komunikacji z firmą korzystającą z zupełnie innej technologii (serw­lety Javy). Obie firmy nie były w żaden sposób ze sobą zsynchronizowane — żaden frag­ment kodu je­dnej nie łączył się w jakikolwiek sposób z kodem drugiej. Ponieważ jako nośnik in­formacji został użyty język XML, w obu firmach mogą się zmienić aplikacje, technologie, a nawet architektury, a i tak nie wpłynie to na stworzony w rozdziale mechanizm. Następnie Czytelnik dowiedział się, jak w wyniku takiej komunikacji można stworzyć zawartość HTML prezentowaną użytkownikom (na zupełnie różne sposoby zależnie od aplikacji) oraz jak „wypchnąć” tę za­wartość do klientów w jeszcze jednym formacie HTML poprzez kanały RSS. Wszystko to możliwe było dzięki obe­cnemu „za kulisami” XML-owi.

Praktyka

Niewiele więcej można powiedzieć o aplikacjach typu firma-firma. Omawiany przykład został zaczerpnięty z życia — podobne wymagania i cele określone zostały w pewnych dużych firmach.

W kolejnych podrozdziałach Czytelnik dowie się, czym różni się to rozwiązanie skoncentrowane wokół XML-a od technologii Electronic Data Interchange (EDI); omówione zostaną również inne zastosowania kanałów RSS.

XML kontra EDI

Zapotrzebowanie na komunikację pomiędzy firmami jest coraz większe i to przyczyniło się do spopularyzowania technologii Electronic Data Interchange (EDI). Drogie produkty i rozwiązania typu „heavy-duty”, jeśli tylko na ich pudełkach widnieje napis „EDI”, od razu sprzedają się jak świeże bułeczki. Ale te kosztowne rozwiązania, co oczywiste, nie są popularne w mniej zamoż­nych firmach. Od kiedy pojawił się XML, nawet firmy o wysokim budżecie rezygnują z EDI na rzecz XML-a. Wynika to nie tylko z faktu, ze XML jest rozwiązaniem wysoce standardowym, ale również z prostoty tego języka. Przecież w jednym rozdziale został opisany sposób komunikacji zupełnie oddzielnych systemów! Dziesięć lat temu wymagałoby to całego zespołu programistów, a powstałe rozwiązanie i tak działałoby tylko w tych konkretnych warunkach.

Można dowieść, że XML całkowicie znosi potrzebę korzystania z EDI. Stare systemy, aplikacje włas­ne, masywne bazy danych i produkty o podwyższonym stopniu bezpieczeństwa — one wszy­stkie mogą wymieniać dane za pomocą formatu XML. Interfejsy API w rodzaju SAX-a, DOM-a, a obecnie również JDOM-a powodują, że tworzenie pełnych rozwiązań XML jest praktyczne, a budowanie warstw XML „na” istniejących danych w różnych formatach to kwestia tygodni i miesięcy, a nie lat. EDI powoli zacznie znikać z rynku, jego miejsce zastąpią oferty e-biznesowe oparte na XML-u i Javie.

Kanały RSS — czy to coś trwałego?

Często pada pytanie, czy formaty XML w rodzaju RSS to rozwiązanie „trwałe”. Format ten jest wyko­rzystywany w pewien konkretny sposób (np. na stronie Netscape Netcenter) — czy więc RSS jest rozwiązaniem firmy Netscape? Tak, RSS kojarzy się z konkretną firmą, ale ponieważ oparty jest na XML-u, może być wykorzystywany tak jak dowolny inny dokument XML. Styl dokumentu jest całkowicie umowny, a napisanie arkusza przekształcającego RSS na WML dla telefonów bez­przewodowych to rzecz banalna. Zresztą zostało już wspomniane, że projekt Apache Jetspeed korzysta z RSS, a sieć O'Reilly Network (http://www.oreillynet.com) „zatrudniła” kanały RSS w serwisach takich jak XML.com (http://www.xml.com).

Jeszcze ważniejsze jest to, że rozwiązania wykorzystujące XML z natury nie mają nic wspólnego z rozwiązaniami „własnymi”. Dowolny dokument XML może być przekształcony tak, jak sobie tego zażyczy autor lub programista. Nie ulega wątpliwości, że w ciągu najbliższych lat dokonana zostanie migracja większości warstw prezentacyjnych do XML-a, bądź też konkretnej odmiany XML-a (np. RSS). Firmy chcą budować strony o dynamicznej zawartości, ale nie mają zamiaru zatrudniać przy tym całej armii twórców witryn.

Co dalej?

Czytelnik umie już posługiwać się XML-em „wewnątrz” kodu w Javie. Potrafi tworzyć, prze­twa­rzać, budować style, przekształcać, zawężać i sprawdzać poprawność XML-a. Wie również, jak korzystać ze struktur publikacji, ze zdalnych wywołań procedur, jak przechowywać informacje o konfiguracji w dokumencie XML oraz jak budować XML „w locie” z kodu Javy. To powinno wystarczyć do zbudowania niemal dowolnej aplikacji w języku XML. W następnym rozdziale, już ostatnim w tej książce, zostaną przedstawione schematy XML Schema. Czytelnik wie już, jak za ich pomocą zawężać dokumenty XML; teraz dowie się, dlaczego XML Schema jest tak inno­wacyjny, oraz jak wpływa na sposób korzystania z języka XML. Rozdział ten nie dotyczy samego ję­zyka Java, ale omawiana w nim problematyka jest niezwykle istotna z punktu widzenia sposobu, w jaki wykorzystywany jest język XML w aplikacjach.

Więcej informacji o klasie URL i operacjach wejścia-wyjścia Javy można znaleźć w książce Java I/O Eliotte Rusty Harolda (O'Reilly & Associates).

Tak, to nieco wydumany przykład, pewnie mało prawdopodobny. Ale pozwala Czytelnikowi poznać jeszcze jedną al­ter­na­tywę co do sposobu programowego tworzenia XML-a. Jednak tak naprawdę wszystkie przykłady w tej książce (łącz­nie z tymi głupiutkimi) oparte są na prawdziwych doświadczeniach związanych z prowadzeniem konsultingu w rze­czywistych firmach!

350 Rozdział 13. Firma-firma

Co dalej? 351

H:\Książki\!Kudlaty\Java i XML\92 po poprawkach korektora\13-08.doc — strona 350

H:\Książki\!Kudlaty\Java i XML\92 po poprawkach korektora\13-08.doc — strona 351

H:\Książki\!Kudlaty\Java i XML\92 po poprawkach korektora\13-08.doc — strona 323

Chyba wyszły za duże odstępy i 2 wiersze "spadły" na następną stronę.

Spadło :-(

W.D.: Opuszczenie na stronie 410 oryginału; ilustracja 13.8: Netcenter z dostosowanym kanałem RSS.

W.D.: Opuszczenie na stronie 412 oryginału; ilustracja 13.9: Strona HTML z kanałem RSS Nestcape.



Wyszukiwarka

Podobne podstrony:
3084
COM SEC(2008)3084 EN
3084
010id 3084
COM SEC(2008)3084 EN
3084 C006
3084 fm
3084 C005

więcej podobnych podstron