Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00437 010349 11037641 na godz. na dobę w sumie
Java i XML. Wydanie III - książka
Java i XML. Wydanie III - książka
Autor: , Liczba stron: 440
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-246-1011-2 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> webmasterstwo >> xml i xslt - programowanie
Porównaj ceny (książka, ebook, audiobook).

Praktyczne zastosowania możliwości języka XML w aplikacji Java

Jesteś programistą Javy i chcesz wykorzystać w swoich aplikacjach technologię XML? Zainteresowała Cię technologia AJAX? Zamierzasz tworzyć własne kanały RSS i podcasty? Java i XML są niemal stworzone do wzajemnej współpracy. W XML tworzy się pliki konfiguracyjne dla aplikacji Javy, zbiory danych i wiele innych elementów. AJAX, bazujący w dużej mierze na języku XML, pozwala na stworzenie eleganckich i wygodnych interfejsów użytkownika dla aplikacji przeglądarkowych. Wiedza o tym, jak efektywnie połączyć XML z Javą, pomoże Ci w budowaniu nowoczesnych programów.

'Java i XML. Wydanie III' to podręcznik, po przeczytaniu którego staniesz się ekspertem w zakresie wykorzystywania możliwości języka XML. Czytając go, poznasz podstawy języka XML, sposoby przetwarzania plików XML w aplikacjach Javy za pomocą API SAX, DOM, StAX, JDOM i dom4j, a także najnowszych wersji JAXP i JAXB. Dowiesz się, jak tworzyć kanały RSS, witryny Web 2.0 i własne podcasty. Przeczytasz także o technologii AJAX i nauczysz się budować z jej wykorzystaniem interfejsy użytkownika dla swoich aplikacji.

Twórz nowoczesne aplikacje, wykorzystując XML

Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

