r12-01, ## Documents ##, XML Vademecum profesjonalisty


Rozdział --> 12[Author:T] .
WML, ASP, JSP, serwlety i Perl

W tym rozdziale zajmiemy się kilkoma różnymi tematami, między innymi Bezprzewodowym językiem znaczników (WML, Wireless Markup Language), czyli popularną aplikacją XML przeznaczoną do użycia w telefonach komórkowych, PDA i innych prostych urządzeniach elektronicznych obsługujących protokół WAP (Wireless Application Protocol). WML jest językiem prostym, obecnie można się na niego już w wielu miejscach natknąć, a nowe serwery WAP pojawiają się jak grzyby po deszczu. W tym rozdziale dużo uwagi poświęcimy tworzeniu dokumentów WML i oglądaniu ich w przeglądarkach WML (często nazywanych mikroprzeglądarkami).

W tym rozdziale zajmiemy się także użyciem XML w połączeniu z istniejącymi technologiami działającymi po stronie serwera, takimi jak Active Server Pages (ASP), Java Server Pages (JSP), serwlety Javy i Perl. Wiele firm usiłuje teraz zaistnieć na rynku XML/Internet, wobec czego pojawia się mnóstwo oprogramowania - zajrzyj na stronę Microsoftu pod adres http://msdn.microsoft.com/xml/demos/default.asp, gdzie znajdziesz zestawienie. Jedną z popularnych technologii działających po stronie serwera jest Prosty protokół dostępu do obiektów (SOAP, Simple Object Access Protocol). Jest to faktycznie prosty protokół, który umożliwia wymianę komunikatów w środowisku rozproszonym, przy czym komunikaty zapisane są w XML. SOAP często jest używany do wysyłania poleceń w nagłówkach HTTP, gdyż protokoły zdalnego wywołania metod, takie jak DCOM Microsoftu, nie są ani dość proste, ani dość elastyczne, aby można je było zastosować w Internecie. Trzeba zresztą powiedzieć, że Microsoft jest jednym z głównych promotorów SOAP, co może kazać się zastanowić nad przyszłością DCOM. Nad SOAP także intensywnie pracują IBM i Lotus.

Więcej o SOAP

Trudno jest w Internecie znaleźć informacje o SOAP, gdyż w języku angielskim słowo to oznacza po prostu mydło i wśród odpowiedzi większość dotyczyła będzie czystości i telewizyjnych tasiemców („opery mydlane”). Na początek możesz zatem poszukiwania zacząć od następujących adresów:

Tutaj koniec ramki „Wyróżnienie”

W tym rozdziale przyjrzymy się też tworzeniu dokumentów XML po stronie serwera. W tym celu będziemy pobierać dane z pliku bazy danych db.mdb w zwykłym formacie Microsoft Access. Następnie dane będziemy formatować w XML i przesyłać wynikowe dokumenty do komputerów klienckich. Baza danych jest bardzo prosta, zawiera jedynie imiona ośmiorga studentów wraz z ich oceną wyrażoną literą - tabela 12.1.

Tabela 12.1.
Studenci z pliku db.mdb

Student

Ocena

Ann

C

Mark

B

Ed

A

Frank

A

Ted

A

Mabel

B

Ralph

B

Tom

B

Zaczniemy od zastosowania Obiektów danych ActiveX (ADO, ActiveX Data Objects) zainstalowanych na serwerze przeszukujących bazę danych i tworzących dokument XML wyświetlany za pomocą Active Server Pages.

Programowanie po stronie serwera

W pierwszej części tego rozdziału, kiedy opisywać będziemy programowanie od strony serwera, wiele technologii omówionych zostanie bardzo pobieżnie. Niestety nie sposób omówić tutaj wszystkiego, co potrzebne do programowania Active Server Pages, Java Server Pages, serwletów Javy czy Perla. Jeśli potrzebne będą Ci dodatkowe informacje, musisz poszukać ich gdzie indziej. Kiedy w drugiej części tego rozdziału omawiać będziemy WML, tego rodzaju ograniczeń już nie będzie - zaczniemy omawianie wszystkiego od samego początku.

XML i Active Server Pages

Active Server Pages (ASP) to technologia internetowa działająca po stronie serwera zaproponowana przez Microsoft, która umożliwia tworzenie dokumentów w locie. Dokumenty tworzone są na serwerach takich, jak Microsoft Internet Information Server (IIS); w naszym wypadku wyszukamy imiona w bazie db.mdb i zwrócimy je w postaci następującego dokumentu XML:

<?xml version="1.0" encoding="iso-8859-2"?>

<document>

<student>

Ann

</student>

<student>

Mark

</student>

<student>

Ed

</student>

<student>

Frank

</student>

<student>

Ted

</student>

<student>

Mabel

</student>

<student>

Ralph

</student>

<student>

Tom

</student>

</document>

Najważniejsze w przypadku ASP to upewnić się, że kod wygeneruje dokument XML, gdyż domyślnym typem dokumentu jest HTML. Jeśli opis typu zawartości w nagłówku HTTP nie zawiera informacji, że mamy do czynienia z dokumentem XML, przeglądarka dokumentu tego nie potraktuje jako XML (i zapewne potraktuje go jako HTML). Typ zawartości określa się za pomocą instrukcji <% Response.ContentType %> podając typ application/xml:

<% Response.ContentType = "application/xml" %>

.

.

.

Następnie dodajemy deklarację XML oraz element główny, document:

<% Response.ContentType = "application/xml" %>

<?xml version="1.0" encoding="iso-8859-2"?>

<document>

.

.

.

Teraz potrzebne nam są imiona studentów z bazy db.mdb. Użyjemy do tego protokołu ADO Microsoftu, gdyż ASP przeznaczony jest do pracy na platformach Windows, takich jak IIS. Utworzymy połączenie ADO oraz użyjemy instrukcji SQL pobierającej zestaw wszystkich rekordów:

<% Response.ContentType = "application/xml" %>

<?xml version="1.0" encoding="iso-8859-2"?>

<document>

<%

DIM adoConnect

DIM adoRecordset

Set adoConnect = Server.CreateObject("ADODB.Connection")

adoConnect.open "Provider=Microsoft.Jet.OLEDB.4.0;" _

& "Data Source=C:\xml\db.mdb"

Set adoRecordset = adoConnect.Execute("SELECT * FROM Students")

.

.

.

Teraz pozostało nam już tylko zorganizować pętlę po wszystkich rekordach i utworzyć w każdym przejściu element XML student:

<% Response.ContentType = "application/xml" %>

<?xml version="1.0" encoding="iso-8859-2"?>

<document>

<%

DIM adoConnect

DIM adoRecordset

Set adoConnect = Server.CreateObject("ADODB.Connection")

adoConnect.open "Provider=Microsoft.Jet.OLEDB.4.0;" _

& "Data Source=C:\xml\db.mdb"

Set adoRecordset = adoConnect.Execute("SELECT * FROM Students")

Do While Not adoRecordset.EOF

Response.Write "<student>" + adoRecordset("Name") + "</student>"

adoRecordset.MoveNext

Loop

adoRecordset.Close

set adoRecordset = Nothing

%>

</document>

W ten sposób utworzony zostanie potrzebny nam dokument XML, co pokazano na rysunku 12.1.

Rysunek 12.1.

Tworzenie dokumentu XML za pomocą ASP

Nie mogę wykonać rysunku, gdyż wymaga IIS. Rysunek można zeskanować z książki (dlatego właśnie nie zmieniłem znaczników document na dokument ani nie zmieniałem imion na polskie odpowiedniki.

Rysunek powinien być taki jak poniżej, ale inny powinien być pasek tytułu (jak w książce); to samo dotyczy rysunków 12.2 i 12.3.

0x01 graphic

Zwróć uwagę na to, że następne rysunki będą bardzo podobne do powyższego; aby zauważyć różnice między nimi, dokładnie przyglądaj się paskom tytułu przeglądarki.

XML i serwlety Javy

Serwlety Javy mają być dla serwerów sieciowych tym, czym są aplety Javy dla komputerów klienckich. Serwletów można użyć do tworzenia dokumentów sieciowych na różnych serwerach. Aby tworzyć serwlety, możesz załadować Java Servlet Development Kit (JSDK) ze strony java.sun.com (w chwili pisania strona główna poświęcona serwletom to http://java.sun.com/products/servlet/index.html) i tworzyć serwlety za pomocą klas z archiwów servlet.jarserver.jar.

Aby odczytać z bazy danych db.mdb imiona studentów, użyjemy pakietu JDBC (Java Database Connectivity) łącząc się z db.mdb po zarejestrowaniu bazy danych jako źródła danych ODBC. Kiedy wyszukamy już imiona studentów, umieścimy je w dokumencie XML i dokument ten odeślemy do klienta.

Znów najważniejsze jest stworzenie dokumentu XML, a nie domyślnego HTML. W przypadku serwletów dokument XML tworzy się za pomocą metody setContentType klasy ServletResponse podając jako typ zawartości application/xml:

import java.net.*;

import java.sql.*;

import java.awt.*;

import java.awt.event.*;

import java.io.*;

import javax.servlet.*;

public class xml extends GenericServlet

{

public void service(ServletRequest request, ServletResponse

response) throws ServletException, IOException

{

response.setContentType("application/xml");

.

.

.

Następnie zwracamy klientowi deklarację XML i element główny:

import java.net.*;

import java.sql.*;

import java.awt.*;

import java.awt.event.*;

import java.io.*;

import javax.servlet.*;

public class xml extends GenericServlet

{

public void service(ServletRequest request, ServletResponse

response) throws ServletException, IOException

{

response.setContentType("application/xml");

PrintWriter printwriter = response.getWriter();

printwriter.println("<?xml version=\"1.0\" encoding=\"iso-8859-2\"?>");

printwriter.println("<document>");

.

.

.

Teraz możemy użyć JDBC do utworzenia zbioru wyników zawierającego wszystkie rekordy z bazy db.mdb:

import java.net.*;

import java.sql.*;

import java.awt.*;

import java.awt.event.*;

import java.io.*;

import javax.servlet.*;

public class xml extends GenericServlet

{

public void service(ServletRequest request, ServletResponse

response) throws ServletException, IOException

{

response.setContentType("application/xml");

PrintWriter printwriter = response.getWriter();

printwriter.println("<?xml version=\"1.0\" encoding=\"iso-8859-2\"?>");

printwriter.println("<document>");

try

{

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

connection = DriverManager.getConnection(

"jdbc:odbc:students", "Steve", "password");

statment = connection.createStatement();

String SQL = "SELECT Name FROM Students";

ResultSet resultset = statement.executeQuery(SQL);

.

.

.

Teraz już tylko musimy utworzyć pętlę po zbiorze wyników, w której pobierzemy imiona studentów i odeślemy je do klienta zamknięte elementami student:

import java.net.*;

import java.sql.*;

import java.awt.*;

import java.awt.event.*;

import java.io.*;

import javax.servlet.*;

public class xml extends GenericServlet

{

public void service(ServletRequest request, ServletResponse

response) throws ServletException, IOException

{

response.setContentType("application/xml");

PrintWriter printwriter = response.getWriter();

printwriter.println("<?xml version=\"1.0\" encoding=\"iso-8859-2\"?>");

printwriter.println("<document>");

try

{

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

connection = DriverManager.getConnection(

"jdbc:odbc:students", "Steve", "password");

statment = connection.createStatement();

String SQL = "SELECT Name FROM Students";

ResultSet resultset = statement.executeQuery(SQL);

while (resultset.next()) {

printwriter.println("<student> +

resultset.getString(1) + "</student>");

}

}

catch(Exception e) {}

printwriter.println("</document>");

printwriter.close();

}

}

I to już wszystko. Wynik działania serwleta pokazano na rysunku 12.2, gdzie do klienta zwrócony został ten sam dokument, co w przypadku omawianego poprzednio ASP.

Rysunek 12.2.

Tworzenie dokumentów za pomocą serwletów Javy

Nie mogę wykonać rysunku, gdyż wymaga serwera HTTP/WWW. Rysunek można zeskanować z książki (dlatego właśnie nie zmieniłem znaczników document na dokument ani nie zmieniałem imion na polskie odpowiedniki.

Kolejną zdobywającą popularność technologią z wykorzystaniem Javy jest użycie Java Server Pages, co omówiono w następnym podrozdziale.

Java Server Pages

Java Server Pages (JSP) to reakcja środowiska Javy na Active Server Pages Microsoftu. JSP umożliwia tworzenie dynamicznych stron sieciowych przez uruchamianie skryptów na serwerze. Dokładny opis JSP znajdziesz na stronie http://java.sun.com/products/jsp/index.html. JSP używa się podobnie jak ASP.

W tym przykładzie użyjemy serwera Apache Tomcat będącego oficjalnie wzorcową implementacją JSP (a także serwletów Javy). Serwer ten możesz „ściągnąć” ze strony http://jakarta.apache.org/tomcat/.

Utworzymy taki sam dokument XML jak w dwóch poprzednich przykładach na podstawie danych z bazy db.mbd. Jako że powtórnie korzystamy z Javy, znów użyjemy do sięgania do bazy danych JDBC.

Znów na początek musimy zapewnić prawidłową interpretację typu dokumentu, aby użyty został typ application/xml, a nie domyślny HTML. W JSP korzysta się z atrybutu contentType:

<%@ page language="java" contentType="application/xml"

import="java.sql.*" %>

.

.

.

Znów inicjalizujemy sterownik JDBC:

<%@ page language="java" contentType="application/xml"

import="java.sql.*" %>

<% Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); %>

.

.

.

Następnie wstawiamy deklarację XML oraz element główny:

<%@ page language="java" contentType="application/xml"

import="java.sql.*" %>

<% Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); %>

<?xml version="1.0" encoding="iso-8859-2"?>

<document>

.

.

.

Teraz pobieramy zbiór wyników z JDBC - rekordy wszystkich studentów zwrócone przez zapytanie SQL:

<%@ page language="java" contentType="application/xml"

import="java.sql.*" %>

<% Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); %>

<?xml version="1.0" encoding="iso-8859-2"?>

<document>

<%

Connection connection = DriverManager.getConnection(

"jdbc:odbc:students", "Steve", "password");

Statement statement = connection.createStatement();

ResultSet resultset =

statement.executeQuery("select * from Students"); %>

.

.

.

Teraz już pozostało tylko utworzenie pętli po studentach i wygenerowanie elementów student:

<%@ page language="java" contentType="application/xml"

import="java.sql.*" %>

<% Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); %>

<?xml version="1.0" encoding="iso-8859-2"?>

<document>

<%

Connection connection = DriverManager.getConnection(

"jdbc:odbc:students", "Steve", "password");

Statement statement = connection.createStatement();

ResultSet resultset =

statement.executeQuery("select * from Students"); %>

<% while(resultset.next()){ %>

<student> <%= resultset.getString() %> </student>

<% } %>

<document>

Na rysunku 12.3 pokazano wyniki działania skryptu JSP. Jak widać, wyniki wcale nie są gorsze niż w przypadku zastosowania ASP, zresztą znam bardzo wielu programistów XML, którzy do udostępniania dokumentów XML wolą właśnie JSP zamiast ASP, gdyż praca z XML w Javie jest niejako naturalna, o czym można było się przekonać w rozdziałach 8 i 9 niniejszej książki.

Rysunek 12.3.

Tworzenie dokumentów XML za pomocą Java Server Pages

Rysunek wymaga serwera Tomcat, który w mojej konfiguracji nie działa. Rysunek można zeskanować z książki (dlatego właśnie nie zmieniłem znaczników document na dokument ani nie zmieniałem imion na polskie odpowiedniki.

XML i Perl

Praktyczny język pobierania danych i raportowania (PERL, Practical Extraction and Reporting Language) przez długi czas był podstawowym narzędziem do programowania serwerów i podstawą CGI. Język ten też szybko znalazł zastosowanie do obsługi XML, nietrudno byłoby na ten temat napisać osobną książkę.

Moduły Perla rozproszone są po  sieciowym archiwum Perla (CPAN, Comprehensive Perl Archive Network) dostępnym pod adresem www.cpan.org, wiele z tych modułów służy do obsługi XML (autor doliczył się 156 takich modułów). W tabeli 12.2 zestawiono wybrane moduły wraz z ich opisem podawanym w witrynie CPAN.

Tabela 12.2.
Moduły Perla do obsługi XML wraz z opisem z CPAN

Moduł

Opis

Apache::AxKit::XMLFinder

Wykrywa pliki XML

Apache::MimeXML

--> „Nasłuchiwacz” typów kodowania mime mod_perl wyszukujący pliki XML.[Author:T]

Boulder::XML

Procedury formatowania XML strumieni wejściowo-wyjściowych --> Boulder[Author:T] .

Bundle::XML

Pakiet instalujący wszystkie moduły powiązane z XML.

CGI::XMLForm

Rozszerzenie CGI.pm odczytujące/generujące sformatowany XML.

Data::DumpXML

Zapisuje dowolne struktury danych jako XML.

DBIx::XML_RDB

Rozszerzenie Perla służące do generacji XML na podstawie istniejących źródeł danych DBI.

GoXML::XQI

Rozszerzenie Perla służące do obsługi interfejsu XML Query w xqi.goxml.com.

Mail::XML

Dodaje do Mail::Internet metodę toXML().

MARC::XML

Podklasa MARC.pm zapewniająca obsługę XML.

PApp::XML

Sekcje pxml i inne.

XML::Catalog

Rozwija identyfikatory publiczne i przekształca identyfikatory systemowe.

XML::CGI

Rozszerzenie Perla służące do konwersji zmiennych CGI.pm z/na XML.

XML::Checker

Moduł Perla służący do walidacji XML.

XML::Checker::Parser

XML::Parser walidujący podczas parsowania dokumentów.

XML::DOM

Moduł Perla służący do tworzenia struktur dokumentów zgodnych z DOM Level 1.

XML::DOM::NamedNodeMap

Interfejs tablic haszujących dla XML::DOM.

XML::DOM::NodeList

Listy węzłów używane przez XML::DOM.

XML::DOM::PerlSAX

Stara nazwa XML::Handler::BuildDOM.

XML::DOM::ValParser

XML::DOM::Parser walidujący w czasie parsowania.

XML::Driver::HTML

Sterownik SAX przeznaczony dla HTML nie sformułowanego poprawnie w rozumieniu XML.

XML::DT

Pakiet przekształcania XML na napisy.

XML::Edifact

Moduł Perla obsługujący komunikaty XML::Edifact.

XML::Encoding

Moduł Perla do parsowania map kodowania XML.

XML::ESISParser

Parser PerlSAX używający nsgmls.

XML::Filter::DetectWS

Filtr PerlSAX wykrywający białe znaki, które mogą zostać pominięte.

XML::Filter::Hekeln

Edytor strumieniowy SAX.

XML::Filter::Reindent

Uzupełnia białe znaki, aby uzyskać dokument XML w ładnej graficznie postaci.

XML::Filter::SAXT

Replikuje zdarzenia SAX kilku procedurom obsługi zdarzeń SAX.

XML::Generator

Rozszerzenie Perla do generacji XML.

XML::Grove

Perlopodobne obiekty XML.

XML::Grove::AsCanonXML

Wyprowadza obiekty XML w postaci kanonicznego XML.

XML::Grove::AsString

Wyprowadza treść obiektów XML jako napisy.

XML::Grove::Builder

Procedura obsługi PerlSAX do tworzenia XML::Grove.

XML::Grove::Factory

Upraszcza tworzenie obiektów XML::Grove.

XML::Grove::Path

Zwraca obiekt z podanej ścieżki.

XML::Grove::PerlSAX

Interfejs zdarzeń PerlSAX dla obiektów XML.

XML::Grove::Sub

Uruchamia procedurę filtrującą na dokumencie.

XML::Grove::Subst

Podstawia wartości do szablonu.

XML::Handler::BuildDOM

Procedura obsługi PerlSAX tworząca struktury dokumentu XML::DOM.

XML::Handler::CanonXMLWriter

Wyprowadza dane w postaci kanonicznego XML.

XML::Handler::Composer

Generuje, drukuje i zapisuje XML.

XML::Handler::PrintEvents

Drukuje zdarzenia PerlSAX (przydatne przy usuwaniu błędów w programach).

XML::Handler::PyxWriter

Przekształca zdarzenia PerlSAX na ESIS nsgmls.

XML::Handler::Sample

Elementarna procedura obsług zdarzeń PerlSAX.

XML::Handler::Subs

Klasa bazowa procedury obsługi zdarzeń PerlSAX przeznaczona do wywoływania procedur zdefiniowanych przez użytkownika.

XML::Handler::XMLWriter

Procedura obsługi zdarzeń PerlSAX przeznaczona do wypisania czytelnego dla człowieka XML.

XML::Handler::YAWriter

Kolejny PerlSAX XML Writer 0.15.

XML::Node

Oparte na obsłudze węzłów parsowanie XML; uproszczony interfejs do XML.

XML::Parser

Moduł Perla do parsowania dokumentów XML.

XML::Parser::Expat

Parser expat Jamesa Clarka umożliwiający dostęp niskiego poziomu.

XML::Parser::PerlSAX

Parser PerlSAX używający XML::Parser.

XML::Parser::PyxParser

Konwertuje ESIS nsgmls lub Pyxie na PerlSAX.

XML::PatAct::Amsterdam

Moduł procedur do uproszczonych arkuszy stylów.

XML::PatAct::MatchName

Moduł wzorców do dobierania nazw elementów.

XML::PatAct::ToObjects

Moduł procedur do tworzenia obiektów Perla.

XML::PYX

Generator XML na PYX.

XML::QL

Język zapytań XML.

XML::RegExp

Wyrażenia regularne dla nazw XML.

XML::Registry

Moduł Perla ładujący i zapisujący rejestry XML.

XML::RSS

Tworzy i aktualizuje pliki RSS.

XML::SAX2Perl

Przekształca metody PerlSAX na metody w stylu Java/CORBA.

XML::Simple

Elementarny interfejs API do czytania i zapisywania XML (szczególnie plików konfiguracyjnych).

XML::Stream

Tworzy połączenie XML i parsuje dane zwrotne.

XML::Stream::Namespace

Obiekt ułatwiający definiowanie przestrzeni nazw.

XML::Template

Instancja szablonu Perl XML.

XML::Twig

Moduł Perla przeznaczony do przetwarzania bardzo dużych dokumentów XML jako drzewek.

XML::UM

Przekształca napisy UTF-8 na dowolne kodowanie obsługiwane przez XML::Encoding.

XML::Writer

Rozszerzenie Perla przeznaczone do zapisywania dokumentów XML.

XML::XPath

Zestaw modułów do parsowania i interpretacji XPath.

XML::XPath::Boolean

Logiczne wartości prawdy i fałszu.

XML::XPath::Builder

Procedura obsługi zdarzeń SAX do tworzenia drzewka XPath.

XML::XPath::Literal

Proste wartości tekstowe.

XML::XPathNode

Wewnętrzna reprezentacja węzła.

XML::XPath::NodeSet

Lista węzłów dokumentu XML.

XML::XPath::Number

Proste wartości numeryczne.

XML::XPath::PerlSAX

Generator zdarzeń PerlSAX.

XML::XPath::XMLParser

Domyślna klasa parsowania XML dająca drzewo węzłów.

XML::XQL

Moduł Perla do zadawania zapytań dotyczących drzewiastych struktur XML za pomocą XQL.

XML::XQL::Date

Dodaje typ XQL::Node służący do reprezentacji i porównywania wartości daty i czasu.

XML::XQL::DOM

Dodaje do węzłów XML::DOM obsługę XQL.

XML::XSLT

Moduł Perla do przetwarzania XSLT.

XMLNews::HTMLTemplate

Moduł do konwersji NITF na HTML.

XMLNews::Meta

Moduł do odczytu i zapisu plików metadanych XMLNews.

Większość modułów Perl z tabeli 12.2 trzeba przed użyciem ściągnąć i zainstalować (proces ten jest żmudny, choć prosty; zarówno w Windows, jak i w UNIXie istnieją narzędzia zarządzające ładowaniem i instalacją). Standardowa dystrybucja Perla zawiera wbudowaną częściową obsługę XML, na przykład moduł XML::Parser.

Oto przykład użycia modułu XML::Parser. W tym wypadku parsować będziemy dokument XML i za pomocą Perla go wydrukujemy. Moduł XML::Parser może obsłużyć wywołania zwrotne, czyli wywoływać podprocedury na początku elementu, przy treści i przy końcu elementu. Oto jak przygotowujemy takie wywołania wiążąc je z procedurami obsługi zdarzeń start_handler, char_handler oraz end_handler tworząc nowy obiekt parsera $parser:

use XML::Parser;

$parser = new XML::Parser(Handlers => {Start => \&start_handler,

End => \&end_handler,

Char => \&char_handler});

.

.

.

Teraz potrzebny jest nam dokument XML, który będziemy parsować. Użyjemy dokumentu spotkania.xml z rozdziału 5:

<?xml version="1.0" encoding="iso-8859-2"?>

<SPOTKANIA>

<SPOTKANIE TYP="nieformalne">

<PRZEWODNICZĄCY>Ted Bond</PRZEWODNICZĄCY>

<TYTUŁ>XML w praktycznych zastosowaniach</TYTUŁ>

<NUMER>2079</NUMER>

<TEMAT>XML</TEMAT>

<DATA>6/1/2002</DATA>

<OSOBY>

<OSOBA STATUS="obecny">

<IMIĘ>Edward</IMIĘ>

<NAZWISKO>Samson</NAZWISKO>

</OSOBA>

<OSOBA STATUS="nieobecny">

<IMIĘ>Ernestyna</IMIĘ>

<NAZWISKO>Johnson</NAZWISKO>

</OSOBA>

<OSOBA STATUS="obecny">

<IMIĘ>Betty</IMIĘ>

<NAZWISKO>Richardson</NAZWISKO>

</OSOBA>

</OSOBY>

</SPOTKANIE>

</SPOTKANIA>

Metoda parsefile obiektu $parser umożliwia nam parsowanie tego dokumentu:

use XML::Parser;

$parser = new XML::Parser(Handlers => {Start => \&start_handler,

End => \&end_handler,

Char => \&char_handler});

$parser->parsefile('spotkania.xml');

.

.

.

Teraz wystarczy już tylko utworzyć podprocedury start_handler, char_handler i end_handler. Zaczniemy od pierwszej z nich, która wywoływana jest przy napotkaniu początku elementu XML. Nazwa elementu zapisywana jest w pierwszej komórce standardowej tablicy Perla --> $_[Author:T] zawierającej argumenty podprocedur. Element ten wraz ze znacznikiem początkowym możemy wyświetlić następująco:

use XML::Parser;

$parser = new XML::Parser(Handlers => {Start => \&start_handler,

End => \&end_handler,

Char => \&char_handler});

$parser->parsefile('spotkania.xml');

sub start_handler

{

print "<$_[[1]>\n";

}

.

.

.

Podobnie drukujemy znacznik końcowy w podprocedurze end_handler:

use XML::Parser;

$parser = new XML::Parser(Handlers => {Start => \&start_handler,

End => \&end_handler,

Char => \&char_handler});

$parser->parsefile('spotkania.xml');

sub start_handler

{

print "<$_[[1]>\n";

}

sub end_handler

{

print "</$_[1]>\n";

}

.

.

.

Z kolei dane elementu możemy wydrukować w podprocedurze char_handler, pominiemy tylko zbędne spacje:

use XML::Parser;

$parser = new XML::Parser(Handlers => {Start => \&start_handler,

End => \&end_handler,

Char => \&char_handler});

$parser->parsefile('spotkania.xml');

sub start_handler

{

print "<$_[[1]>\n";

}

sub end_handler

{

print "</$_[1]>\n";

}

sub char_handler

{

if(index($_[1], " ") < 0 && index($_[1], "\n") < 0){

print "$_[1]\n";

}

}

Program jest już gotowy, uruchomienie takiego skryptu Perla da wynik taki, jak pokazano poniżej:

<SPOTKANIA>

<SPOTKANIE>

<PRZEWODNICZĄCY>

Ted Bond

</PRZEWODNICZĄCY>

<TYTUŁ>

XML w praktycznych zastosowaniach

</TYTUŁ>

<NUMER>

2079

</NUMER>

<TEMAT>

XML

</TEMAT>

<DATA>

6/1/2002

</DATA>

<OSOBY>

<OSOBA>

<IMIĘ>

Edward

</IMIĘ>

<NAZWISKO>

Samson

</NAZWISKO>

</OSOBA>

<OSOBA>

<IMIĘ>

Ernestyna

</IMIĘ>

<NAZWISKO>

Johnson

</NAZWISKO>

</OSOBA>

<OSOBA>

<IMIĘ>

Betty

</IMIĘ>

<NAZWISKO>

Richardson

</NAZWISKO>

</OSOBA>

</OSOBY>

</SPOTKANIE>

</SPOTKANIA>

Jak zapewne zauważyłeś, parsowanie dokumentu i definiowanie funkcji zwrotnych w Perlu bardzo przypomina to, co robiliśmy w rozdziale 9, kiedy omawialiśmy interfejs SAX.

Teraz przyjrzymy się udostępnianiu dokumentów XML przez skrypty Perla. Niestety, Perl nie zawiera tak rozbudowanego protokołu komunikacji z bazą danych jak JDBC wraz z odpowiednim ODBC lub ASP z ADO. Obsługa baz danych wbudowana w Perl oparta jest na plikach DBM, które mają strukturę --> haszowanych[Author:T] baz danych. Możesz też oczywiście zainstalować moduły Perla, które pozwalają obsługiwać wszelakie bazy danych, od ODBC po Oracle.

W naszym przypadku użyjemy skryptu Perla, który umożliwi podanie klucza (na przykład warzywo) wraz z wartością (na przykład brokuły), taka para będzie przechowywana w bazie danych w formacie NDBM domyślnie obsługiwanym przez Perla. Baza danych znajdować się będzie na serwerze. Kiedy użytkownik poda klucz na stronie, nasz program wyszuka w bazie danych odpowiednie rekordy i jeśli jakieś znajdzie, zwróci klucze wraz z ich wartościami. Jeśli na przykład wpiszesz jako klucz warzywo, jako wartość brokuły, taka para zostanie dopisana do bazy danych. Kiedy następnie wyszukiwać będziesz klucza warzywo, skrypt zwróci klucz wraz z odpowiadającą mu wartością w postaci dokumentu XML:

<?xml version="1.0" encoding="iso-8859-2"?>

<dokument>

<klucz>warzywo</klucz>

<wartość>brokuły</wartość>

</dokument>

Na rysunku 12.4 pokazano wyniki działania skryptu CGI. Aby dodać do bazy nowy rekord, wpisuje się klucz i odpowiadającą mu wartość, następnie klika przycisk Dodaj. Na rysunku 12.4 właśnie dodawana jest wartość brokuły z kluczem warzywo.

Rysunek 12.4.

Perlowy skrypt CGI jako program obsługi bazy danych

0x01 graphic

Aby pobrać z bazy danych wartość, wpisuje się w pole szukany klucz i klika przycisk Szukaj. Baza danych jest przeszukiwana, a wyniki w postaci dokumentu XML są odsyłane do klienta, co pokazano na rysunku 12.5. W tym wypadku wyszukiwany był klucz warzywo. Wprawdzie uzyskany dokument XML wyświetlany jest w przeglądarce, ale dość prosto jest za pomocą wtyczek internetowych (Internet sockets) Perla taki dokument obsłużyć także bez przeglądarki.

Rysunek 12.5.

Dokument XML generowany przez skrypt Perl

Rysunek został wykonany inną metodą, bezwzględnie konieczne jest usunięcie przez grafika z paska tytułu nazwy pliku i pozostawienie tam tylko po lewo napisu „Microsoft Internet Explorer”!

0x01 graphic

W tym skrypcie użyjemy standardowo do Perla dołączanego modułu CGI.pm. Zaczniemy od utworzenia strony sieciowej z rysunku 12.4 zawierającej między innymi potrzebne kontrolki HTML:

#!/usr/local/bin/perl

use Fcntl;

use NDBM_File;

use CGI;

$co = new CGI;

if(!$co->param()) {

print $co->header,

$co->start_html('Przykład funkcji CGI'),

$co->center($co->h1('Przykład bazy danych CGI')),

$co->hr,

$co->b("Dodanie pary klucz/wartość do bazy danych..."),

$co->start_form,

"Klucz dodawany do bazy: ",

$co->textfield(-name=>'key', -default=>'', -override=>1),

$co->br,

"Wartość dodawana do bazy danych: ",

$co->textfield(-name->'value', -default=>'', -override=>1),

$co-br,

$co->hidden(-name=>'type', -value=>'write', -override=>1),

$co->br,

$co->center(

$co->submit('Dodaj'),

$co>reset

),

$co->end_form,

$co-hr,

$co->b("Wyszukiwanie wartości w bazie danych..."),

$co->start_form,

"Szukany klucz: ", $co->textfield(-name=>'key', -default=>'', -override=>1),

$co->br,

$co->hidden(-name=>'type',-value=>'read', -override=>1),

$co->br,

$co->center(

$co->submit('Wyszukanie wartości'),

$co->reset

),

$co->end_form,

$co->hr;

print$co->end_html;

}

.

.

.

Ten skrypt CGI utworzy dwa formularze HTML: jeden do zapisywania par klucz/wartość do bazy, drugi do wyszukiwania wartości odpowiadającej kluczowi. Nie wskazaliśmy, gdzie dane z formularzy mają być przesyłane, wobec czego zostaną odesłane do tego samego skryptu. To, czy skrypt otrzymał przy wywołaniu jakieś dane do przetwarzania, możemy sprawdzić sprawdzając wartość zwróconą przez metodę CGI.pm param. Jeśli otrzymamy wartość true, jakieś dane już czekają na przetwarzanie.

Zwracany przez ten skrypt dokument jest dokumentem XML, a nie domyślnym HTML, zatem konieczne jest wskazanie tego w nagłówku HTTP, w opisie typu zawartości. Używamy metody header, jej parametrowi type przypisujemy wartość application/xml. Oto fragment kodu skryptu znajdujący się bezpośrednio za kodem dotąd napisanym:

if($co->param()) {

print $co->header(-type=>"application/xml");

print "<?xml version=\"1.0\" encoding=\"iso-8859-2\"?>";

print "<dokument>";

.

.

.

Rozdzieliliśmy dwa formularze HTML dodając dla rozróżnienia zmienną type. Jeśli zmienna ta ma wartość write, podane przez użytkownika dane mają być dopisane do bazy danych:

if($co->param()) {

print $co->header(-type=>"application/xml");

print "<?xml version=\"1.0\" encoding=\"iso-8859-2\"?>";

print "<dokument>";

if($co->param('type') eq 'write') {

tie %dbhash, "NDBM_File", "dbdata", O_RDWR|O_CREATE, 0644;

$key = $co->param('key');

$value = $co->param('value');

$dbhash{$key} = $value;

untie %dbhash;

if ($!) {

print "Wystąpil błąd: $!";

} else {

print "$key=>$value zostały zapisane w bazie danych";

}

}

.

.

.

}

W przeciwnym wypadku szukamy w bazie danych podanego klucza i zwracamy klucz wraz z wartością w postaci dokumentu XML:

if($co->param()) {

print $co->header(-type=>"application/xml");

print "<?xml version=\"1.0\" encoding=\"iso-8859-2\"?>";

print "<dokument>";

if($co->param('type') eq 'write') {

tie %dbhash, "NDBM_File", "dbdata", O_RDWR|O_CREATE, 0644;

$key = $co->param('key');

$value = $co->param('value');

$dbhash{$key} = $value;

untie %dbhash;

if ($!) {

print "Wystąpil błąd: $!";

} else {

print "$key=>$value zostały zapisane w bazie danych";

}

} else {

tie %dbhash, "NDBM_File", "dbdata", O_RDWR|O_CREAT, 0644;

$key = $co->param('key');

$value = $dbhash{$key};

$value = $dbhash{$key};

print "<klucz>";

print $key;

print "</klucz>";

print "<wartość>;

print $value;

print "</wartość>;

if ($value) {

if ($!) {

print "Wystąpił błąd: $!";

}

} else {

print "Brak wartości dla podanego klucza";

}

untie %dbhash

}

print "</dokument>";

}

W ten sposób utworzyliśmy skrypt Perl, który umożliwia zapisywanie danych w bazie i odczytywanie ich w postaci XML. Na wydruku 12.1 pokazano pełny kod programu, dbxml.cgi. Oczywiście samodzielne robienie wszystkiego jest trudnym zadaniem - jeśli zamierzasz zająć się obsługą XML w Perlu, powinieneś przyjrzeć się dokładniej licznym modułom Perla do obsługi XML udostępnionym w CPAN.

Wydruk 12.1.
dbxml.cgi

#!/usr/local/bin/perl

use Fcntl;

use NDBM_File;

use CGI;

$co = new CGI;

if(!$co->param()) {

print $co->header,

$co->start_html('Przykład funkcji CGI'),

$co->center($co->h1('Przykład bazy danych CGI')),

$co->hr,

$co->b("Dodanie pary klucz/wartość do bazy danych..."),

$co->start_form,

"Klucz dodawany do bazy: ",

$co->textfield(-name=>'key', -default=>'', -override=>1),

$co->br,

"Wartość dodawana do bazy danych: ",

$co->textfield(-name->'value', -default=>'', -override=>1),

$co-br,

$co->hiddent(-name=>'type', -value=>'write', -override=>1),

$co->br,

$co->center(

$co->submit('Dodaj'),

$co>reset

),

$co->end_form,

$co-hr,

$co->b("Wyszukiwanie wartości w bazie danych..."),

$co->start_form,

"Szukany klucz: ", $co->textfield(-name=>'key', -default=>'', -override=>1),

$co->br,

$co->hidden(-name=>'type',-value=>'read', -override=>1),

$co->br,

$co->center(

$co->submit('Wyszukanie wartości'),

$co->reset

),

$co->end_form,

$co->hr;

print$co->end_html;

}

if($co->param()) {

print $co->header(-type=>"application/xml");

print "<?xml version=\"1.0\" encoding=\"iso-8859-2\"?>";

print "<dokument>";

if($co->param('type') eq 'write') {

tie %dbhash, "NDBM_File", "dbdata", O_RDWR|O_CREATE, 0644;

$key = $co->param('key');

$value = $co->param('value');

$dbhash{$key} = $value;

untie %dbhash;

if ($!) {

print "Wystąpil błąd: $!";

} else {

print "$key=>$value zostały zapisane w bazie danych";

}

} else {

tie %dbhash, "NDBM_File", "dbdata", O_RDWR|O_CREAT, 0644;

$key = $co->param('key');

$value = $dbhash{$key};

$value = $dbhash{$key};

print "<klucz>";

print $key;

print "</klucz>";

print "<wartość>;

print $value;

print "</wartość>;

if ($value) {

if ($!) {

print "Wystąpił błąd: $!";

}

} else {

print "Brak wartości dla podanego klucza";

}

untie %dbhash

}

print "</dokument>";

}

Bezprzewodowy język znaczników

Jedną z aplikacji XML skupiających powszechną uwagę jest Bezprzewodowy język znaczników WML (Wireless Markup Language). WML i związany z nim protokół WAP przeznaczone są do obsługi przenośnych urządzeń takich jak telefony komórkowe, PDA i inne urządzenia o ograniczonych możliwościach technicznych. WML to język z mocno ograniczoną składnią, który łatwo jest w takich urządzeniach zastosować, programy ten język obsługujące w urządzeniach często nazywa się mikroprzeglądarkami.

Oto lista wybranych zasobów na temat WML:

W tabeli 12.3 zestawiono elementy WML wraz z ich atrybutami.

Tabela 12.3.
Elementy WML

Element

Realizowana funkcja

Atrybuty

a

hiperłącze

class href id title xml:lang

access

element dostępu

class domain id path

anchor

pełni rolę zakładki

class id title xml:lang

b

pogrubienie

class id xml:lang

big

powiększony tekst

class id xml:lang

br

koniec wiersza

class id xml:lang

card

tworzy kartę

class do id label name newcontext onenterbackward onenterforward ontimer optional ordered title type xml:lang

em

akcentuje tekst

class id xml:lang

fieldset

zestaw pól

class id title xml:lang

go

nawigacja

accept-charset class href id method sendreferer

head

część nagłówkowa

class id

i

kursywa

class id xml:lang

img

obsługa obrazków

align alt class height hspace id localsrc src vspace width xml:lang

input

pole tekstowe

class emptyok format id maxlength name size tabindex title type value xml:lang

meta

zawiera metadane

class content forua http-equiv id name scheme

noop

brak operacji (pomocniczy)

class id

onevent

obsługa zdarzenia

class id type

optgroup

tworzy grupę opcji

class id title xml:lang

option

opcja

class id onpick title value xml:lang

p

akapit

align mode xml:lang class id

postfield

przesyła pole danych

class id name value

prev

przejście do poprzedniej karty

-

refresh

obsługa odświeżania

class id

select

wybiera kontrolkę

class id iname ivalue multiple name tabindex title value xml:lang

setvar

nadaje zmiennej wartość

class id name value

small

tekst pomniejszony

class id xml:lang

strong

wyróżnienie tekstu

class id xml:lang

table

tworzy tabelę

align class columns id title xml:lang

td

komórka danych tabeli

class id xml:lang

template

szablon

class id onenterbackward onenterforward ontimer

timer

tworzy zegar

class id name value

tr

wiersz tabeli

class id

u

podkreślenie

class id xml:lang

Oprócz tego WML obsługuje następujące encje znakowe:

&amp;

symbol &

&apos;

apostrof (')

&gt;

znak większości (>)

&lt;

znak mniejszości (<)

&nbsp;

spacja nierozdzielająca (' ')

&quot;

cudzysłów (")

&shy;

łącznik opcjonalny (-)

W kolejnych punktach używać będziemy popularnej przeglądarki WML Apache Klondike, którą można pobrać z witryny www.apachesoftware.com. Przeglądarka ta jest dobrze opracowana i warto ją zainstalować.

Zaczynamy poznawać WML

Mikroprzeglądarki nie mają zbyt wielkich wyświetlaczy, wobec czego dokumenty WML dzieli się na karty, za każdym razem wyświetlana jest właśnie jedna taka karta. Dokument WML nazywany talią to zestaw takich kart. Talia ujęta jest w element wml, natomiast poszczególne karty w elementy card. Kiedy mikroprzeglądarka odczytuje dokument WML, od razu odczytuje całą talię mimo że na raz pokazywana jest pojedyncza karta.

Dokument WML zaczyna się deklaracją XML:

<?xml version="1.0"?>

.

.

.

W WML (podobnie jak w XHTML) używa się znacznika <!DOCTYPE> z formalnym identyfikatorem publicznym, tyle tylko, że ciałem standaryzacyjnym jest WAP Forum, a nie W3C:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

.

.

.

Dokument czyli talia zaczyna się znacznikiem <wml>:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

.

.

.

</wml>

Do tworzenia poszczególnych kart w talii używa się elementu card; naszej karcie nadamy identyfikator Card1 i tytuł Pierwszy przykład WML (tytuł pokazuje się w pasku tytułowym Klondike):

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Pierwszy przykład WML">

.

.

.

</card>

</wml>

W dokumentach WML komentarze wstawia się tak jak w zwykłym XML:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Pierwszy przykład WML">

<!-- To jest komentarz. -->

.

.

.

</card>

</wml>

Każda karta zawierać musi element p (czyli akapit), w naszym przykładzie w tym elemencie umieścimy krótkie pozdrowienie:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Pierwszy przykład WML">

<!-- To jest komentarz. -->

<p>

Pozdrowienia z WML.

</p>

</card>

</wml>

I tak wygląda nasz pierwszy dokument. Na rysunku pokazano ten przykład w przeglądarce Klondike.

Rysunek 12.6.

Pierwszy dokument WML

0x01 graphic

Wyrównanie tekstu

Element p ma atrybut align, który jest przydatny do określania sposobu wyrównania tekstu. Atrybutowi temu można przypisać jedną z wartości left, center lub right. Istnieje też atrybut mode, którego można użyć, czy tekst ma być zawijany, czy też nie - odpowiednio wartości wrap lub nowrap. W poniższym przykładzie pokazano wyrównanie tekstu za pomocą omawianych atrybutów:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Wyrównanie tekstu">

<p align="center">Wyrównanie tekstu</p>

<p align="left">Tekst wyrównany do lewej strony</p>

<p align="center">Tekst wyśrodkowany</p>

<p align="right">Tekst wyrównany do prawej strony</p>

<p mode="wrap">Nie zawijany tekst w długim wierszu...</p>

</card>

</wml>

Na rysunku 12.7 pokazano ten dokument w przeglądarce.

Rysunek 12.7.

Wyrównywanie tekstu w dokumencie WML

0x01 graphic

Podstawowe formatowanie tekstu

W WML obsługiwane są także niektóre elementy formatujące tekstu odziedziczone po HTML, takie jak <b> do pogrubienia, <i> do kursywy czy <u> do podkreślenia. Oto przykład ich zastosowania (pamiętaj jednak, że nie wszystkie mikroprzeglądarki obsługują te elementy):

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Formatowanie tekstu">

<p align="center"><b>Formatowanie tekstu</b></p>

<p>

W WML obsługiwane są następujące sposoby formatowania tekstu:

<b>pogrubienie</b>,

<big>powiększenie</big>,

<em>zaakcentowanie</em>,

<i>kursywa</i>,

<small>zmniejszenie</small>,

<strong>wyróżnienie</strong>

oraz <u>podkreślenie</u>.

</p>

</card>

</wml>

Wynik w przeglądarce pokazano na rysunku 12.8.

Rysunek 12.8.

Formatowanie tekstu w WML

0x01 graphic

Przyciski

W WML przyciski tworzy się za pomocą elementu do. Załóżmy na przykład, że chcemy umożliwić użytkownikowi dokumentu WML przejście na stronę www.starpowder.com/planets.wml. Zaczniemy od elementu do, przypiszemy mu atrybut type o wartości accept i dodamy etykietę za pomocą atrybutu label:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Przyciski">

<p align="center"><b>Przyciski</b></p>

<do type="accept" label="Skok na nową stronę...">

.

.

.

</do>

</card>

</wml>

Do przejścia do nowego dokumentu służy element go, w którym w atrybucie href podaje się docelowy adres URI:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Przyciski">

<p align="center"><b>Przyciski</b></p>

<do type="accept" label="Skok na nową stronę...">

<go href="http://www.starpowder.com/planets.wml"/>

</do>

</card>

</wml>

Na rysunku pokazano wynik naszej pracy - pojawił się przycisk. Jego kliknięcie spowoduje skok pod adres www.starpowder.com/planets.wml.

Rysunek 12.9.

Wyświetlanie w dokumencie WML przycisku

0x01 graphic

Jak już wcześniej wspomniano, w talii może znajdować się wiele kart, ale zawsze jest widoczna tylko jedna na raz. Jak zatem dostać się do pozostałych? Używa się do tego przycisków. W tym wypadku atrybutowi href elementu go przypisujesz identyfikator karty docelowej.

Oto przykład, gdzie mamy dwie karty i przycisk umożliwiający użytkownikowi nawigację z pierwszej karty do drugiej:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Wiele kart">

<p align="center"><b>Wiele kart</b></p>

<do type="accept" label="Na drugą kartę">

<go href="#Card2"/>

</do>

</card>

<card id="Card2" title="Karta 2">

<p>

To jest karta 2.

</p>

</card>

</wml>

Wynik pokazano na rysunku 12.10. Kiedy użytkownik kliknie przycisk, przeglądarka przeskoczy na drugą kartę z talii. Tak właśnie można się poruszać między kartami w WML.

Rysunek 12.10.

Wyświetlanie w dokumencie WML przycisku nawigacyjnego

0x01 graphic

Jak teraz użytkownik ma się dostać z powrotem z karty 2 na kartę 1? To właśnie temat następnego punktu.

Przycisk Wstecz

W WML obsługiwany jest specjalny przycisk, który jest bardzo często wyświetlany - Wstecz. Aby taki przycisk dodać do drugiej karty, użyjemy elementu prev:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Wiele kart">

<p align="center"><b>Wiele kart</b></p>

<do type="accept" label="Na drugą kartę">

<go href="#Card2"/>

</do>

</card>

<card id="Card2" title="Karta 2">

<p>

To jest karta 2.

</p>

<do type="prev" label="Wstecz">

<prev/>

</do>

</card>

</wml>

I to już wystarczy. Jak widać na rysunku 12.11, na drugiej karcie pojawił się przycisk Wstecz. Kiedy użytkownik go kliknie, przeglądarka przeskoczy na poprzednią kartę. Pamiętaj, że użytkownik używa przycisków do poruszania się między kartami talii, więc wskazane jest umieszczenie przycisku Wstecz na każdej karcie (mikroprzeglądarki zwykle nie mają wbudowanego przycisku Wstecz czy Back, który istnieje w Klondike).

Rysunek 12.11.

Wyświetlanie przycisku Wstecz

0x01 graphic

Hiperłącza

W WML obsługiwany jest także element a umożliwiający tworzenie hiperłączy. Tak jak w HTML, tak i tu docelowy adres podawany jest w atrybucie href. Oto przykład, w którym hiperłącze zawiedzie użytkownika do przykładu firmy Apache:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Hiperłącza">

<p align="center"><b>Hiperłącza</b></p>

<p>

Chcesz zobaczyć różne przykłady WML?

Obejrzyj zatem

<a href="http://www.apachesoftware.com/wml/wmldemo.wml">

przykłady Apache

</a>.

</p>

</card>

</wml>

Na rysunku 12.12 pokazano wynik; kiedy użytkownik kliknie hiperłącze, przeglądarka przeniesie go pod wskazany adres.

Rysunek 12.12.

Hiperłącze WML

0x01 graphic

Tabele

Tabele w WML tworzy się za pomocą znanych z HTML elementów table, tr i td (nie istnieją natomiast th, tbody, thead ani tfoot). Zwróć uwagę, jak bardzo poniższy przykład przypomina tabelę HTML:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Tabele">

<p align="center"><b>Tabele</b></p>

<p align="center">

<table columns="3">

<tr>

<td>TIC</td>

<td>TAC</td>

<td>TOE</td>

</tr>

<tr>

<td>x</td>

<td>o</td>

<td>x</td>

</tr>

<tr>

<td>o</td>

<td>x</td>

<td>o</td>

</tr>

<tr>

<td>x</td>

<td>o</td>

<td>x</td>

</tr>

</table>

</p>

</card>

</wml>

Na rysunku 12.13 pokazano wynik.

Rysunek 12.13.

Tabele WML

0x01 graphic

Wprowadzanie danych tekstowych

W WML obsługiwany jest także element input. Jeśli jego atrybutowi type nadasz wartość text, wyświetlone zostanie pole tekstowe, takiej jak pola znane z HTML (jednak nie wszystkie mikroprzeglądarki są w stanie ten element obsłużyć).

W poniższym przykładzie umożliwimy użytkownikowi podać nazwę pliku lokalnego w polu tekstowym. Kiedy użytkownik kliknie przycisk Skocz, przeglądarka wyświetli podany plik. Zaczniemy od utworzenia pola tekstowego:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Wprowadzanie tekstu">

<p align="center"><b>Wprowadzanie tekstu</b></p>

<p>

Skocz pod adres:

<input type="text" name="uri"/>

.

.

.

</p>

</card>

</wml>

Kiedy użytkownik kliknie przycisk Skocz, będziemy musieli jakoś odczytać tekst z pola uri. Do wartości pola tekstowego można się odwołać stosując zapis $(uri):

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Wprowadzanie tekstu">

<p align="center"><b>Wprowadzanie tekstu</b></p>

<p>

Skocz pod adres:

<input type="text" name="uri"/>

<do type="accept" label="Skocz">

<go href="$(uri)"/>

</do>

</p>

</card>

</wml>

Na rysunku 12.14 pokazano wyniki. Kiedy użytkownik w polu tekstowym poda adres dokumentu lokalnego i kliknie przycisk Skocz, przeglądarka odczyta nazwę dokumentu i go otworzy.

Rysunek 12.14.

Obsługa wprowadzania tekstu

0x01 graphic

Niejako przy okazji zetknęliśmy się tu z pojęciem zmiennych WML, w tym przypadku $(uri). Możliwość bezpośredniej obsługi zmiennych czyni z WML język nie tylko znacznikowy, ale też zawierający pewne funkcje skryptowe. Istnieje też element setvar, który umożliwia przypisywanie zmiennym wartości:

<setvar name="uri" value="rys12-13.wml"/>

W następnym punkcie zajmiemy się zmiennymi dokładniej.

Listy wyboru

Tak jak w HTML, tak i w WML obsługiwany jest element select tworzący kontrolkę wyboru (działającą jak lista rozwijalna). W ramach przykładu taką kontrolkę utworzymy teraz. Kiedy po dokonaniu już wyboru użytkownik kliknie przycisk Odczyt wyboru, zostanie przeniesiony na nową kartę, która dokonany wybór pokaże.

Zaczniemy od zdefiniowania kontrolki i nadania jej nazwy selection:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Wybór">

<p align="center"><b>Wybór</b></p>

<select name="selection">

.

.

.

</select>

Tak jak w HTML, poszczególne opcje podajemy stosując element option:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Wybór">

<p align="center"><b>Wybór</b></p>

<select name="selection">

<option value="brokuły">Brokuły</option>

<option value="zielone fasolki">Zielone fasolki</option>

<option value="szpinak">Szpinak</option>

</select>

.

.

.

Następnie dodajemy przycisk Odczyt wyboru, którego kliknięcie spowoduje przejście do następnej karty, karty 2:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Wybór">

<p align="center"><b>Wybór</b></p>

<select name="selection">

<option value="brokuły">Brokuły</option>

<option value="zielone fasolki">Zielone fasolki</option>

<option value="szpinak">Szpinak</option>

</select>

<do type="accept" label="Odczyt wyboru">

<go href="#card2"/>

</do>

.

.

.

Na karcie 2 wyświetlimy wartość kontrolki wyboru, do której odwołamy się stosując zapis $(selection). Wartość ta jest napisem z atrybutu value aktualnie wybranego elementu option. Na karcie 2 wyświetlimy dokonany wybór:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Wybór">

<p align="center"><b>Wybór</b></p>

<select name="selection">

<option value="brokuły">Brokuły</option>

<option value="zielone fasolki">Zielone fasolki</option>

<option value="szpinak">Szpinak</option>

</select>

<do type="accept" label="Odczyt wyboru">

<go href="#Card2"/>

</do>

</card>

<card id="Card2" title="Karta 2">

<p>

Wybrano $(selection).

</p>

</card>

</wml>

Na rysunku 12.15 pokazano naszą talię w działaniu - wybrano Szpinak.

Rysunek 12.15.

Wybieranie wartości

0x01 graphic

Kliknięcie przycisku Odczyt wyboru powoduje przejście do karty 2, na której pokazywany jest wybór dokonany przez użytkownika - rysunek 12.16.

Rysunek 12.16.

Informowanie o dokonanym wyborze

0x01 graphic

Inną użyteczną możliwością zastosowania kontrolek wyboru jest użycie atrybutu onpick elementów option, co umożliwia przenoszenie się pod inne adresy URI kiedy tylko użytkownik wybierze jakąś opcję. Oto przykład - wystarczy ustawić wartość atrybut onpick poszczególnych elementów option na adresy URI; kiedy użytkownik wybierze jeden z nich, przeglądarka przeskoczy pod wskazany adres:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Wybór">

<p align="center"><b>Wybór</b></p>

<select name="selection">

<option onpick="http://www.starpowder.com/mercury.wml">

Merkury

</option>

<option onpick="http://www.starpowder.com/venus.wml">

Wenus

</option>

<option onpick="http://www.starpowder.com/earth.wml">

Ziemia

</option>

</select>

</card>

</wml>

Użycie zegara

W WML można użyć zegara do odmierzenia zadanego czasu, a przeglądarka po upływie tego okresu automatycznie coś wykona. Jeśli na przykład atrybutowi ontimer karty przypiszemy identyfikator innej karty, to przeglądarka po upływie zadanego czasu przejdzie do karty docelowej:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" ontimer="#Card2" title="Użycie zegara">

.

.

.

</card>

.

.

.

Zegar tworzy się stosując element timer i przypisując mu okres czasu w atrybucie value (miarą jest dziesiąta część sekundy). Nasz zegar ustawimy na 10 sekund:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" ontimer="#Card2" title="Użycie zegara">

<p align="center"><b>Użycie zegara</b></p>

<timer value="100"/>

<p>

W ciągu dziesięciu sekund zostanie przeniesiony

na drugą kartę.

</p>

</card>

.

.

.

Teraz należy dodać tę drugą kartę:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" ontimer="#Card2" title="Użycie zegara">

<p align="center"><b>Użycie zegara</b></p>

<timer value="100"/>

<p>

W ciągu dziesięciu sekund zostanie przeniesiony

na drugą kartę.

</p>

</card>

<card id="Card2" title="Witaj">

<p>

Witaj na karcie 2.

</p>

</card>

</wml>

Kiedy otwierasz tę talię, wyświetlana jest karta 1, co pokazano na rysunku 12.17. Po dziesięciu sekundach przeglądarka przełącza się na kartę 2. W przeglądarce Klondike upływ czasu jest pokazywany w prawym dolnym rogu, w okienku Timer; na rysunku widać, że do przełączenia zostało jeszcze 7 sekund.

Rysunek 12.17.

Użycie zegara

0x01 graphic

Łączenie się z serwerem

W WML można tworzyć formularze, które są bardzo podobne w działaniu do formularzy HTML. Dane formularza WML są tak samo kodowane, można je zatem przekazać do skryptu CGI (jednak trzeba pamiętać, że nie wszystkie przeglądarki formularze obsługują).

W poniższym przykładzie prosimy użytkowników o ich komentarze, które przekazujemy do skryptu CGI o nazwie comments.cgi. Na początek tworzymy przycisk z etykietą Ładowanie danych, jego atrybut method ustawiamy na post, zaś href na adres, pod który dane mają być wysyłane, tutaj http://www.starpowder.com/comments.cgi - zupełnie jak w HTML:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" ontimer="#Card2" title="Ładowanie danych">

<p align="center"><b>Ładowanie danych</b></p>

<do type="accept" label="Ładowanie danych">

<go method="post"

href="http://www.starpowder.com/comments.cgi">

.

.

.

</go>

.

.

.

Teraz trzeba tylko wskazać ładowane dane i dane te nazwać. Używa się do tego atrybutów name i value elementu postfield. W tym wypadku ładować będziemy tekst z pola comments:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" ontimer="#Card2" title="Ładowanie danych">

<p align="center"><b>Ładowanie danych</b></p>

<do type="accept" label="Ładowanie danych">

<go method="post"

href="http://www.starpowder.com/comments.cgi">

<postfield name="comments" value="$(comments)"/>

</go>

<p>

Proszę podać swoje uwagi:

<input type="text" name="comments"/>

</p>

</card>

</wml>

To już wystarczy. Skrypt CGI może odczytać załadowane dane tak, jak odczytałby je z dokumentu HTML. Zwróć uwagę, że podczas odsyłania odpowiedzi dane należy sformatować jako WML, a w nagłówku HTTP jako typ MIME podać text/vnd.wap.wml.

Obrazki

W WML można wyświetlać obrazki, ale jest tu pewna pułapka: wszystkie te obrazki muszą być w specjalnym formacie WBMP, a ten format nie pozwala uzyskać takiej głębi kolorów, do jakiej przywykłeś. Tak naprawdę WBMP jest formatem czarno białym bez żadnej skali szarości - jeden bit na piksel.

Pod adresami z poniższej listy znajdziesz nieco informacji i programów do obsługi WBMP:

Aby wyświetlić obrazek, używa się elementu img - chyba nie jesteś zaskoczony? Ustawia się atrybuty alt, src, width i height, jak w poniższym przykładzie:

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

"http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>

<card id="Card1" title="Obrazki">

<p align="center"><b>Obrazki</b></p>

<p align="center">

<img alt="Obrazek WML"

src="twarz.wbmp" width="164" height="164"/>

</p>

</card>

</wml>

Na rysunku 12.18 pokazano dokument WML wraz z obrazkiem WBMP.

Rysunek 12.18.

Wyświetlanie obrazka

0x01 graphic

I tak oto kończymy poznawanie WML, a także XML. W trakcie czytania tej książki poznałeś naprawdę wiele tematów związanych z XML, od podstawowych jak składnia XML po zaawansowane, jak programowa obsługa dokumentów, poznałeś też różne aplikacje XML, na przykład VML czy WML. Teraz zostało Ci już tylko jedno: zaprząc tę niezwykłą technologię, aby pracowała na Twoje potrzeby --> .[Author:T]

Właściwie pole ukryte formularza. (przyp. tłum.)

Jak widać w pasku tytułu, przeglądarka ta nie zawsze dobrze sobie radzi z polskimi literami. (przyp. tłum.)

24 Część I Podstawy obsługi systemu WhizBang (Nagłówek strony)

Rozdział 1 Pierwsze kroki (Nagłówek strony)

24 C:\Moje dokumenty\Wojtek Romowicz\Książki\XML Vademecum profesjonalisty\r12-01.doc

C:\Moje dokumenty\Wojtek Romowicz\Książki\XML Vademecum profesjonalisty\r12-01.doc 1

w oryginale 20

proszę o sprawdzenie

proszę o sprawdzenie

u autora @_; wskazana konsultacja kogoś znającego Perla

proszę o kontrolę/podmianę

Ostatni akapit zmieniony - usunąłem wyliczankę tematów, gdyż w polskim wydaniu pominięte zostały niektóre istotne zagadnienia, które znalazły się w innych książkach Wydawnictwa.



Wyszukiwarka

Podobne podstrony:
r03-01, ## Documents ##, XML Vademecum profesjonalisty
r05-01, ## Documents ##, XML Vademecum profesjonalisty
r04-01, ## Documents ##, XML Vademecum profesjonalisty
r07-01, ## Documents ##, XML Vademecum profesjonalisty
r06-01, ## Documents ##, XML Vademecum profesjonalisty
r08-01, ## Documents ##, XML Vademecum profesjonalisty
r11-01, ## Documents ##, XML Vademecum profesjonalisty
r09-01, ## Documents ##, XML Vademecum profesjonalisty
r10-01, ## Documents ##, XML Vademecum profesjonalisty
Projektowanie Baz Danych Xml Vademecum Profesjonalisty [XML]
R12-05, ## Documents ##, WIN 2000 Professional -W praktyce
Projektowanie baz danych XML Vademecum profesjonalisty pxmlvp 2
Projektowanie baz danych XML Vademecum profesjonalisty pxmlvp
Projektowanie baz danych XML Vademecum profesjonalisty 2
Projektowanie Baz Danych Xml Vademecum Profesjonalisty [XML]
Projektowanie baz danych XML Vademecum profesjonalisty pxmlvp
Projektowanie Baz Danych Xml Vademecum Profesjonalisty R 5 Architektura Systemu Baz Danych
Projektowanie baz danych XML Vademecum profesjonalisty

więcej podobnych podstron