Java i XML. Wydanie III Autorzy: Brett D. McLaughlin, Justin Edelson T³umaczenie: £ukasz Piwko ISBN: 978-83-246-1011-2 Tytu³ orygina³u: Java and XML (3rd edition) Format: B5, stron: 440 Praktyczne zastosowania mo¿liwoœci jêzyka XML w aplikacji Java (cid:129) Z jakich elementów sk³ada siê XML? (cid:129) W jaki sposób przetwarzaæ pliki XML w aplikacjach Javy? (cid:129) Jak tworzyæ w³asne kana³y RSS? Jesteœ programist¹ Javy i chcesz wykorzystaæ w swoich aplikacjach technologiê XML? Zainteresowa³a Ciê technologia AJAX? Zamierzasz tworzyæ w³asne kana³y RSS i podcasty? Java i XML s¹ niemal stworzone do wzajemnej wspó³pracy. W XML tworzy siê pliki konfiguracyjne dla aplikacji Javy, zbiory danych i wiele innych elementów. AJAX, bazuj¹cy w du¿ej mierze na jêzyku XML, pozwala na stworzenie eleganckich i wygodnych interfejsów u¿ytkownika dla aplikacji przegl¹darkowych. Wiedza o tym, jak efektywnie po³¹czyæ XML z Jav¹, pomo¿e Ci w budowaniu nowoczesnych programów. „Java i XML. Wydanie III” to podrêcznik, po przeczytaniu którego staniesz siê ekspertem w zakresie wykorzystywania mo¿liwoœci jêzyka XML. Czytaj¹c go, poznasz podstawy jêzyka XML, sposoby przetwarzania plików XML w aplikacjach Javy za pomoc¹ API SAX, DOM, StAX, JDOM i dom4j, a tak¿e najnowszych wersji JAXP i JAXB. Dowiesz siê, jak tworzyæ kana³y RSS, witryny Web 2.0 i w³asne podcasty. Przeczytasz tak¿e o technologii AJAX i nauczysz siê budowaæ z jej wykorzystaniem interfejsy u¿ytkownika dla swoich aplikacji. (cid:129) Elementy jêzyka XML (cid:129) Walidacja dokumentów XML (cid:129) Przetwarzanie plików XML za pomoc¹ SAX (cid:129) Wykorzystanie innych technologii do obróbki plików XML (cid:129) Wi¹zanie danych w JAXB (cid:129) Tworzenie kana³ów RSS (cid:129) Transformacja XML na HTML za pomoc¹ JSP (cid:129) Korzystanie z mechanizmów AJAX (cid:129) Wykorzystanie danych XML w jêzyku ActionScript 3.0 Twórz nowoczesne aplikacje, wykorzystuj¹c XML Wydawnictwo Helion ul. Koœciuszki 1c 44-100 Gliwice tel. 032 230 98 63 e-mail: helion@helion.pl Wstęp ...............................................................................................................................7 1. Wprowadzenie .............................................................................................................. 13 13 21 21 29 XML 1.0 XML 1.1 Transformacje XML Co więcej 2. Zawężanie ..................................................................................................................... 31 32 37 44 DTD XML Schema RELAX NG 3. SAX ................................................................................................................................. 51 51 55 59 72 Instalacja SAX Programowanie przy użyciu SAX Obsługa treści Obsługa błędów 4. SAX dla zaawansowanych ........................................................................................... 77 77 80 84 85 86 90 Właściwości i cechy Tłumaczenie encji Notyfikacje i nieprzetwarzane encje Klasa DefaultHandler Interfejsy rozszerzeń Filtry i generatory 3 5. DOM ...............................................................................................................................97 97 102 114 124 Co to jest DOM? Serializacja Modyfikacja i tworzenie XML Przestrzenie nazw 6. Moduły DOM ............................................................................................................... 127 127 130 144 Sprawdzanie obsługi modułów Moduły DOM Level 2 Moduły DOM Level 3 7. JAXP ............................................................................................................................. 155 155 156 165 175 186 Więcej niż API Analiza składniowa Przetwarzanie XSL XPath Walidacja XML 8. Przetwarzanie strumieniowe przy użyciu StAX ....................................................... 193 193 195 196 220 228 231 231 Podstawy StAX Fabryki StAX Analiza składniowa przy użyciu StAX Zapis dokumentów za pomocą StAX Właściwości fabryki Najczęstsze problemy ze StAX XmlPull 9. JDOM ............................................................................................................................235 235 239 250 259 267 271 Podstawy Klasa PropsToXML Klasa XMLProperties Więcej klas JDOM JDOM i Fabryki Częste problemy z JDOM 10. dom4j ........................................................................................................................... 277 277 280 286 292 295 Przegląd Odczyt i zapis w dom4j Przechodzenie przez dokument Transformacje Fabryki do specjalnych zastosowań 4 | Spis treści 11. Wiązanie danych w JAXB ...........................................................................................297 297 301 309 330 Podstawy wiązania danych Wprowadzenie do JAXB Używanie JAXB Inne środowiska wiązań 12. Agregacja treści za pomocą RSS ................................................................................333 334 340 348 352 Co to jest RSS? Tworzenie źródeł RSS Odczyt ze źródła RSS Moduły ROME 13. Prezentacyjny XML .....................................................................................................365 365 371 373 380 392 XML a wzorzec Model-View-Controller Transformacja na HTML za pomocą JSP Używanie XSLT Ajax Flash 14. Przyszłość ................................................................................................................... 405 405 405 406 406 406 Urządzenia przetwarzające XML Bazy danych XML XQuery Fast Infoset I wiele więcej… A Cechy i właściwości SAX ........................................................................................... 409 Skorowidz .................................................................................................................... 417 Spis treści | 5 ROZDZIAŁ 13. Do tej pory XML traktowaliśmy jako technologię niskiego poziomu — użytkownik końcowy nie wie, czy użyte zostały zwykłe pliki właściwości, czy też pliki właściwości XML omawiane w rozdziale 9. Ponadto aplikacje współdzielące omawiane do tej pory dokumenty są z reguły serwerami przetwarzającymi dane. W ostatnim rozdziale przedstawiłem przykłady, w któ- rych XML był używany w kontekście klient-serwer: źródła RSS i Atom są dostarczane bezpo- średnio do klientów — w tych przypadkach do agregatorów RSS i Atom (oczywiście, istnieją też serwerowe agregatory RSS, takie jak NewsGator — http://www.newsgator.com — czy My Yahoo! — http://my.yahoo.com). Ale jest to dość ograniczony przypadek, zawężony do specy- ficznej leksyki RSS i Atom. W niniejszym rozdziale przyjrzymy się bardziej ogólnym przy- padkom użycia XML jako części technologii prezentacyjnej w aplikacji sieciowej. Opracowując ten rozdział przyjąłem kilka założeń. Po pierwsze zakładam, że osoba go czytająca przeczytała też poprzednie rozdziały. Podobnie jak w przypadku bi- blioteki ROME z poprzedniego rozdziału, będziemy korzystać z niektórych bibliotek, które omówione zostały wcześniej, a w szczególności z DOM. Po drugie zakładam, że Czytelnik dysponuje pewną wiedzą na temat różnych technologii sieciowych, ta- kich jak HTML, JavaScript, serwlety Java i JavaServer Pages (JSP). Ponadto zakła- dam, że potrafi zainstalować kontener serwletów Javy (np. Apache Tomcat) lub zna kogoś, kto chętnie służy pomocą. W rozdziale tym nie ma informacji na temat pisa- nia aplikacji sieciowych w Javie. Osobom, które nie mają przynajmniej podstawowej wiedzy na temat wymienionych technologii, stanowczo polecam odłożenie tej książki, uzupełnienie wiadomości i wrócenie do niej z odpowiednim przygotowaniem. Do najlepszych książek na temat technologii sieciowych Javy należą Java Servlet. Progra- mowanie. Wydanie II autorstwa Jasona Huntera (Helion, Gliwice 2002) i JavaServer Pages. Leksykon Kieszonkowy napisana przez Hansa Bergstena (Helion, Gliwice 2002). XML a wzorzec Model-View-Controller Kiedy odnoszę się do XML jako technologii prezentacyjnej, to przede wszystkim mam na myśli widok w aplikacji wykorzystujący architekturę Model-View-Controller (MVC). MVC jest architekturą oprogramowania, która początkowo została stworzona jako wzorzec dla tradycyjnych aplikacji klienckich (jak te tworzone za pomocą Swinga), ale została powszech- nie adaptowana do aplikacji sieciowych. Krótko mówiąc, zastosowanie MVC pozwala na podział aplikacji na trzy główne obszary: 365 Model Surowe dane i reguły biznesowe aplikacji. View Dostępna dla użytkownika interpretacja widoku modelu. Controller Procedury odbierające żądania od użytkowników, interpretujące je, oddziałujące z modelem i dostarczające widoku z wszystkimi niezbędnymi obiektami modelu. Jako konkretny przykład może posłużyć aplikacja sieciowa MVC napisana przy użyciu serwletów Javy i JSP, która może przetworzyć żądanie użytkownika w czterech etapach: 1. serwlet (kontroler) odbiera żądanie i przetwarza je, 2. 3. 4. serwlet wywołuje jakieś metody na obiekcie dostępu do danych, serwlet przekazuje obiekty danych modelu do strony JSP w celu ich wizualizacji, strona JSP wysyła na wyjście stronę HTML zawierającą dane z obiektów modelu. Dostępnych jest wiele środowisk MVC dla Javy, które dostarczają znaczną część podstawo- wego kodu potrzebnego w każdej aplikacji sieciowej. Do najpopularniejszych należą Apache Struts (http://struts.apache.org), Spring MVC (http://www.springframework.org), JavaServer Faces (http://java.sun.com/javaee/javaserverfaces) oraz Tapestry (http://tapestry.apache.org). XML w aplikacjach sieciowych MVC XML w aplikacjach sieciowych MVC można użyć w kilku miejscach. Większość tego typu środowisk wykorzystuje XML jako wewnętrzny mechanizm konfiguracyjny. Dla nas bardziej interesujące jest, kiedy XML używa się do przekazywania danych pomiędzy widokiem a kontrolerem. Zamiast do widoku przekazywać jeden lub więcej obiektów modelu, kontro- ler tworzy reprezentację XML obiektów modelu i tak utworzony dokument przekazuje do widoku. W niektórych przypadkach aplikacja jest odpowiedzialna za dostarczenie XML — widok tylko dokonuje serializacji dokumentu jako odpowiedź HTTP. W innych widok sta- nowi pewnego rodzaju transformację po stronie serwera XML dostarczonego przez kontroler na XML o innej składni lub HTML. Ponadto transfer danych modelu pomiędzy kontrolerem a widokiem przy użyciu XML pozwala na przeniesienie wszystkich niezbędnych operacji transformujących z serwera do aplikacji użytkownika (z reguły przeglądarki internetowej). Na początku utworzymy prosty serwlet tworzący dokument XML. Listing 13.1 przedstawia serwlet tworzący dokument XML zawierający listę książek. Nasz model jest listą (List) obiek- tów Map. Po utworzeniu obiektu DOM Document serwlet wysyła na wyjście dokument przy użyciu techniki transformacji identycznościowej, którą omówiłem w rozdziale 7. Listing 13.1. Serwlet generujący dokument XML package javaxml3.ch13; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; 366 | Rozdział 13. Prezentacyjny XML import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Result; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Text; public class BookListXMLServlet extends HttpServlet { private DocumentBuilderFactory documentBuilderFactory; private TransformerFactory transformerFactory; public void init() { documentBuilderFactory = DocumentBuilderFactory.newInstance(); transformerFactory = TransformerFactory.newInstance(); } private Element newElementFromMap(Map map, String key, Document doc) { String text = (String) map.get(key); Text textNode = doc.createTextNode(text); Element element = doc.createElement(key); element.appendChild(textNode); return element; } protected void renderDocument(Document doc, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // Informacja dla przeglądarki, że wysyłany jest XML. response.setContentType( text/xml ); // Transformacja identycznościowa. try { Transformer identity = transformerFactory.newTransformer(); // Nasz obiekt Result to StreamResult opakowujący // ServletOutputStream. Result result = new StreamResult(response.getOutputStream()); identity.transform(new DOMSource(doc), result); } catch (TransformerException e) { throw new ServletException( Nie można wykonać transformacji identycznościowej , e); } } protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List bookList = BookListFactory.INSTANCE; DocumentBuilder docBuilder = null; try { docBuilder = documentBuilderFactory.newDocumentBuilder(); XML a wzorzec Model-View-Controller | 367 } catch (ParserConfigurationException e) { throw new ServletException( Nie można utworzyć DocumentBuilderFactory , e); } // Tworzenie dokumentu DOM. Document doc = docBuilder.newDocument(); Element books = doc.createElement( books ); doc.appendChild(books); for (Iterator it = bookList.iterator(); it.hasNext();) { Map bookMap = (Map) it.next(); Element book = doc.createElement( book ); books.appendChild(book); book.appendChild(newElementFromMap(bookMap, BookListConstants.TITLE, doc)); book.appendChild(newElementFromMap(bookMap, BookListConstants.AUTHOR, doc)); book.appendChild(newElementFromMap(bookMap, BookListConstants.PUBDATE, doc)); } renderDocument(doc, request, response); } } class BookListConstants { public static final String AUTHOR = author ; public static final String PUBDATE = pubdate ; public static final String TITLE = title ; } class BookListFactory { public static final List INSTANCE; static { List templist = new ArrayList(); Map m = new HashMap(); m.put(BookListConstants.TITLE, Ajax Hacks ); m.put(BookListConstants.AUTHOR, Bruce W. Perry ); m.put(BookListConstants.PUBDATE, merzec 2006 ); templist.add(m); m = new HashMap(); m.put(BookListConstants.TITLE, LDAP System Administration ); m.put(BookListConstants.AUTHOR, Gerald Carter ); m.put(BookListConstants.PUBDATE, marzec 2003 ); templist.add(m); m = new HashMap(); m.put(BookListConstants.TITLE, Java Servlet Programming ); m.put(BookListConstants.AUTHOR, Jason Hunter ); m.put(BookListConstants.PUBDATE, kwiecień 2001 ); templist.add(m); INSTANCE = Collections.unmodifiableList(templist); } private BookListFactory() { } } 368 | Rozdział 13. Prezentacyjny XML Listing 13.2 zawiera plik konfiguracyjny serwletu web.xml, który mapuje ten serwlet na ścieżkę /booklist-xml. Listing 13.2. Przykładowy plik web.xml ?xml version= 1.0 encoding= UTF-8 ? web-app id= ch13-servlet version= 2.4 xmlns= http://java.sun.com/xml/ns/j2ee xmlns:xsi= http://www.w3.org/2001/XMLSchema-instance display-name ch13-servlet /display-name servlet servlet-name BookListXMLServlet /servlet-name servlet-class javaxml3.ch13.BookListXMLServlet /servlet-class /servlet servlet-mapping servlet-name BookListXMLServlet /servlet-name url-pattern /booklist-xml /url-pattern /servlet-mapping /web-app Po utworzeniu aplikacji sieciowej zawierającej tę klasę serwletu i plik konfiguracyjny możemy obejrzeć wyniki w przeglądarce, jak na rysunku 13.1. Rysunek 13.1. Dane wyjściowe XML serwletu Do utworzenia tego dokumentu nie trzeba było używać serwletu. To samo można uzyskać za pomocą JSP lub innego języka szablonu (np. Velocity). Zamiast serwletu z listingu 13.1 mo- glibyśmy uzyskać znacznie prostszy serwlet, jak ten na listingu 13.3, a następnie XML utworzyć w JSP z listingu 13.4. Listing 13.3. Znacznie prostszy serwlet listy książek package javaxml3.ch13; import java.io.IOException; import java.util.List; XML a wzorzec Model-View-Controller | 369 import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class BookListXMLJSPServlet extends HttpServlet { protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List bookList = BookListFactory.INSTANCE; request.setAttribute( bookList , bookList); RequestDispatcher dispatcher = getServletContext() .getRequestDispatcher( /booklist1.jsp ); dispatcher.include(request, response); } } Listing 13.4. Wizualizacja XML za pomocą znaczników JSP ?xml version= 1.0 encoding= UTF-8 ? @ page contentType= text/xml @ taglib prefix= c uri= http://java.sun.com/jsp/jstl/core books c:forEach items= ${bookList} var= book book title ${book.title} /title author ${book.author} /author pubdate ${book.pubdate} /pubdate /book /c:forEach /books Należy zwrócić uwagę, że deklaracja XML znajduje się na samej górze strony JSP, nad dyrektywami. Jest tak dlatego, że deklaracja XML powinna być na samym początku dokumentu XML. Jednak przy generowaniu XML za pomocą JSP, jak na listingu 13.4, można utworzyć źle sformułowany dokument. Jako że serwlet z listingu 13.2 tworzy dokument w zgodzie z DOM, nie ma możliwości utworzenia niepoprawnie sformułowanego dokumentu (chyba że jest błąd w bibliotekach XML). Przy zastosowaniu JSP jako metody tworzenia dokumentów XML nie ma sposobu na ochronę przed przypadkowym stworzeniem dokumentu zawierającego źle dopasowane znaczniki zamykające, jak poniżej: ?xml version= 1.0 encoding= UTF-8 ? books book title Ajax Hacks /title author Bruce W. Perry /pubdate pubdate marzec 2006 /author /book /books Nie da się wyeliminować prawdopodobieństwa wystąpienia jakiegokolwiek błędu związa- nego z poprawną formulacją. Aczkolwiek ten sposób tworzenia dokumentów za pomocą JSP na pewno jest szybszy i potrzebuje mniej pamięci, ponieważ pomija tworzenie pośrednich obiektów DOM. 370 | Rozdział 13. Prezentacyjny XML Transformacja na HTML za pomocą JSP Jeśli zamiast XML spodziewaną odpowiedzią od aplikacji sieciowej są dokumenty HTML, to do dyspozycji mamy kilka możliwości transformacji reprezentacji XML obiektów modelu na HTML. Mimo że podstawowy JSP nie udostępnia żadnych funkcji przeznaczonych specjalnie do pracy z XML, to biblioteka Java Standard Tag Library zawiera kilka znaczników przezna- czonych specjalnie dla dokumentów XML. Za ich pomocą można przekształcać dokumenty XML na HTML przy użyciu XPath lub XSLT. Dodatkowo JSLT zawiera znaczniki pozwalające na przetworzenie dokumentu XML na obiekt DOM, do którego można następnie stosować pozostałe znaczniki. Znaczniki XML JSTL JSTL to zbiór znaczników JSP, których przeznaczeniem jest zaspokojenie różnych podstawo- wych potrzeb podczas pisania stron JSP. Zawiera bibliotekę znaczników XML udostępniającą szereg znaczników używanych do przetwarzania dokumentów XML za pomocą stron JSP: out Ewaluuje wyrażenie XPath i wysyła wynik na wyjście. parse Przetwarza i włącza łańcuch do obiektu DOM Document. set Ewaluuje wyrażenie XPath i zapisuje wynik jako lokalną zmienną JSP. if Wykonuje to, co jest w ciele znacznika, jeśli wyrażenie XPath zwróci wartość true. choose-when-otherwise Ma podobną funkcjonalność co konstrukcja Javy switch-case-default, przy użyciu wyrażeń XPath. forEach Przechodzi przez listę wierzchołków DOM. transform Wykonuje transformację XSLT. Jako że wszystkie te znaczniki (poza parse) przyjmują jako punkt początkowy wierzchołek DOM, możemy zmodyfikować metodę renderBooks() z listingu 13.1 w taki sposób, aby zapisy- wała obiekt DOM Document jako atrybut żądania i wysyłała go do pliku o nazwie booklist2.jsp: private void renderBooks(Document doc, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { request.setAttribute( xml , doc); RequestDispatcher dispatcher = getServletContext() .getRequestDispatcher( /booklist2.jsp ); dispatcher.include(request, response); } Listing 13.5 przedstawia stronę JSP booklist.jsp. Należy zwrócić uwagę, że atrybut żądania xml jest dostępny jako zmienna XPath. Poza atrybutami żądań w tych wyrażeniach XPath można także wykorzystać atrybuty sesji i aplikacji, parametry żądania, nagłówki HTTP, pliki cookies oraz parametry inicjalizacyjne serwletu. Transformacja na HTML za pomocą JSP | 371 Listing 13.5. Wysyłanie na wyjście listy książek za pomocą JSTL @ taglib prefix= x uri= http://java.sun.com/jsp/jstl/xml !DOCTYPE HTML PUBLIC -//W3C//DTD HTML 4.01 Transitional//EN html head title Lista książek /title /head body h1 Lista książek /h1 table border= 1 tbody tr th Tytuł /th th Autor /th th Data wydania /th /tr x:forEach select= $xml/books/book var= book tr td x:out select= $book/title / /td td x:out select= $book/author / /td td x:out select= $book/pubdate / /td /tr /x:forEach /tbody /table /body /html Po zaktualizowaniu kodu serwletu i strony JSP wynik HTML jest już znacznie bliższy temu, czego się spodziewaliśmy, co widać na rysunku 13.2. Rysunek 13.2. Dane książek w formacie HTML wygenerowane przez JSP Jak już wspominałem powyżej, w JSP jest znacznik transformacji służący do wykonywania przekształceń za pomocą XSL. Przejdźmy zatem do transformacji XSL. 372 | Rozdział 13. Prezentacyjny XML Używanie XSLT Jak można się było przekonać we wcześniejszych rozdziałach, XSLT jest niezwykle pożytecz- nym narzędziem do transformacji dokumentów XML z jednego rodzaju składni na inny, jak również na HTML. Jedną z bardziej interesujących opcji dostępnych dzięki XSLT jest prze- rzucenie ciężaru dokonywania konwersji na aplikacje klienckie, jako że większość współcze- snych przeglądarek obsługuje XSLT. Aczkolwiek podejście to ma pewne wady. Jeśli tworzone aplikacje nie są przeznaczone dla bardzo wąskiego grona kontrolowanych odbiorców, bę- dziemy mieli bardzo mały, jeśli w ogóle, wpływ na szybkość działania ich aplikacji klienckich. W wyniku tego różni użytkownicy mogą odnieść całkiem inne wrażenie. Oczywiście, do pewnego stopnia ma to też zastosowanie do zwykłego HTML. Po tym wstępie można tylko dodać, że transformacje po stronie klienta są przydatnym narzędziem w arsenale każdego programisty XML. Wykonywanie transformacji po stronie klienta Istnieją dwie metody wykonywania transformacji po stronie klienta — użycie instrukcji przetwarzania i pisanie skryptów wykonywanych po stronie klienta. Użycie instrukcji przetwarzania Najprostszym sposobem zażądania transformacji XSL jest umieszczenie instrukcji przetwa- rzania xml-stylesheet pomiędzy deklaracją XML a elementem korzenia. Jeśli przeglądarka otrzyma na przykład dokument z listingu 13.6, to zażąda pliku http://www.example.com/books.xsl i wykorzysta zawarty w nim arkusz stylów do przekształcenia dokumentu w celu jego prezentacji. Listing 13.6. Dokument XML z odniesieniem do arkusza stylów ?xml version= 1.0 encoding= UTF-8 ? ?xml-stylesheet type= text/xsl href= http://www.example.com/books.xsl ? books book title Ajax Hacks /title author Bruce W. Perry /author pubDate marzec 2006 /pubDate /book book title LDAP System Administration /title author Gerald Carter /author pubDate marzec 2003 /pubDate /book book title Java Servlet Programming /title author Jason Hunter /author pubDate kwiecień 2001 /pubDate /book /books Instrukcję przetwarzania xml-stylesheet można ograniczyć, aby miała zastosowanie tylko w przypadkach, gdy dokument ma być prezentowany w urządzeniach określonego typu. Wiele źródeł RSS wykorzystuje tę instrukcję przetwarzania do wyświetlania stron HTML, Używanie XSLT | 373 kiedy klientem jest przeglądarka. Przykładowo źródło RSS ze strony Wired zawiera poniższą instrukcję przetwarzania: ?xml-stylesheet href= http://feeds.wired.com/~d/styles/rss2full.xsl type= text/xsl media= screen ? W wyniku tego, kiedy oglądam to źródło (http://feeds.wired.com/wired/topheadlines) w przeglą- darce internetowej (która jest widoczna na moim ekranie), widzę jego zawartość oraz różne odnośniki umożliwiające subskrypcję tego źródła w wybranym agregatorze RSS, jak widać na rysunku 13.3. Rysunek 13.3. Transformacja przeznaczona dla określonego medium Kiedy ten sam dokument jest ładowany przez agregator RSS, to transformacja jest ignorowana dzięki określeniu w instrukcji przetwarzania odpowiedniego typu mediów. Transformacje przy użyciu JavaScript Do uruchamiania procesu transformacji po stronie klienta można używać języka JavaScript zamiast instrukcji przetwarzania w przeglądarkach Mozilla Firefox i Internet Explorer. Więcej na ten temat piszę dalej w podrozdziale „Używanie XSLT z Ajax”. Transformacje po stronie serwera Jak wcześniej wspominałem, transformacje po stronie klienta mają pewne wady. Poza pro- blemem z wydajnością jest jeszcze to, że nie wszystkie przeglądarki obsługują transformacje. Jednym z możliwych wyjść z takiej sytuacji jest zastosowanie transformacji po stronie klienta, jeśli są przez niego obsługiwane, i po stronie serwera w pozostałych przypadkach. 374 | Rozdział 13. Prezentacyjny XML Transformacja w filtrze Przy użyciu filtra serwletów Javy można przechwycić żądania dokumentów XML wysyłane przez przeglądarki, które nie obsługują transformacji i, jeśli dokument zawiera instrukcję przetwarzania xml-stylesheet, wykonać transformację na serwerze. Filtr taki, który wyko- nuje transformacje po stronie serwera, obsługując tekstową przeglądarkę Lynx, przedstawio- no na listingu 13.7. Listing 13.7. Transformacja w filtrze package javaxml3.ch13; import java.io.CharArrayWriter; import java.io.IOException; import java.io.PrintWriter; import java.io.StringReader; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class XSLFilter implements Filter { private Pattern hrefPattern; private SAXParserFactory saxParserFactory; private TransformerFactory transformerFactory; private Pattern typePattern; public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (request instanceof HttpServletRequest) { if (isLynxRequest((HttpServletRequest) request)) { CharResponseWrapper wrapper = new CharResponseWrapper( (HttpServletResponse) response); chain.doFilter(request, wrapper); String xml = wrapper.toString(); Używanie XSLT | 375 // Przetwarzaj tylko odpowiedzi XML. if ( text/xml .equals(wrapper.getContentType())) { String stylesheetHref = getStylesheetHref(xml); if (stylesheetHref != null) { response.setContentType( text/html ); transformResponse(response, xml, stylesheetHref); } else { response.getWriter().print(xml); } } else { response.getWriter().print(xml); } } else { chain.doFilter(request, response); } } else { chain.doFilter(request, response); } } private String getStylesheetHref(String xml) { StylesheetPIHandler handler = new StylesheetPIHandler(); try { SAXParser parser = saxParserFactory.newSAXParser(); InputSource input = new InputSource(new StringReader(xml)); parser.parse(input, handler); return handler.getHref(); } catch (Exception e) { return null; } } public void init(FilterConfig config) throws ServletException { saxParserFactory = SAXParserFactory.newInstance(); transformerFactory = TransformerFactory.newInstance( ); typePattern = Pattern.compile( .*type\s*=\s* (\S*) .* ); hrefPattern = Pattern.compile( .*href\s*=\s* (\S*) .* ); } private boolean isLynxRequest(HttpServletRequest request) { String userAgent = request.getHeader( User-Agent ); return (userAgent.indexOf( Lynx ) = 0); } private void transformResponse(ServletResponse response, String xml, String stylesheetHref) throws IOException, ServletException { StreamSource sheetSource = new StreamSource(stylesheetHref); StreamSource xmlSource = new StreamSource(new StringReader(xml)); StreamResult result = new StreamResult(response.getWriter()); try { Transformer trans = transformerFactory.newTransformer(sheetSource); trans.transform(xmlSource, result); } catch (TransformerException e) { throw new ServletException( Nie można wykonać transformacji. , e); } } class CharResponseWrapper extends HttpServletResponseWrapper { private CharArrayWriter output; 376 | Rozdział 13. Prezentacyjny XML public CharResponseWrapper(HttpServletResponse response) { super(response); output = new CharArrayWriter(); } public ServletOutputStream getOutputStream() throws IOException { return new ServletOutputStream() { public void write(int b) throws IOException { output.write(b); } }; } public PrintWriter getWriter() { return new PrintWriter(output); } public String toString() { return output.toString(); } } class StylesheetPIHandler extends DefaultHandler { private String href = null; public String getHref() { return href; } public void processingInstruction(String target, String data) throws SAXException { if ( xml-stylesheet .equals(target)) { Matcher typeMatcher = typePattern.matcher(data); if (typeMatcher.matches() text/xsl .equals(typeMatcher.group(1))) { Matcher hrefMatcher = hrefPattern.matcher(data); if (hrefMatcher.matches()) href = hrefMatcher.group(1); } } } } } Jak widać na listingu, filtr ten przechwytuje żądania. Jeśli zaistnieje możliwość, że trzeba będzie dane wysyłane w odpowiedzi przetransformować, filtr zamieni bieżący obiekt HttpServlet- Response na obiekt osłonowy buforujący te dane. Po wygenerowaniu danych odpowiedzi parser SAX szuka instrukcji przetwarzania, a następnie dwa wyrażenia regularne pozwalają na sprawdzenie odpowiedniego identyfikatora URI arkusza stylów. Po zastosowaniu tego filtra w wyniku żądania pliku books.xml do przeglądarki Lynx zostanie zwrócony kod HTML, a do innych przeglądarek XML. Rysunki 13.4 i 13.5 przedstawiają ten sam kod w przeglądarkach Lynx i Internet Explorer. Jedyna różnica polega na tym, gdzie ten kod HTML został wygenerowany. Używanie XSLT | 377 Rysunek 13.4. Wynik transformacji po stronie serwera w przeglądarce Lynx Rysunek 13.5. Wynik transformacji po stronie klienta w przeglądarce Internet Explorer Transformacje przy użyciu JSTL Jak wcześniej wspominałem, JSTL udostępnia znacznik transform, który pozwala przekształcać dokumenty XML. Do tego potrzebne są dokument XML i arkusz stylów. Można je zdefiniować w kodzie strony: c:set var= doc books book title Ajax Hacks /title author Bruce W. Perry /author pubdate marzec 2006 /pubdate /book !-- Dodaj tu więcej książek. -- 378 | Rozdział 13. Prezentacyjny XML /books /c:set c:set var= xsl xsl:stylesheet version= 1.0 xmlns:xsl= http://www.w3.org/1999/XSL/Transform xsl:output method= html / xsl:template match= books html head title Książki /title /head body h1 Lista książek /h1 table border= 1 tbody tr th Tytuł /th th Autor /th th Data wydania /th /tr xsl:apply-templates select= book / /tbody /table /body /html /xsl:template xsl:template match= book tr td xsl:value-of select= title / /td td xsl:value-of select= author / /td td xsl:value-of select= pubdate / /td /tr /xsl:template /xsl:stylesheet /c:set x:transform doc= ${doc} xslt= ${xsl} / Dokumenty te mogą zostać załadowane z podanych adresów URL: @ taglib prefix= x uri= http://java.sun.com/jsp/jstl/xml @ taglib prefix= c uri= http://java.sun.com/jsp/jstl/core c:import var= doc url= http://localhost:8080/ch13-servlet/books.xml / c:import var= xsl url= http://localhost:8080/ch13-servlet/books.xsl / x:transform doc= ${doc} xslt= ${xsl} / Kod XML można zamknąć w znaczniku transform: @ taglib prefix= x uri= http://java.sun.com/jsp/jstl/xml @ taglib prefix= c uri= http://java.sun.com/jsp/jstl/core c:import var= xsl url= http://localhost:8080/ch13-servlet/books.xsl / x:transform xslt= ${xsl} books book title Ajax Hacks /title author Bruce W. Perry /author pubdate marzec 2006 /pubdate /book !-- Dodaj tu więcej książek. -- /books /x:transform Używanie XSLT | 379 Na koniec wynik transformacji można zapisać jako obiekt DOM, względem którego mogą być ewaluowane wyrażenia XPath: @ taglib prefix= x uri= http://java.sun.com/jsp/jstl/xml @ taglib prefix= c uri= http://java.sun.com/jsp/jstl/core c:import var= xsl url= http://localhost:8080/ch13-servlet/books.xsl / x:transform xslt= ${xsl} var= result books book title Ajax Hacks /title author Bruce W. Perry /author pubdate marzec 2006 /pubdate /book !-- Dodaj tu więcej książek. -- /books /x:transform x:out select= $result//h1 / Ajax Za nazwą Ajax kryje się grupa powiązanych ze sobą wzorców programowania sieciowego wykorzystywanych do tworzenia interaktywnych aplikacji sieciowych. W tradycyjnych, nie- używających technologii Ajax, aplikacjach sieciowych użytkownik odwiedza poszczególne strony jedna po drugiej — każda jego czynność powoduje wysłanie przez przeglądarkę żą- dania nowej strony. W Ajax natomiast uaktualniany jest tylko pewien fragment strony na podstawie niewielkich pakietów danych, przesyłanych asynchronicznie pomiędzy serwerem a przeglądarką. Dzięki temu aplikacja jest znacznie bardziej interaktywna i zużywa o wiele mniej transferu. Mimo iż termin „Ajax” został ukuty w 2005 roku1, techniki tego typu były stosowane od chwili wprowadzenia ramek do HTML w połowie lat 90. Początkowo doku- menty HTML ładowano za pomocą JavaScript do ukrytych ramek, a w Internet Explorerze do znacznika IFRAME. Dokumenty te zawierały kod JavaScript, który zmieniał wygląd stron. Ponadto dodatkową funkcjonalność uzyskiwano przy użyciu apletów w Javie i wtyczek do przeglądarek. Mimo że ramki oferowały możliwości asynchroniczne, to były one jednak bardzo podatne na błędy. Na przykład kliknięcie przez użytkownika przycisku przejścia do poprzedniej strony mogło spowodować wejście przeglądarki w nieprawidłowy stan. Techniki alternatywne do ramek, takie jak aplety Javy czy wtyczki, były obciążone własnymi problemami z kompaty- bilnością i bezpieczeństwem. W wyniku tego aplikacje Ajax nie były zbyt popularne i stoso- wano je tylko dla określonych grup użytkowników lub platform. Wszystko zmieniło się, kiedy Microsoft wprowadził obiekt XMLHttpRequest w przeglądarce Internet Explorer 5 w 2000 roku. 1 Patrz http://www.adaptivepath.com/publications/essays/archives/000385.php. 380 | Rozdział 13. Prezentacyjny XML Czy Ajax to akronim? Ściśle mówiąc, Ajax jest definiowany jako akronim zbudowany z pierwszych liter słów Asynchronous JavaScript and XML. Jednak przyjął się zapis z tylko pierwszą wielką literą — „Ajax” zamiast „AJAX”. Ponadto, w miarę jak wzorce Ajaksa zyskiwały coraz to więcej użyt- kowników wśród programistów sieciowych, pojawiły się techniki pozwalające na uzyskanie oferowanej przez niego funkcjonalności bez używania XML. Na przykład w aplikacjach Ajax Google (Gmail, Google Maps, Google Spreadsheets) użyto względnie mało XML. W związku z tym coraz bardziej staje się jasne, że Ajax nie powinien być uważany za akronim, a jeśli już, to jego źródła należy doszukiwać się w słowach Asynchronous JavaScript and the XMLHttp- Request object. Obiekt XMLHttpRequest Obiekt XMLHttpRequest jest używany przez języki skryptowe w przeglądarce (zazwyczaj JavaScript, ale nie tylko) do wysyłania żądań HTTP. Jak jego nazwa wskazuje, został stwo- rzony do tworzenia żądań dokumentów XML. Jednak w zachowaniu tego obiektu nie ma nic, co byłoby ściśle związane z XML. Obiekt XMLHttpRequest nie został jeszcze ustandaryzowany, ale obecne jego implementacje oferują zbliżone do siebie możliwości. Konsorcjum W3C pod- jęło już działania w kierunku standaryzacji interfejsu i funkcjonalności tego obiektu. Postęp prac można obejrzeć na stronie http://www.w3.org/TR/XMLHttpRequest. W przeglądarkach Internet Explorer w wersjach wcześniejszych niż 7. obiekt XMLHttpRequest jest kontrolką ActiveX, której egzemplarz tworzy się następująco: var req = new ActiveXObject( Microsoft.XMLHTTP ); W Internet Explorer 7 i innych przeglądarkach, jest on obiektem JavaScript, którego egzem- plarze tworzone są za pomocą słowa kluczowego new: var req = new XMLHttpRequest(); W związku z tym, aby utworzyć właściwy obiekt dla danej przeglądarki, z reguły wykorzy- stuje się instrukcję warunkową if-else: var req; if (window.XMLHttpRequest) { req = new XMLHttpRequest(); } else if (window.ActiveXObject) { req = new ActiveXObject( Microsoft.XMLHTTP ); } Obiekt XMLHttpRequest może pracować zarówno w trybie synchronicznym (skrypt oczekuje na odpowiedź od serwera), jak i asynchronicznym (skrypt jest wykonywany po wysłaniu żądania, a po nadejściu odpowiedzi wywoływana jest metoda zwrotna). Listing 13.8 przedstawia stronę, która żąda dokumentu XML i zwraca go w postaci wartości pola formularza osadzonego na stronie HTML. Listing 13.8. Synchroniczne wykorzystanie obiektu XMLHttpRequest html body form id= form textarea rows= 20 cols= 80 id= xmlarea /textarea /form Ajax | 381 script language= JavaScript var req; var xmlarea = document.forms[ form ].elements[ xmlarea ] if (window.XMLHttpRequest) { req = new XMLHttpRequest(); } else if (window.ActiveXObject) { req = new ActiveXObject( Microsoft.XMLHTTP ); } if (req == undefined) { xmlarea.value = Obiekt XMLHttpRequest jest niedostępny. ; } else { req.open( GET , /ch13-servlet/booklist-xml , false); // Trzeci param = false oznacza tryb synchroniczny. req.send(null); // Sprawdzenie statusu. if (req.status == 200) xmlarea.value = req.responseText; else xmlarea.value = Got Response Code: + req.status; } /script /body /html Kod z listingu 13.9 robi dokładnie to samo, ale pracuje w trybie asynchronicznym. Listing 13.9. Asynchroniczne zastosowanie obiektu XMLHttpRequest html body form id= form textarea rows= 20 cols= 80 id= xmlarea /textarea /form script language= JavaScript var xmlarea = document.forms[ form ].elements[ xmlarea ]; var req; if (window.XMLHttpRequest) { req = new XMLHttpRequest(); } else if (window.ActiveXObject) { req = new ActiveXObject( Microsoft.XMLHTTP ); } if (req == undefined) { xmlarea.value = Obiekt XMLHttpRequest jest niedostępny. ; } else { req.open( GET , /ch13-servlet/booklist-xml , true); // Trzeci param = true oznacza tryb asynchroniczny. req.onreadystatechange = docLoaded; req.send(null); } function docLoaded() { if (req.readyState == 2) { xmlarea.value = Czekaj... ; } if (req.readyState == 4) { xmlarea.value = Otrzymano odpowiedź... ; // Tylko dla zwiększenia efektu, uaktualnij pole tekstowe po odczekaniu jednej sekundy. setTimeout( updateTextArea() ,1000); } } function updateTextArea() { 382 | Rozdział 13. Prezentacyjny XML if (req.status == 200) xmlarea.value = req.responseText; else xmlarea.value = Otrzymano kod odpowiedzi: + req.status; } /script /body /html W trybie asynchronicznym obiekt XMLHttpRequest musi mieć funkcję zwrotną ustawioną przy użyciu właściwości onreadystatechange. Funkcja ta sprawdza wartość właściwości readyState w celu określenia bieżącego stanu żądania. Możliwe wartości tej właściwości przedstawia tabela 13.1. Należy zwrócić uwagę, że ta funkcja zwrotna nie może być wywo- ływana dla każdego z tych stanów. Tabela 13.1. Dostępne wartości właściwości readyState obiektu XMLHttpRequest Wartość 0 1 2 3 4 Znaczenie Niezainicjalizowane Otwarte Wysłane Otrzymywanie Załadowane Generalnie obiekt XMLHttpRequest nie może wysyłać żądań do serwera innego niż ten, z którego została załadowana zawierająca go strona. W przykładach tych zawartość dokumentu XML jest dołączana po prostu do strony przy jej pierwszym załadowaniu. Kod na listingu 13.10 idzie o krok dalej i pozwala na przełączanie pomiędzy dwoma dokumentami bez ponownego wczytywania strony. Listing 13.10. Żądanie różnych dokumentów na podstawie działań użytkownika html body form id= form textarea rows= 20 cols= 80 id= xmlarea Brak książek. /textarea /form script language= JavaScript var xmlarea = document.forms[ form ].elements[ xmlarea ]; var req; if (window.XMLHttpRequest) { req = new XMLHttpRequest(); } else if (window.ActiveXObject) { req = new ActiveXObject( Microsoft.XMLHTTP ); } function loadBooks(filename) { if (req == undefined) { xmlarea.value = Obiekt XMLHttpRequest jest niedostępny. ; } else { xmlarea.value = Czekaj... ; req.open( GET , /ch13-servlet/ +filename, true); req.onreadystatechange = docLoaded; req.send(null); } } Ajax | 383 if (req.readyState == 4) { if (req.status == 200) xmlarea.value = req.responseText; else xmlarea.value = Got Response Code: + req.status; } /script a href= javascript:loadBooks( books.xml ) Załaduj książki /a br/ a href= javascript:loadBooks( morebooks.xml ) Załaduj więcej książek /a br/ /body /html Przy pierwszym załadowaniu tej strony pole tekstowe zawiera tylko łańcuch Brak książek. Wtedy użytkownik może kliknąć jeden z odnośników, aby zapełnić to pole. Na rysunkach odpowiednio 13.6 i 13.7 przedstawiono stronę bezpośrednio po załadowaniu i po kliknięciu odnośnika Załaduj więcej książek. Rysunek 13.6. Strona bezpośrednio po załadowaniu Rysunek 13.7. Strona po kliknięciu odnośnika Załaduj więcej książek 384 | Rozdział 13. Prezentacyjny XML Używanie DOM z Ajaksem Poza właściwością responseText zawierającą odpowiedź w postaci tekstu obiekt XMLHttp- Request posiada też właściwość, która zawiera odpowiedź w postaci obiektu DOM. Zamiast tylko umieścić na stronie kod XML (jak było robione wcześniej), można użyć API DOM i wy- dobyć wartości z tego obiektu. Strona HTML z listingu 13.11 zawiera znacznik div, który jest zapełniany tytułami i autorami wszystkich książek z pliku XML. Kiedy zostanie kliknięty jeden z odnośników wyboru pliku, domyślny tekst zostanie nadpisany przez listę książek przy użyciu właściwości innerHTML. W kodzie wykorzystana została metoda DOM getElementBy- TagName() oraz różne właściwości tego API. Listing 13.11. Dostęp do dokumentu DOM w JavaScript html body div id= xmlarea Nie załadowano żadnych książek. /div hr/ script language= JavaScript var xmlarea = document.getElementById( xmlarea ); var req; if (window.XMLHttpRequest) { req = new XMLHttpRequest(); } else if (window.ActiveXObject) { req = new ActiveXObject( Microsoft.XMLHTTP ); } function loadBooks(filename) { if (req == undefined) { xmlarea.innerHTML = Obiekt XMLHttpRequest jest niedostępny. ; } else { xmlarea.innerHTML = Czekaj... ; req.open( GET , /ch13-servlet/ +filename, true); req.onreadystatechange = docLoaded; req.send(null); } } function docLoaded() { if (req.readyState == 4) { doc = req.responseXML; newValue = Książki: br/ ; books = doc.getElementsByTagName( book ); for (i = 0; i books.length; i++) { book = books.item(i); var title; var author; for (j = 0; j book.childNodes.length; j++) { node = book.childNodes[j]; if (node.nodeName == title ) { title = node.firstChild.nodeValue; } else if (node.nodeName == author ) { author = node.firstChild.nodeValue; } } newValue = newValue + (i+1) + ) + title + by + author + br/ ; } Ajax | 385 xmlarea.innerHTML = newValue; } } /script Choose a file list: br/ a href= javascript:loadBooks( books.xml ) books.xml /a br/ a href= javascript:loadBooks( morebooks.xml ) morebooks.xml /a br/ /body /html Rysunek 13.8 przedstawia stronę po jej pierwszym załadowaniu. Strona po załadowaniu pliku books.xml została przedstawiona na rysunku 13.9. Warto zwrócić uwagę, że rozmiar elementu div został automatycznie zmieniony i w wyniku tego odnośniki przesunęły się w dół. Rysunek 13.8. Strona DOM przed wybraniem pliku Rysunek 13.9. Strona DOM po wybraniu pliku Osoby, które dobrze poznały API DOM w Javie, powinny być w stanie zastosować tę wiedzę do używania DOM w JavaScript. Dowiązania DOM dla języka ECMAScript (standardowego języka skryptowego, od którego pochodzi JavaScript) zostały zdefiniowane przez W3C na stronie http://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.html. Więcej szczegółów na temat API DOM JavaScript można znaleźć w książce Davida Flanagana pod tytułem JavaScript: The Definitive Guide (O’Reilly). 386 | Rozdział 13. Prezentacyjny XML Używanie XSLT z Ajaksem Zarówno Internet Explorer, jak i Mozilla Firefox obsługują transformacje XSL wykonywane poprzez JavaScript. Niestety, podobnie jak w przypadku obiektu XMLHttpRequest, do obsłu- gi transformacji dostęp uzyskuje się w nich na różne sposoby. W Internet Explorerze obiekty DOM mają metodę transformNode(), której przekazuje się obiekt DOM Document zawierający arkusz stylów: transformOutput = element.transformNode(xslDocument); Wynikiem transformacji może być łańcuch, jak powyżej, lub obiekt DOM. W Firefoksie jest obiekt JavaScript o nazwie XSLTProcessor, do którego dodawane są arkusze stylów przed transformacją: xsltProcessor = new XSLTProcessor(); xsltProcessor.importStylesheet(xslDocument); transformOutputDoc = xsltProcessor.transformToFragment(element, document); Wynik transformacji w Firefoksie może być fragmentem drzewa DOM albo dokumentem DOM. Strona na listingu 13.12 w następnym podrozdziale posiada taką samą funkcjonalność przy użyciu XSLT, jaką miała ta z listingu 13.11 z DOM. W tym przykładzie zobaczymy różne sposoby użycia wyniku transformacji w Internet Explorerze i Firefoksie. html body div id= xmlarea Nie załadowano żadnych książek. /div hr/ script language= JavaScript var xmlarea = document.getElementById( xmlarea ); var req; if (window.XMLHttpRequest) { req = new XMLHttpRequest(); } else if (window.ActiveXObject) { req = new ActiveXObject( Microsoft.XMLHTTP ); } req.open( GET , /ch13-ajax/authortitle.xsl , false); req.send(null); var xsldoc = req.responseXML; function loadBooks(filename) { if (req == undefined) { xmlarea.innerHTML = Obiekt XMLHttpRequest jest niedostępny. ; } else { xmlarea.innerHTML = Czekaj... ; req.open( GET , /ch13-servlet/ +filename, true); req.onreadystatechange = docLoaded; req.send(null); } } function docLoaded() { if (req.readyState == 4 req.status == 200) { xmldoc = req.responseXML; if (window.ActiveXObject) { xmlarea.innerHTML = xmldoc.transformNode(xsldoc); } else if (window.XSLTProcessor) { processor = new XSLTProcessor(); Ajax | 387 processor.importStylesheet(xsldoc); xmloutput = processor.transformToFragment(xmldoc, document); xmlarea.innerHTML = ; xmlarea.appendChild(xmloutput); } else { xmlarea.innerHTML = XSLT nie jest dostępny w Twojej przeglądarce. ; } } } /script Choose a file list: br/ a href= javascript:loadBooks( books.xml ) books.xml /a br/ a href= javascript:loadBooks( morebooks.xml ) morebooks.xml /a br/ /body /html Wysyłanie XML do serwera W powyższych przykładach wszystkie żądania wysyłane za pomocą obiektu XMLHttpRequest były zwykłymi adresami URL. Można do nich z łatwością dodać opcje w postaci parametrów adresu strony, na przykład http://www.example.com/servlets/stock?s=IBM. W przypadku bardziej złożonych parametrów XMLHttpRequest pozwala wysyłać treść w ciele żądania przy użyciu metody HTTP POST. Jednym z zastosowań tej możliwości jest wysyłanie dokumentów XML do aplikacji działającej na serwerze. W tym celu należy ustawić nagłówek żądania Content-Type na text/xml i dokument XML przekazać jako łańcuch znaków albo obiekt DOM do metody send() obiektu XMLHttpRequest. Tworzenie dokumentu XML w JavaScript Aby wygenerować dokument XML dla żądania, można zastosować konkatenację łańcuchów, jak poniżej: req.send( search name + document.getElementById( name ).value + /name year + document.getElementById( year ).value + /year /search ); Kod JavaScript budujący dokumenty za pomocą łączenia (konkatenacji) łańcuchów może stać się skomplikowany i podatny na błędy, ponieważ nie ma w nim żadnego mechanizmu zapo- biegającego tworzeniu źle sformułowanych dokumentów. Aby mieć pewność, że tworzone dokumenty będą poprawne składniowo, należy skorzystać z możliwości DOM dostępnych w JavaScript. Podobnie jak w przypadku obiektu XMLHttpRequest, obiekty DOM Document w Internet Explorerze są tworzone jako kontrolki ActiveX, a w innych przeglądarkach poprzez natywne API JavaScript. Aby w przeglądarce Internet Explorer utworzyć obiekt Document, trzeba wpierw utworzyć pusty dokument, a następnie w nim element korzenia: doc = new ActiveXObject( Microsoft.XMLDOM ); doc.appendChild(doc.createElement( search )); W Firefoksie i pozostałych przeglądarkach dokument jest tworzony od razu z elementem korzenia: doc = document.implementation.createDocument(null, search , null); Metoda createDocument() przyjmuje identyfikator URI przestrzeni nazw i DTD oraz nazwę elementu korzenia. 388 | Rozdział 13. Prezentacyjny XML Wysyłanie dokumentu XML Po utworzeniu dokumentu XML jako łańcucha lub obiektu DOM przekazuje się go do metody send() obiektu XMLHttpRequest. Listing 13.12 przedstawia prosty formularz HTML, w którym naciśnięcie przycisku submit spowoduje wysłanie zawartości pól jako dokumentu XML. Listing 13.12. Wysyłanie danych z formularza jako XML html body h1 Składnica książek /h1 form id= form onsubmit= search(); return false; Nazwa: input type= text id= name / br/ Rok (optional): select id= year option value= notselected ...wybierz... /option option value= 2001 2001 /option option value= 2002 2002 /option option value= 2003 2003 /option option value= 2004 2004 /option option value= 2005 2005 /option /select br/ input type= submit value= Wyślij / hr/ Wyniki wyszukiwania: br/ textarea rows= 3 cols= 50 id= results readonly= true /textarea /form script language= JavaScript function search() { var req; var form = document.forms[ form ]; if (window.XMLHttpRequest) { req = new XMLHttpRequest(); } else if (window.ActiveXObject) { req = new ActiveXObject( Microsoft.XMLHTTP ); } if (req == undefined) { document.getElementById( results ).value = Obiekt XMLHttpRequest jest niedostępny. ; } else { req.open( POST , /ch13-ajax/post , false); req.setRequestHeader( Content-Type , text/xml ); postDoc = makePostData(); req.send(postDoc); // Sprawdź status. if (req.status == 200) document.getElementById( results ).value = req.responseText; else document.getElementById( results ).value = Otrzymano kod odpowiedzi: + req.status; } } function makePostData() { var doc; if (window.ActiveXObject) { doc = new ActiveXObject( Microsoft.XMLDOM ); doc.appendChild(doc.createElement( search )); } else { doc = document.implementation.createDocument(null, search , null); Ajax | 389 } nameElement = doc.createElement( name ); nameText = doc.createTextNode(document.getElementById( name ).value); nameElement.appendChild(nameText); doc.documentElement.appendChild(nameElement); yearElement = doc.createElement( year ); yearText = doc.createTextNode(document.getElementById( year ).value); yearElement.appendChild(yearText); doc.documentElement.appendChild(yearElement); return doc; } /script /body /html W prawdziwej aplikacji trzeba by było dodać jeszcze mechanizm walidacji w JavaScript wprowadzonych danych przed wysłaniem żądania. Jedną z zalet Ajaksa w porównaniu z tradycyjnymi aplikacjami sieciowymi jest to, że za jego pomocą można przynajmniej część walidacji wykonać przed wysłaniem danych z formularza. Przy tworzeniu serwletu odbierającego te żądania i analizującego składnię przesyłanego do- kumentu można użyć albo obiektu Reader, albo InputStream z żądania, do których dostęp dają odpowiednio metody getReader() i getInputStream(). Listing 13.13 zawiera serwlet, który wprawdzie niczego nie wyszukuje, ale przyjmuje dokument utworzony przez kod z li- stingu 13.12 i przesyła kryteria wyszukiwania z powrotem do przeglądarki. Do wydobycia ich z dokumentu wykorzystano obsługę XPath w JDOM. Listing 13.13. Serwlet odbierający dokumenty XML package javaxml3.ch13; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.jdom.Document; import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; import org.jdom.xpath.XPath; public class PostServlet extends HttpServlet { private SAXBuilder builder = new SAXBuilder(); private XPath nameXPath; private XPath yearXPath; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if (! text/xml .equals(request.getContentType())) { response.getWriter().println( Prześlij proszę jako text/xml. ); } else { try { Document doc = builder.build(request.getReader()); 390 | Rozdział 13. Prezentacyjny XML StringBuffer buff = new StringBuffer(); buff.append( Szukano nazwy + nameXPath.valueOf(doc) + ); String year = yearXPath.valueOf(doc); if (! notselected .equals(year)) { buff.append( i roku + year + ); } buff.append( . ); response.getWriter().print(buff.toString()); } catch (JDOMException e) { response.getWriter().print( Błąd uzyskiwania kryteriów szukania: + e.getMessage()); } } } public void init() throws ServletException { try { nameXPath = XPath.newInstance( /search/name/text() ); yearXPath = XPath.newInstance( /search/year/text() ); } catch (JDOMException e) { throw new ServletException( Nie można utworzyć wyrażeń XPath. , e); } super.init(); } } Wspólnie kod HTML i serwlet dadzą wynik jak na rysunku 13.10. Rysunek 13.10. Wynik wysłania XML Podrozdział ten zawiera krótkie wprowadzenie do XML w aplikacjach Ajax. Tworzenie pro- gramów przy użyciu tej techniki nie kończy się oczywiście na tym. Jest to bardzo dynamicz- nie rozwijająca się technologia, na której temat powstało mnóstwo zasobów dostępnych w internecie — od blogów (Ajaxian.com) po strony dla programistów prowadzone przez takie firmy jak Mozilla czy Microsoft. Dostępnych jest też na jej temat wiele publikacji książko- wych, łącznie z, nie mógłbym nie wspomnieć, Head Rush Ajax autorstwa Bretta McLaughlina (O’Reilly). Ajax | 391 Flash Od chwili wprowadzenia w 1996 roku pod nazwą FutureSplash, Adobe Flash (wcześniej Macromedia Flash) stał się standardem dla twórców animacji i interaktywności sieciowej. Każde kolejne wydanie tej technologii było wzbogacane aż do stanu obecnego, w którym Flash jest w pełni funkcjonalną platformą do tworzenia dowolnego rodzaju animacji. Na plat- formę tę składają się obecnie trzy różne komponenty: format pliku o nazwie SWF (pliki w tym formacie są powszechnie nazywane filmami we · Flashu), programy otwierające pliki SWF, które mogą występować jako samodzielne aplikacje · (Flash Player) lub wtyczki do przeglądarek, narzędzia do tworzenia animacji. · Na stronie firmy Adobe dostępna jest specyfikacja formatu SWF. Jednak w warunkach licen- cji zabroniono wykorzystywania tej specyfikacji do tworzenia alternatywnego oprogramo- wania dla Flash Playera. Można jej używać przy pisaniu programów tworzących pliki SWF. W wyniku tego wśród narzędzi do tworzenia plików SWF można znaleźć produkty firmy Adobe (Flash Professional, Flash Standard i Flex) jak również kompilatory open source dzia- łające z poziomu wiersza poleceń, jak na przykład MTASC. ActionScript Prawie każda wersja Flasha zawierała obsługę języków skryptowych na jakimś poziomie. W 2005 roku we Flashu 5 wprowadzono nowy język skryptowy ActionScript. ActionScript opiera się na ECMAScript, dzięki czemu przypomina JavaScript. We Flash 7 (znany również jako Flash MX 2004) wprowadzona została wersja 2.0 języka ActionScript, która posiadała właściwości bardziej znane z Javy niż z JavaScript, takie jak dziedziczenie klas, interfejsy i ścisła kontrola typów. ActionScript 3.0 pojawił się wraz z programem Flash Player 9 w 2006 roku i kontynuuje dzieło poprzednika poprzez ulepszenie mechanizmu obsługi wyjątków, dodanie rzeczywistego typowania podczas pracy, nowego API dla XML i obsługi wyrażeń regularnych. Ponadto wokół tego języka skupia się aktywna społeczność programistów. Można tworzyć dokumentacje w stylu Javadoc za pomocą narzędzia as2api i wykonywać testy jednostkowe za pomocą AS2Unit. Odnośniki do tych i innych narzędzi open source można znaleźć na stronie http://www.osflash.org. Flex W marcu 2004 roku firma Macromedia zaprezentowała oprogramowanie Flex, czyli alterna- tywny serwer mający stanowić platformę programistyczną Flasha. W przeciwieństwie do Flash Professional i Flash Standard, korzystających z binarnego formatu plików FLA, które są kompilowane do formatu SWF, Flex korzysta z formatu XML o nazwie MXML i z niego do- konuje kompilacji do formatu SWF. Pliki MXML reprezentują zarówno wygląd, jak i funk- cjonalność aplikacji. Listing13.14 zawiera przykładowy plik MXML. Wynik kompilacji tego pliku widać na rysunku 13.11. Nawet osoby, które nie miały nigdy wcześniej do czynienia z językiem ActionScript, Flashem lub Fleksem, bez trudu odgadną, co robi ten program. 392 | Rozdział 13. Prezentacyjny XML Listing 13.14. Prosty formularz w formacie MXML ?xml version= 1.0 encoding= utf-8 ? mx:Application xmlns:mx= http://www.adobe.com/2006/mxml layout= absolute width= 331 height= 258 mx:Script ![CDATA[ import mx.collections.ArrayCollection; [Bindable] private var listData:ArrayCollection = new ArrayCollection(); private function addText() : void { listData.addItem(text.text); text.text = ; } private function clearList() : void { li
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Java i XML. Wydanie III
Autor:
,

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: