Rozdział
-->
6[Author:T]
.
XML i wiązanie danych
W poprzednim rozdziale zajmowaliśmy się przetwarzaniem dokumentów w Internet Explorerze przy pomocy modelu DOM. Używaliśmy metod takich, jak firstChild, lastChild, lastSibling i tak dalej. Użycie tych metod pozwoliło sięgnąć do wszystkich danych dokumentu XML, ale traktowanie tego dokumentu jako drzewa węzłów było mylące, szczególnie jeśli zapomni się, że dane znakowe elementów także mają własne swoje węzły.
Dokumenty XML można jednak w Internet Explorerze obsługiwać też inaczej, tym właśnie zajmiemy się w tym rozdziale. Internet Explorer umożliwia odczytywanie dokumentów HTML i XML i przechowywanie ich w bazie danych. Używając metod bazy danych, które omówimy w tym rozdziale, możemy przechodzić między rekordami danych, co dla wielu programistów jest łatwiejsze od stosowania metod DOM.
Wiązanie danych w Internet Explorerze
W Internet Explorerze rozwinięto koncepcję wiązania danych. Wiązanie to umożliwia łączenie danych z dokumentów z bazą danych ADO (ActiveX Data Object) i później łatwy dostęp do tych danych. Taka technika pracy jest wygodna, gdyż dane z bazy można wysyłać jako dokumenty XML przez Internet i w miejscu przeznaczenia można je przekształcić z powrotem. Dzięki temu programiści, którym nieobce są zagadnienia baz danych, mogą skoncentrować się na dobrze znanych sobie technikach, a nie muszą uczyć się metod DOM.
Najpierw ogólnie omówimy wiązanie danych w Internet Explorerze, później zajmiemy się konkretnie dokumentami XML. Użycie wiązania danych w Explorerze składa się z dwóch etapów: najpierw używa się obiektów danych źródłowych (DSO, data source objects), potem dane wiąże się z elementami HTML strony sieciowej.
Więcej informacji o wiązaniu danych
Więcej informacji o wiązaniu danych w Internet Explorerze znajdziesz pod adresem http://msdn.microsoft.com/workshop/c-frame.htm#/workshop/author/default.asp.
Użycie obiektów danych źródłowych
W Internet Explorerze istnieją cztery obiekty danych źródłowych (DSO, Data Source Object): kontrolka Microsoft HTML (MSHTML), kontrolka danych tabelarycznych (TDC), XML DSO i wyspy danych XML. Internet Explorer obsługuje jeszcze dość wyspecjalizowany RDS DSO (DSO dostępu zdalnego do danych), który umożliwia połączenie się z aplikacjami bazodanowymi, takimi jak aplikacje SQL uruchamiane na serwerze sieciowym). Dwa DSO, mianowicie XML DSO i wyspy danych XML, umożliwiają obsługę dokumentów XML.
DSO na stronie nie są widoczne (choć, jak zobaczymy pod koniec tego rozdziału, XML DSO może wyświetlać na stronie komunikaty o stanie). DSO używa się do odczytywania dokumentu i udostępniania jego danych reszcie strony. Aby DSO był w stanie odczytać dane dokumentu, dane te muszą być odpowiednio sformatowane.
Poniżej przedstawiono dokument przykładowy, klient.html, który zawiera dane dotyczące sprzedaży detalicznej. Rejestrujemy nazwiska i identyfikatory klientów, daty zakupu, dział, z którego towar kupiono oraz nazwę towaru. Zwróć uwagę, jak za pomocą znaczników <SPAN> określono strukturę dokumentu, aby dane były czytelne dla Internet Explorera (można by użyć też innego znacznika, na przykład <DIV>). Każdemu znacznikowi z danymi przypisano atrybut ID, który określa rodzaj danych. Jak widać, stosowana technika aż się prosi o zapis w postaci XML.
<HTML>
<HEAD>
<TITLE>
Dane o klientach
</TITLE>
</HEAD>
<BODY>
Nazwisko: <SPAN ID="NAZWISKO">Charles</SPAN><BR>
ID: <SPAN ID="ID_KLIENTA">58704</SPAN><BR>
Data zakupu: Data: <SPAN ID="DATA_ZAKUPU">
2001.10.15</SPAN><BR>
Dział: <SPAN ID="DZIAŁ">Mięso</SPAN><BR>
Produkt: <SPAN ID="PRODUKT">Szynka</SPAN><BR>
Nazwisko: <SPAN ID="NAZWISKO">Franklin</SPAN><BR>
ID: <SPAN ID="ID_KLIENTA">58705</SPAN><BR>
Data zakupu: Data: <SPAN ID="DATA_ZAKUPU">
2001.10.15</SPAN><BR>
Dział: <SPAN ID="DZIAŁ">Warzywa</SPAN><BR>
Produkt: <SPAN ID="PRODUKT">Pomidory</SPAN><BR>
Nazwisko: <SPAN ID="NAZWISKO">Phoebe</SPAN><BR>
ID: <SPAN ID="ID_KLIENTA">58706</SPAN><BR>
Data zakupu: Data: <SPAN ID="DATA_ZAKUPU">
2001.10.15</SPAN><BR>
Dział: <SPAN ID="DZIAŁ">Mięso</SPAN><BR>
Produkt: <SPAN ID="PRODUKT">Indyk</SPAN><BR>
Nazwisko: <SPAN ID="NAZWISKO">Mark</SPAN><BR>
ID: <SPAN ID="ID_KLIENTA">58707</SPAN><BR>
Data zakupu: Data: <SPAN ID="DATA_ZAKUPU">
2001.10.15</SPAN><BR>
Dział: <SPAN ID="DZIAŁ">Mięso</SPAN><BR>
Produkt: <SPAN ID="PRODUKT">Wołowina</SPAN><BR>
Nazwisko: <SPAN ID="NAZWISKO">Nancy</SPAN><BR>
ID: <SPAN ID="ID_KLIENTA">58708</SPAN><BR>
Data zakupu: Data: <SPAN ID="DATA_ZAKUPU">
2001.10.15</SPAN><BR>
Dział: <SPAN ID="DZIAŁ">Mrożonki</SPAN><BR>
Produkt: <SPAN ID="PRODUKT">Brokuły</SPAN><BR>
</BODY>
</HTML>
Najbardziej typowym sposobem obsługi danych sformatowanych w postać dokumentu HTML jest użycie DSO MSHTML, tego obiektu tutaj użyjemy. DSO odczytuje dokument taki jaki pokazano wyżej i przekształca go na zbiór rekordów. Każdy rekord z tego zbioru pochodzi z elementów HTML lub XML, których użyto do przechowywania danych. Oto przykładowy rekord HTML:
Nazwisko: <SPAN ID="NAZWISKO">Charles</SPAN><BR>
ID: <SPAN ID="ID_KLIENTA">58704</SPAN><BR>
Data zakupu: Data: <SPAN ID="DATA_ZAKUPU">
2001.10.15</SPAN><BR>
Dział: <SPAN ID="DZIAŁ">Mięso</SPAN><BR>
Produkt: <SPAN ID="PRODUKT">Szynka</SPAN><BR>
Rekord ten ma pięć pól: NAZWISKO, ID_KLIENTA, DATA_ZAKUPU, DZIAŁ i PRODUKT. Zbiór rekordów wygląda jak tablica rekordów - kiedy pracujesz z konkretnym rekordem, możesz sięgać do jego poszczególnych pól. Aby na przykład sprawdzić, co kupił Charles, wystarczy odnaleźć opisujący go rekord i sprawdzić wartość jego pola PRODUKT.
Używając znacznika <OBJECT> można utworzyć obiekt DSO MSHTML i powiązać go z plikiem klient.html. Obiekt ten nazwiemy dsoKlient:
<OBJECT ID="dsoKlient" DATA="klient.html" HEIGHT="0" WIDTH="0">
</OBJECT>
DSO odczyta i zinterpretuje plik klient.html, przekształci go na zbiór danych ADO (tak naprawdę Internet Explorer używa zbioru tylko do odczytu, ADOR). DSO zawiera na raz dane jednego tylko rekordu, rekord ten jest rekordem bieżącym. Do nawigacji po zbiorze można używać wbudowanych metod obiektu DSO, najpopularniejsze z nich to moveFirst, moveLast, moveNext i movePrevious - odpowiednio: skok do pierwszego rekordu, skok do rekordu ostatniego, następny i poprzedni rekord. Aby wyświetlić dane z DSO, trzeba je powiązać z elementami HTML.
Wiązanie danych z elementami HTML
Tak naprawdę niewiele elementów HTML w Internet Explorerze obsługuje właściwości, które umożliwiają wiązanie danych z DSO. Do wiązania używa się atrybutów DATASRC i DATAFLD. Atrybut DATASRC jako wartość otrzymuje nazwę obiektu DSO, natomiast DATAFLD - nazwę pola danych, które ma być związane z elementem, wtedy element HTML wyświetli dane z bieżącego rekordu. Stosując metody moveFirst, moveLast, moveNext i movePrevious można pokazać pozostałe rekordy ze zbioru.
Jeśli na przykład powiążemy pole tekstowe z DSO dsoKlient z polem danych NAZWISKO, kontrolka przy pierwszym załadowaniu danych wyświetli napis Charles. Wywołanie metody moveNext spowoduje, że rekordem bieżącym stanie się drugi rekord ze zbioru, a w polu tekstowym wyświetlony zostanie napis Franklin.
Oto zestawienie elementów HTML z wyszczególnieniem, co daje ustawienie atrybutów DATASRC i DATAFLD:
Element |
Co jest wiązane z danymi |
A |
Właściwość href; niemożliwa jest modyfikacja danych. |
APPLET |
Właściwość param; modyfikacja danych jest możliwa. |
BUTTON |
Właściwość value; niemożliwa jest modyfikacja danych. |
DIV |
Właściwości innerText oraz innerHTML; niemożliwa jest modyfikacja danych. |
FRAME |
Właściwość src; niemożliwa jest modyfikacja danych. |
IFRAME |
Właściwość src; niemożliwa jest modyfikacja danych. |
IMG |
Właściwość src; niemożliwa jest modyfikacja danych. |
INPUT TYPE=BUTTON |
Właściwość value; niemożliwa jest modyfikacja danych. |
INPUT TYPE=CHECKBOX |
Właściwość checked; możliwa jest modyfikacja danych. |
INPUT TYPE=HIDDEN |
Właściwość value; możliwa jest modyfikacja danych. |
INPUT TYPE=PASSWORD |
Właściwość value; możliwa jest modyfikacja danych. |
INPUT TYPE=RADIO |
Właściwość checked; możliwa jest modyfikacja danych. |
INPUT TYPE=TEXT |
Właściwość value; możliwa jest modyfikacja danych. |
LABEL |
Właściwość value; niemożliwa jest modyfikacja danych. |
MARQUEE |
Właściwości innerText i innerHTML; niemożliwa jest modyfikacja danych. |
OBJECT |
Właściwość objects; możliwa jest modyfikacja danych. |
PARAM |
Właściwość param; możliwa jest modyfikacja danych. |
SELECT |
Właściwość text opcji; możliwa jest modyfikacja danych. |
SPAN |
Właściwości innerText i innerHTML; niemożliwa jest modyfikacja danych. |
TABLE |
Tworzy całą tabelę; niemożliwa jest modyfikacja danych. |
TEXTAREA |
Właściwość value; możliwa jest modyfikacja danych. |
Oprócz tego znaczniki HTML mają zdarzenia, których można użyć przypadku wiązania ich z danymi:
Zdarzenie |
Opis |
onafterupdate |
Zachodzi po aktualizacji danych elementu w DSO. |
onbeforeunload |
Zachodzi przed usunięciem strony z pamięci. |
onbeforeupdate |
Zachodzi przed aktualizacją danych elementu w DSO. |
onerrorupdate |
Zachodzi, jeśli dane DSO nie zostały zaktualizowane z powodu błędu. |
Czas teraz całą tę naszą wiedzę zaprząc do pracy. Zaczniemy od dodania na stronie kontrolki MSHTML dsoKlient i połączenia tego obiektu DSO z plikiem klient.html:
<HTML>
<HEAD>
<TITLE>
Wiązanie danych za pomocą DSO MSHTML
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Wiązanie danych za pomocą DSO MSHTML
</H1>
<OBJECT ID="dsoKlient" DATA="klient.html"
HEIGHT="0" WIDTH="0">
</OBJECT>
.
.
.
Teraz nasz obiekt DSO powiążemy z polem tekstowym ustawiając atrybut DATASRC tego pola na wartość #dsoCutomer (Explorer wymaga poprzedzenia nazwy DSO krzyżykiem hash). Pole tekstowe może wyświetlić jednocześnie dane tylko z jednego pola danych, wskażemy pole NAZWISKO - użyjemy atrybutu DATAFLD:
<HTML>
<HEAD>
<TITLE>
Wiązanie danych za pomocą DSO MSHTML
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Wiązanie danych za pomocą DSO MSHTML
</H1>
<OBJECT ID="dsoKlient" DATA="klient.html"
HEIGHT="0" WIDTH="0">
</OBJECT>
Nazwisko: <INPUT TYPE="TEXT" DATASRC="#dsoKlient"
DATAFLD="NAZWISKO" SIZE="10">
.
.
.
Teraz pole danych ID_KLIENTA powiążemy z następnym polem tekstowym. Zresztą dane z DSO można byłoby także wyświetlać bezpośrednio na stronie, bez używania pól tekstowych - należałoby obiekt DSO powiązać z elementem SPAN, jak to robimy z datą zakupu:
<HTML>
<HEAD>
<TITLE>
Wiązanie danych za pomocą DSO MSHTML
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Wiązanie danych za pomocą DSO MSHTML
</H1>
<OBJECT ID="dsoKlient" DATA="klient.html"
HEIGHT="0" WIDTH="0">
</OBJECT>
Nazwisko: <INPUT TYPE="TEXT" DATASRC="#dsoKlient"
DATAFLD="NAZWISKO" SIZE="10">
<P>
ID: <INPUT TYPE="TEXT" DATASRC="#dsoKlient"
DATAFLD="ID_KLIENTA" SIZE="5">
<P>
Data zakupu: <SPAN DATASRC="#dsoKlient"
DATAFLD="DATA_ZAKUPU"></SPAN>
.
.
.
Aby pokazać sposób wiązania z danymi innych kontrolek, pole DZIAŁ powiążemy z kontrolką SELECT, której odpowiada lista rozwijalna. DSO wskazujemy jak zwykle, ale trzeba też podać wszystkie dopuszczalne wartości tego pola za pomocą wewnętrznych elementów OPTION:
<HTML>
<HEAD>
<TITLE>
Wiązanie danych za pomocą DSO MSHTML
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Wiązanie danych za pomocą DSO MSHTML
</H1>
<OBJECT ID="dsoKlient" DATA="klient.html"
HEIGHT="0" WIDTH="0">
</OBJECT>
Nazwisko: <INPUT TYPE="TEXT" DATASRC="#dsoKlient"
DATAFLD="NAZWISKO" SIZE="10">
<P>
ID: <INPUT TYPE="TEXT" DATASRC="#dsoKlient"
DATAFLD="ID_KLIENTA" SIZE="5">
<P>
Data zakupu: <SPAN DATASRC="#dsoKlient"
DATAFLD="DATA_ZAKUPU"></SPAN>
<P>
Dział: <SELECT DATASRC="#dsoKlient"
DATAFLD="DZIAŁ" SIZE="1">
<OPTION VALUE="Mięso">Mięso
<OPTION VALUE="Warzywa">Warzywa
<OPTION VALUE="Mrożonki">Mrożonki
</SELECT>
<P>
Produkt: <SPAN DATASRC="#dsoKlient" DATAFLD="PRODUKT">
</SPAN>
.
.
.
Niejako przy okazji powiązaliśmy jeszcze pole danych PRODUKT z kolejnym elementem SPAN. Przy pierwszym załadowaniu strony pokazane zostaną wszystkie dane pierwszego rekordu ze zbioru danych - jak jednak pokazać pozostałe dane?
Trzeba udostępnić użytkownikowi metody moveFirst, moveLast, moveNext i movePrevious, aby mógł poruszać się po zbiorze rekordów; najwygodniej będzie powiązać te metody z przyciskami. Do obiektu zbioru rekordów z DSO można się odwoływać stosując zapis dsoKlient.recordset, zatem przesunięcie się do pierwszego rekordu realizowane metodą moveFirst będzie wyglądało tak: dsoKlient.recordset.moveFirst(). Oto przyciski, jakich użyjemy:
Opis przycisku |
Funkcja |
<< |
Przejście do pierwszego rekordu. |
< |
Przejście do poprzedniego rekordu. |
> |
Przejście do następnego rekordu. |
>> |
Przejście do ostatniego rekordu. |
Kod obsługi tych przycisków będzie wyglądał następująco:
<BUTTON ONCLICK="dsoKlient.recordset.moveFirst()"><<
</BUTTON>
<BUTTON ONCLICK="dsoKlient.recordset.movePrevious()"><
</BUTTON>
<BUTTON ONCLICK="dsoKlient.recordset.moveNext()">>
</BUTTON>
<BUTTON ONCLICK="dsoKlient.recordset.moveLast()">>>
</BUTTON>
Zanim jednak metod movePrevious i moveNext użyjemy, warto sprawdzić, czy rekordy poprzedni i następny w ogóle istnieją (jeśli przesuniemy się poza koniec zbioru rekordów, pokażą się puste pola). Można użyć właściwości BOF (początek zbioru danych) oraz EOF (koniec zbioru danych) obiektu recordset. Gotowy kod będzie wyglądał tak:
<HTML>
<HEAD>
<TITLE>
Wiązanie danych za pomocą DSO MSHTML
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Wiązanie danych za pomocą DSO MSHTML
</H1>
<OBJECT ID="dsoKlient" DATA="klient.html"
HEIGHT="0" WIDTH="0">
</OBJECT>
Nazwisko: <INPUT TYPE="TEXT" DATASRC="#dsoKlient"
DATAFLD="NAZWISKO" SIZE="10">
<P>
ID: <INPUT TYPE="TEXT" DATASRC="#dsoKlient"
DATAFLD="ID_KLIENTA" SIZE="5">
<P>
Data zakupu: <SPAN DATASRC="#dsoKlient"
DATAFLD="DATA_ZAKUPU"></SPAN>
<P>
Dział: <SELECT DATASRC="#dsoKlient"
DATAFLD="DZIAŁ" SIZE="1">
<OPTION VALUE="Mięso">Mięso
<OPTION VALUE="Warzywa">Warzywa
<OPTION VALUE="Mrożonki">Mrożonki
</SELECT>
<P>
Produkt: <SPAN DATASRC="#dsoKlient" DATAFLD="PRODUKT">
</SPAN>
<P>
<BUTTON ONCLICK="dsoKlient.recordset.moveFirst()"><<
</BUTTON>
<BUTTON ONCLICK="if (!dsoKlient.recordset.BOF)
dsoKlient.recordset.movePrevious()"><
</BUTTON>
<BUTTON ONCLICK="if (!dsoKlient.recordset.EOF)
dsoKlient.recordset.moveNext()">>
</BUTTON>
<BUTTON ONCLICK="dsoKlient.recordset.moveLast()">>>
</BUTTON>
</CENTER>
</BODY>
</HTML>
Wynik działania tej strony pokazano na rysunku 6.1. Jak widać, wyświetlane są dane z pliku klient.html; użytkownik może poruszać się po rekordach przy pomocy przycisków.
Rysunek 6.1. Wiązanie danych w Internet Explorerze |
|
Tyle ogólnie o wiązaniu danych i o HTML; czas zająć się tym, co tygrysy lubią najbardziej, czyli XML.
XML i wiązanie danych
Zaczniemy od przekształcenia pliku klient.html na XML. W HTML musieliśmy używać elementów SPAN z atrybutem ID, w XML po prostu tworzymy potrzebne nam elementy. Nasze dane jako XML uzyskają postać:
<?xml version="1.0" encoding="iso-8859-2"?>
<KLIENCI>
<KLIENT>
<NAZWISKO>Charles</NAZWISKO>
<ID_KLIENTA>58704</ID_KLIENTA>
<DATA_ZAKUPU></DATA_ZAKUPU>
2001.10.15
<DZIAŁ>Mięso</DZIAŁ>
<PRODUKT>Szynka</PRODUKT>
</KLIENT>
<KLIENT>
<NAZWISKO>Franklin</NAZWISKO>
<ID_KLIENTA>58705</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Warzywa</DZIAŁ>
<PRODUKT>Pomidory</PRODUKT>
</KLIENT>
<KLIENT>
<NAZWISKO>Phoebe</NAZWISKO>
<ID_KLIENTA>58706</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Mięso</DZIAŁ>
<PRODUKT>Indyk</PRODUKT>
</KLIENT>
<KLIENT>
<NAZWISKO>Mark</NAZWISKO>
<ID_KLIENTA>58707</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Mięso</DZIAŁ>
<PRODUKT>Wołowina</PRODUKT>
</KLIENT>
<KLIENT>
<NAZWISKO>Nancy</NAZWISKO>
<ID_KLIENTA>58708</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Mrożonki</DZIAŁ>
<PRODUKT>Brokuły</PRODUKT>
</KLIENT>
</KLIENCI>
Jak widać, każdemu rekordowi odpowiada jeden element KLIENT. Można zresztą użyć dowolnej nazwy elementów, Internet Explorer i tak będzie w stanie przetworzyć dane. W poprzednim przykładzie, kiedy mieliśmy dane w postaci HTML, jako DSO używaliśmy kontrolki MSHTML, teraz mamy do wyboru wyspy danych XML lub DSO XML oparty na specjalnym aplecie dostarczanym wraz z Explorerem. Zaczniemy od użycia wysp danych.
Wiązanie pojedynczych rekordów przy użyciu --> wyspa[Author:AJ] danych XML
Aby zobaczyć sposób wiązania elementów HTML z wyspami danych XML, utworzymy nową stronę HTML, w której będziemy czytać dane z pliku klient.xml:
<HTML>
<HEAD>
<TITLE>
Wiązanie pojedynczych rekordów przy użyciu wysp danych XML
</TITLE>
</HEAD>
<XML SRC="klient.xml" ID="klienci”></XML>
.
.
.
Teraz już obiektu customers można użyć jako DSO, który można łączyć z elementami HTML, co już w tym rozdziale widzieliśmy:
<HTML>
<HEAD>
<TITLE>
Wiązanie pojedynczych rekordów przy użyciu wysp danych XML
</TITLE>
</HEAD>
<XML SRC="klient.xml" ID="klienci”></XML>
<BODY>
<CENTER>
<H1>
Wiązanie pojedynczych rekordów przy użyciu wysp danych XML
</H1>
Nazwisko: <INPUT TYPE="TEXT" DATASRC="#klienci”
DATAFLD="NAZWISKO" SIZE="10">
<P>
ID: <INPUT TYPE="TEXT" DATASRC="#klienci”
DATAFLD="ID_KLIENTA" SIZE="5">
<P>
Data zakupu: <SPAN DATASRC="#klienci”
DATAFLD="DATA_ZAKUPU"></SPAN>
<P>
Dział: <SELECT DATASRC="#klienci”
DATAFLD="DZIAŁ" SIZE="1">
<OPTION VALUE="Mięso">Mięso
<OPTION VALUE="Warzywa">Warzywa
<OPTION VALUE="Mrożonki">Mrożonki
</SELECT>
<P>
Produkt: <SPAN DATASRC="#klienci” DATAFLD="PRODUKT">
</SPAN>
.
.
.
</CENTER>
</BODY>
</HTML>
Właściwości, metody i zdarzenia DSO XML
W przykładzie z początku tego rozdziału pokazano, jak można użyć metod zbioru rekordów, takich jak moveFirst, moveLast, moveNext i movePrevious do poruszania się po tym zbiorze. Teraz wszystkie dostępne właściwości, metody i zdarzenia omówimy bardziej systematycznie. Zaczniemy od właściwości obiektu DSO XML:
Właściwość |
Opis |
absolutePage |
Strona, na której jest bieżący rekord. |
absolutePosition |
Położenie bieżącego rekordu w zbiorze. |
BOF |
Ma wartość true, jeśli rekordem bieżącym jest pierwszy rekord. |
cacheSize |
Liczba rekordów ze zbioru znajdujących się lokalnie w pamięci podręcznej. |
cursorLocation |
Położenie kursora w zbiorze rekordów. |
cursorType |
Rodzaj użytego kursora bazy danych. |
editMode |
Wskazuje, czy przeprowadzana jest edycja. |
EOF |
Ma wartość true, jeśli rekord bieżący znajduje się za ostatnim rekordem zbioru. |
lockType |
Rodzaj użytego blokowania w bazie danych. |
maxRecords |
Dopuszczalna liczba rekordów, jaka może zostać zwrócona przez zapytanie. |
pageCount |
Liczba stron danych znajdujących się w zbiorze rekordów. |
pageSize |
Liczba rekordów składających się na jedną stronę. |
recordCount |
Liczba rekordów w zbiorze. |
state |
Stan zbioru rekordów (otwarty lub zamknięty). |
status |
Status bieżącego rekordu. |
stayInSync |
Wskazuje, czy hierarchiczny zbiór rekordów ma być cały czas związany ze źródłem danych. |
Obiekty DSO XML zawierają następujące metody:
Metoda |
Opis |
addNew |
Dodaje do zbioru nowy rekord. |
cancel |
Odwołuje żądanie wykonania oczekującego żądania Execute lub Open. |
cancelUpdate |
Odwołuje żądanie aktualizacji danych. |
clone |
Tworzy kopię zbioru rekordów. |
close |
Zamyka zbiór rekordów. |
delete |
Usuwa bieżący rekord (lub grupę rekordów). |
find |
Przeszukuje zbiór rekordów (jednak Internet Explorer nie obsługuje jeszcze składni języka SQL). |
getRows |
Odczytuje rekordy i zapisuje je w tablicy. |
getString |
Pobiera zbiór rekordów w postaci napisu (tekstu). |
move |
Zmienia pozycję bieżącego rekordu. |
moveFirst, moveLast, moveNext, movePrevious |
Umożliwiają poruszanie się po zbiorze rekordów. |
nextRecordSet |
Zeruje bieżący obiekt zbioru danych i zwraca zbiór następny. Metoda używana w przypadku hierarchicznych zbiorów rekordów. |
open |
Otwiera bazę danych. |
requery |
Ponownie uruchamia zapytanie tworzące zbiór danych. |
save |
Zapisuje bieżący zbiór rekordów w pliku. |
supports |
Wskazuje, jakie możliwości udostępnia zbiór danych. Konieczne jest przekazanie wartości typu long odpowiadającej zmiennym metodom ADO zgodnie z dokumentacją Microsoft ADO. Na przykład przekazanie wartości 0x1000400 (0x oznacza zapis szesnastkowy) zwróci true, aby poinformować, że zbiór danych udostępnia metodę addNew. Przekazanie 0x10000 da w wyniku false, gdyż zbiory danych nie zawierają metody updateBatch. |
Z obiektami DSO XML związane są różne zdarzenia - przypomnij sobie, jak pokazywaliśmy w poprzednim rozdziale obsługę zdarzeń związanych z ładowaniem dokumentów XML.
Zdarzenie |
Opis |
onDataAvailable |
Zachodzi przy każdym ładowaniu zestawu danych. |
onDatasetChanged |
Zachodzi przy każdej modyfikacji zbioru danych. |
onDatasetComplete |
Zachodzi, kiedy zbiór danych zostanie załadowany i gotów jest do użycia. |
onReadyStateChange |
Zachodzi, kiedy zmienia się wartość właściwości ReadyState. |
onRowEnter |
Zachodzi, kiedy inny rekord niż dotąd staje się rekordem bieżącym. |
onRowExit |
Zachodzi podczas opuszczania bieżącego rekordu. |
onRowsDelete |
Zachodzi przy usuwaniu rekordu. |
onRowsInserted |
Zachodzi przy wstawianiu rekordu. |
onCellChange |
Zachodzi, kiedy dane kontrolki związanej ze zbiorem się zmieniają, a kursor opuszcza daną komórkę. |
Aby umożliwić użytkownikowi nawigację po zbiorze rekordów utworzonych z pliku klient.xml, dodamy te same przyciski, które znamy już z przykładu HTML i znów użyjemy metod typu klienci.recordset.moveNext() do nawigacji po tym zbiorze:
<HTML>
<HEAD>
<TITLE>
Wiązanie pojedynczych rekordów przy użyciu wysp danych XML
</TITLE>
</HEAD>
<XML SRC="klient.xml" ID="klienci”></XML>
<BODY>
<CENTER>
<H1>
Wiązanie pojedynczych rekordów przy użyciu wysp danych XML
</H1>
Nazwisko: <INPUT TYPE="TEXT" DATASRC="#klienci”
DATAFLD="NAZWISKO" SIZE="10">
<P>
ID: <INPUT TYPE="TEXT" DATASRC="#klienci”
DATAFLD="ID_KLIENTA" SIZE="5">
<P>
Data zakupu: <SPAN DATASRC="#klienci”
DATAFLD="DATA_ZAKUPU"></SPAN>
<P>
Dział: <SELECT DATASRC="#klienci”
DATAFLD="DZIAŁ" SIZE="1">
<OPTION VALUE="Mięso">Mięso
<OPTION VALUE="Warzywa">Warzywa
<OPTION VALUE="Mrożonki">Mrożonki
</SELECT>
<P>
Produkt: <SPAN DATASRC="#klienci” DATAFLD="PRODUKT">
</SPAN>
<P>
<BUTTON ONCLICK="klienci.recordset.moveFirst()"><<
</BUTTON>
<BUTTON ONCLICK="if (!klienci.recordset.BOF)
klienci.recordset.movePrevious()"><
</BUTTON>
<BUTTON ONCLICK="if (!klienci.recordset.EOF)
klienci.recordset.moveNext()">>
</BUTTON>
<BUTTON ONCLICK="klienci.recordset.moveLast()">>>
</BUTTON>
</CENTER>
</BODY>
</HTML>
Wynik naszej pracy można obejrzeć na rysunku 6.2: wartości pól danych zostały umieszczone w elementach HTML. Klikając przyciski nawigacyjne użytkownik może poruszać się po zbiorze danych.
Rysunek 6.2. Użycie wiązania danych do wyświetlania dokumentu XML |
|
Jak wynika z pokazanych wcześniej tabel, istnieje znacznie więcej możliwości nawigowania po zbiorze danych niż ich tu wykorzystaliśmy. Często na przykład wygodnie jest sięgać do pojedynczych pól rekordu. Załóżmy, że chcemy określić wartość pola ID_KLIENTA bieżącego rekordu DSO. Można to osiągnąć stosując wyrażenie klienci.recordset("ID_KLIENTA").
Zapewne zauważyłeś, o ile łatwiej jest sięgać do danych przez pola zbioru danych niż przez użycie metod DOM typu nextChild czy lastSibling. Jeśli dokument XML traktować jako bazę danych, użycie zbioru rekordów znakomicie upraszcza życie programisty.
Teraz pokażemy na przykładzie, jak sięgać do poszczególnych pól rekordów. Zorganizujemy pętlę działającą na kolejnych rekordach bazy danych (skorzystamy z pętli while, warunkiem zakończenia będzie uzyskanie przez właściwość EOF wartości true). Wyświetlać będziemy nazwisko klienta, kupiony towar i dział, w którym dokonano zakupu. Oto kod:
<HTML>
<HEAD>
<TITLE>
Dostęp do poszczególnych pól
</TITLE>
<XML ID="klient" SRC="klient.xml"></XML>
<SCRIPT LANGUAGE="JavaScript">
function viewData()
{
while (!klient.recordset.EOF) {
div1.innerHTML +=
klient.recordset("NAZWISKO") + " kupił(a) <I>" +
klient.recordset("PRODUKT") + "</I> w dziale " +
klient.recordset("DZIAŁ") + ".<BR>"
klient.recordset.moveNext()
}
}
</SCRIPT>
</HEAD>
<BODY>
<CENTER>
<H1>
Dostęp do poszczególnych pól
</H1>
</CENTER>
<FORM>
<CENTER>
<INPUT TYPE="BUTTON" VALUE="Przegląd danych"
ONCLICK="viewData()">
</CENTER>
</FORM>
<DIV ID="div1"></DIV>
</BODY>
</HTML>
Wyniki działania tego kodu pokazano na rysunku 6.3. Jak widać, zestawione i wyświetlone zostały poszczególne pola z różnych rekordów.
Rysunek 6.3. Dostęp do pojedynczych pól |
|
Jak dotąd mieliśmy dostęp do pojedynczych rekordów ze zbioru, można jednak oglądać od razu dane z całego dokumentu XML - dane te należy wstawić do tabeli.
Tabelaryczne wiązanie danych XML
Kiedy wiążesz zbiór danych z tabelą HTML, w tabeli tej umieścić można cały ten zbiór. Oto przykład - w tabelę wstawimy dane z pliku klient.xml. Zaczniemy od utworzenia wysp danych XML z identyfikatorem customers:
<HTML>
<HEAD>
<TITLE>
Tabelaryczne wiązanie danych - wyspy danych XML
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Tabelaryczne wiązanie danych - wyspy danych XML
</H1>
<XML SRC="klient.xml" ID="klienci”></XML>
.
.
.
Aby związać dane z pliku klient.xml z tabelą, wystarczy ustawić atrybut DATASRC tabeli na customers:
<HTML>
<HEAD>
<TITLE>
Tabelaryczne wiązanie danych - wyspy danych XML
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Tabelaryczne wiązanie danych - wyspy danych XML
</H1>
<XML SRC="klient.xml" ID="klienci”></XML>
<TABLE DATASRC="#klienci” CELLSPACING="10">
.
.
.
Rekord z pliku klient.xml zawiera pola NAZWISKO, ID_KLIENTA, DATA_ZAKUPU, DZIAŁ i PRODUKT. Pola te powiążemy z poszczególnymi komórkami tabeli w taki oto sposób:
<HTML>
<HEAD>
<TITLE>
Tabelaryczne wiązanie danych - wyspy danych XML
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Tabelaryczne wiązanie danych - wyspy danych XML
</H1>
<XML SRC="klient.xml" ID="klienci”></XML>
<TABLE DATASRC="#klienci” CELLSPACING="10">
<THEAD>
<TR>
<TH>Nazwisko</TH>
<TH>ID klienta</TH>
<TH>Data zakupu</TH>
<TH>Dział</TH>
<TH>Produkt</TH>
</TR>
</THEAD>
<TBODY>
<TR>
<TD>
<SPAN DATAFLD="NAZWISKO"></SPAN>
</TD>
<TD>
<SPAN DATAFLD="ID_KLIENTA"></SPAN>
</TD>
<TD>
<SPAN DATAFLD="DATA_ZAKUPU"></SPAN>
</TD>
<TD>
<SPAN DATAFLD="DZIAŁ"></SPAN>
</TD>
<TD>
<SPAN DATAFLD="PRODUKT"></SPAN>
</TD>
</TR>
</TBODY>
</TABLE>
</CENTER>
</BODY>
</HTML>
Wyniki pokazano na rysunku 6.4; dane z pliku klient.xml zostały wyświetlone w postaci tabeli.
Rysunek 6.4. Wiązanie danych z tabelą w Internet Explorerze |
|
Istnieje jeszcze jeden obiekt DSO, którego można użyć do dokumentów XML w Internet Explorerze - DSO XML.
Wiązanie pojedynczych rekordów za pomocą DSO XML
Poczynając od wersji 4 Internet Explorera Microsoft włączył DSO XML przeznaczony do korzystania z XML. Obiekt ten jest nieco dziwny, gdyż nie jest wewnętrznym obiektem Explorera, ale jest apletem Javy. Aplet ten można włączać w stronę i obiekt DSO XML tworzyć w elemencie APPLET:
<APPLET
CODE="com.ms.xml.dso.XMLDSO.class"
ID="IDENTYFIKATOR"
WIDTH="0"
HEIGHT="0"
MAYSCRIPT="true">
<PARAM NAME="URL" VALUE="AdresURLStronyXML">
</APPLET>
Stosując znacznik <PARAM> przekazujemy apletowi parametr, stosując zaś atrybut ID znacznika <APPLET> określamy nazwę DSO.
W następnym przykładzie użyjemy DSO XML łącząc go z plikiem klient.xml. Aby powiązać nasz plik XML z elementami HTML, zaczniemy od dodania apletu XML do strony sieciowej - wywołamy DSO dsoKlient i przekażemy mu jako parametr adres URL dokumentu:
<HTML>
<HEAD>
<TITLE>
Wiązanie pojedynczych rekordów przy pomocy DSO XML
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Wiązanie pojedynczych rekordów przy pomocy DSO XML
</H1>
<APPLET
CODE="com.ms.xml.dso.XMLDSO.class"
ID="dsoKlient"
WIDTH="0"
HEIGHT="0"
MAYSCRIPT="true">
<PARAM NAME="URL" VALUE="klient.xml">
</APPLET>
.
.
.
To już właściwie wszystko. DSO udostępnia obiekt zbioru danych tak, jak to się dzieje w przypadku wysp danych XML, możemy zatem wiązać elementy HTML tak, jak poprzednio:
<HTML>
<HEAD>
<TITLE>
Wiązanie pojedynczych rekordów przy pomocy DSO XML
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Wiązanie pojedynczych rekordów przy pomocy DSO XML
</H1>
<APPLET
CODE="com.ms.xml.dso.XMLDSO.class"
ID="dsoKlient"
WIDTH="0"
HEIGHT="0"
MAYSCRIPT="true">
<PARAM NAME="URL" VALUE="klient.xml">
</APPLET>
Nazwisko: <INPUT TYPE="TEXT" DATASRC="#dsoKlient"
DATAFLD="NAZWISKO" SIZE="10">
<P>
ID: <INPUT TYPE="TEXT" DATASRC="#dsoKlient"
DATAFLD="ID_KLIENTA" SIZE="5">
<P>
Data zakupu: <SPAN DATASRC="#dsoKlient"
DATAFLD="DATA_ZAKUPU"></SPAN>
<P>
Dział: <SELECT DATASRC="#dsoKlient"
DATAFLD="DZIAŁ" SIZE="1">
<OPTION VALUE="Mięso">Mięso
<OPTION VALUE="Warzywa">Warzywa
<OPTION VALUE="Mrożonki">Mrożonki
</SELECT>
<P>
Produkt: <SPAN DATASRC="#dsoKlient" DATAFLD="PRODUKT">
</SPAN>
.
.
.
Można znowu użyć metod obiektu zbioru danych, takich jak moveNext, do poruszania się między rekordami; metody te znowu możemy powiązać z przyciskami:
<HTML>
<HEAD>
<TITLE>
Wiązanie pojedynczych rekordów przy pomocy DSO XML
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Wiązanie pojedynczych rekordów przy pomocy DSO XML
</H1>
<APPLET
CODE="com.ms.xml.dso.XMLDSO.class"
ID="dsoKlient"
WIDTH="0"
HEIGHT="0"
MAYSCRIPT="true">
<PARAM NAME="URL" VALUE="klient.xml">
</APPLET>
Nazwisko: <INPUT TYPE="TEXT" DATASRC="#dsoKlient"
DATAFLD="NAZWISKO" SIZE="10">
<P>
ID: <INPUT TYPE="TEXT" DATASRC="#dsoKlient"
DATAFLD="ID_KLIENTA" SIZE="5">
<P>
Data zakupu: <SPAN DATASRC="#dsoKlient"
DATAFLD="DATA_ZAKUPU"></SPAN>
<P>
Dział: <SELECT DATASRC="#dsoKlient"
DATAFLD="DZIAŁ" SIZE="1">
<OPTION VALUE="Mięso">Mięso
<OPTION VALUE="Warzywa">Warzywa
<OPTION VALUE="Mrożonki">Mrożonki
</SELECT>
<P>
Produkt: <SPAN DATASRC="#dsoKlient" DATAFLD="PRODUKT">
</SPAN>
<P>
<BUTTON ONCLICK="dsoKlient.recordset.moveFirst()"><<
</BUTTON>
<BUTTON ONCLICK="if (!dsoKlient.recordset.BOF)
dsoKlient.recordset.movePrevious()"><
</BUTTON>
<BUTTON ONCLICK="if (!dsoKlient.recordset.EOF)
dsoKlient.recordset.moveNext()">>
</BUTTON>
<BUTTON ONCLICK="dsoKlient.recordset.moveLast()">>>
</BUTTON>
</CENTER>
</BODY>
</HTML>
Działanie tej strony pokazano na rysunku 6.5. Aplet --> DSO XML[Author:T] działa zgodnie z oczekiwaniami, ale w niczym nie zmienia to faktu, że aplet ten jest obiektem zewnętrznym względem Explorera, co sugeruje, że Microsoft wcześniej czy później może porzucić dalszy jego rozwój na rzecz wysp XML.
Rysunek 6.5. Wiązanie pojedynczych rekordów przy pomocy DSO XML |
|
Tak jak wyspy danych XML, tak i DSO XML można wiązać z tabelami.
Tabelaryczne wiązanie danych za pomocą DSO XML
Wiązać XML DSO z tabelami jest równie łatwo, jak wiązać z tabelami wyspy danych. W poniższym przykładzie pokażemy, jak to działa. Powiążemy z tabelą dane z klient.xml, wyświetlimy jednocześnie wszystkie pola poszczególnych rekordów:
<HTML>
<HEAD>
<TITLE>
Wiązanie danych DSO XML z tabelami
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Wiązanie danych DSO XML z tabelami
</H1>
<APPLET CODE="com.ms.xml.dso.XMLDSO.class""
ID="klienci”
WIDTH="0" HEIGHT="0"
MAYSCRIPT="true">
<PARAM NAME="URL" VALUE="klient.xml">
</APPLET>
<TABLE DATASRC="#klienci” CELLSPACING="10">
<THEAD>
<TR>
<TH>Nazwisko</TH>
<TH>ID klienta</TH>
<TH>Data zakupu</TH>
<TH>Dział</TH>
<TH>Produkt</TH>
</TR>
</THEAD>
<TBODY>
<TR>
<TD>
<SPAN DATAFLD="NAZWISKO"></SPAN>
</TD>
<TD>
<SPAN DATAFLD="ID_KLIENTA"></SPAN>
</TD>
<TD>
<SPAN DATAFLD="DATA_ZAKUPU"></SPAN>
</TD>
<TD>
<SPAN DATAFLD="DZIAŁ"></SPAN>
</TD>
<TD>
<SPAN DATAFLD="PRODUKT"></SPAN>
</TD>
</TR>
</TBODY>
</TABLE>
</CENTER>
</BODY>
</HTML>
Teraz można już na rysunku 6.6 obejrzeć wyniki naszej pracy.
Rysunek 6.6. Wiązanie danych DSO XML z tabelą |
|
XML i dane hierarchiczne
Jedną z najciekawszych cech współczesnych baz danych jest możliwość tworzenia hierarchicznych rekordów zbiorów, w których pojedyncze rekordy mogą zawierać całe zbiory nowych rekordów. Dokumenty XML to idealny sposób zapisu takich hierarchicznych zbiorów, gdyż bez problemu można zawierać jeden zestaw elementów w innym.
Oto przykład. Dodajemy do danych klientów z pliku klient.xml dane o dostawach i wszystko zapisujemy w nowym dokumencie, dostawy.xml.
<?xml version="1.0" encoding="iso-8859-2"?>
<KLIENCI>
<KLIENT>
<NAZWISKO>Charles</NAZWISKO>
<REKORD>
<ID_KLIENTA>58704</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Mięso</DZIAŁ>
<PRODUKT>Szynka</PRODUKT>
<DOSTAWA>
<DATA>2001.10.20</DATA>
<SUMA>7.90 zł</SUMA>
</DOSTAWA>
<DOSTAWA>
<DATA>2001.10.25</DATA>
<SUMA>5.80 zł</SUMA>
</DOSTAWA>
</REKORD>
</KLIENT>
<KLIENT>
<NAZWISKO>Franklin</NAZWISKO>
<REKORD>
<ID_KLIENTA>58705</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Warzywa</DZIAŁ>
<PRODUKT>Pomidory</PRODUKT>
<DOSTAWA>
<DATA>2001.10.20</DATA>
<SUMA>12.00 zł</SUMA>
</DOSTAWA>
<DOSTAWA>
<DATA>2001.10.25</DATA>
<SUMA>11.80 zł</SUMA>
</DOSTAWA>
</REKORD>
</KLIENT>
<KLIENT>
<NAZWISKO>Phoebe</NAZWISKO>
<REKORD>
<ID_KLIENTA>58706</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Mięso</DZIAŁ>
<PRODUKT>Indyk</PRODUKT>
<DOSTAWA>
<DATA>2001.10.20</DATA>
<SUMA>22.00 zł</SUMA>
</DOSTAWA>
<DOSTAWA>
<DATA>2001.10.25</DATA>
<SUMA>34.00 zł</SUMA>
</DOSTAWA>
</REKORD>
</KLIENT>
<KLIENT>
<NAZWISKO>Mark</NAZWISKO>
<REKORD>
<ID_KLIENTA>58707</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Mięso</DZIAŁ>
<PRODUKT>Wołowina</PRODUKT>
<DOSTAWA>
<DATA>2001.10.20</DATA>
<SUMA>15.80 zł</SUMA>
</DOSTAWA>
<DOSTAWA>
<DATA>2001.10.25</DATA>
<SUMA>27.90 zł</SUMA>
</DOSTAWA>
</REKORD>
</KLIENT>
<KLIENT>
<NAZWISKO>Nancy</NAZWISKO>
<REKORD>
<ID_KLIENTA>58708</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Mrożonki</DZIAŁ>
<PRODUKT>Brokuły</PRODUKT>
<DOSTAWA>
<DATA>2001.10.20</DATA>
<SUMA>7.90 zł</SUMA>
</DOSTAWA>
<DOSTAWA>
<DATA>2001.10.25</DATA>
<SUMA>11.80 zł</SUMA>
</DOSTAWA>
</REKORD>
</KLIENT>
</KLIENCI>
W pokazywanym przykładzie element REKORD zawiera dwa elementy DOSTAWA, a te z kolei zawierają po jednym elemencie DATA i SUMA. Obiekt DSO nie może potraktować wielu tak umieszczonych rekordów jako rekordu pojedynczego, gdyż spowodowałoby to powstanie w jednym rekordzie kilku pól o tej samej nazwie. W Internet Explorerze można w takiej sytuacji użyć hierarchicznego zbioru rekordów, w których każdemu elementowi DOSTAWA odpowiada jeden podzbiór rekordów.
Powstaje zatem kwestia, jak w hierarchicznej bazie danych można się odwoływać do takich podzbiorów? Jak na przykład odwołać się do elementów DOSTAWA zawartych w poszczególnych elementach REKORD? Stosuje się odwołanie do nowego zbioru rekordów, na przykład REKORD.DOSTAWA. Wyrażenie to oznacza odwołanie do zbioru rekordów będącego dzieckiem elementów DOSTAWA.
Jak zwykle łatwiej wszystko to zrozumieć na przykładzie. Opiszemy powiązanie danych pliku dostawy.xml z tabelą i wyświetlanie danych o poszczególnych dostawach. Zaczynamy od powiązania tabeli z wyspą danych XML i wyświetlenia nazwisk klientów:
<HTML>
<HEAD>
<TITLE>
Użycie rekordów hierarchicznych w XML
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Użycie rekordów hierarchicznych w XML
</H1>
<XML SRC="dostawy.xml" ID=dsoKlient></XML>
<TABLE DATASRC="#dsoKlient" BORDER="1">
<TR>
<TH><DIV DATAFLD="NAZWISKO"></DIV></TH>
<TD>
.
.
.
Następnie wiążemy tabelę z polem REKORD bieżącego rekordu:
<HTML>
<HEAD>
<TITLE>
Użycie rekordów hierarchicznych w XML
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Użycie rekordów hierarchicznych w XML
</H1>
<XML SRC="dostawy.xml" ID=dsoKlient></XML>
<TABLE DATASRC="#dsoKlient" BORDER="1">
<TR>
<TH><DIV DATAFLD="NAZWISKO"></DIV></TH>
<TD>
<TABLE DATASRC="#dsoKlient" DATAFLD="REKORD">
.
.
.
Aby w każdym rekordzie DOSTAWA wyświetlić pola DATA i SUMA, wiążemy wewnętrzną tabelę ze zbiorem danych REKORD.DOSTAWA:
<HTML>
<HEAD>
<TITLE>
Użycie rekordów hierarchicznych w XML
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Użycie rekordów hierarchicznych w XML
</H1>
<XML SRC="dostawy.xml" ID=dsoKlient></XML>
<TABLE DATASRC="#dsoKlient" BORDER="1">
<TR>
<TH><DIV DATAFLD="NAZWISKO"></DIV></TH>
<TD>
<TABLE DATASRC="#dsoKlient" DATAFLD="REKORD">
<TR>
<TD>
<TABLE DATASRC="#dsoKlient"
CELLPADDING="5"
DATAFLD="REKORD.DOSTAWA">
<TR ALIGN="LEFT">
<TH>Data</TH>
<TH>Wartość</TH>
</TR>
<TR ALIGN="LEFT">
<TD><DIV DATAFLD="DATA"></DIV></TD>
<TD><DIV DATAFLD="SUMA"></DIV></TD>
</TR>
</TABLE>
</TD>
</TR>
</TABLE>
</TD>
</TR>
</TABLE>
</CENTER>
</BODY>
</HTML>
W Internet Explorerze dane pokażą się w takiej postaci, jak na rysunku 6.7. Obok każdego nazwiska podano daty i koszty poszczególnych dostaw - mamy hierarchiczne zestawy danych pochodzących z XML.
Rysunek 6.7. Wyświetlanie hierarchicznych zbiorów rekordów w Internet Explorerze |
|
Obsługa danych hierarchicznych o zmiennej długości
Pokazano już, jak DSO Internet Explorera obsługują hierarchiczne zbiory rekordów. Używane przez nas podzbiory zawierały po dwa rekordy, ale taki przykład odbiega nieco od rzeczywistości. Zwykle podzbiory mogą mieć bardzo różną długość. Jak ma w takiej sytuacji zachować się DSO? Przyjrzyj się następnemu dokumentowi, różnie.xml, w którym wewnętrzne zbiory mają od jednego do trzech rekordów DOSTAWA:
<?xml version="1.0" encoding="iso-8859-2"?>
<KLIENCI>
<KLIENT>
<NAZWISKO>Charles</NAZWISKO>
<REKORD>
<ID_KLIENTA>58704</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Mięso</DZIAŁ>
<PRODUKT>Szynka</PRODUKT>
<DOSTAWA>
<DATA>2001.10.20</DATA>
<SUMA>7.90 zł</SUMA>
</DOSTAWA>
<DOSTAWA>
<DATA>2001.10.25</DATA>
<SUMA>5.80 zł</SUMA>
</DOSTAWA>
<DOSTAWA>
<DATA>2001.10.25</DATA>
<SUMA>5.80 zł</SUMA>
</DOSTAWA>
</REKORD>
</KLIENT>
<KLIENT>
<NAZWISKO>Franklin</NAZWISKO>
<REKORD>
<ID_KLIENTA>58705</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Warzywa</DZIAŁ>
<PRODUKT>Pomidory</PRODUKT>
<DOSTAWA>
<DATA>2001.10.20</DATA>
<SUMA>12.00 zł</SUMA>
</DOSTAWA>
</REKORD>
</KLIENT>
<KLIENT>
<NAZWISKO>Phoebe</NAZWISKO>
<REKORD>
<ID_KLIENTA>58706</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Mięso</DZIAŁ>
<PRODUKT>Indyk</PRODUKT>
<DOSTAWA>
<DATA>2001.10.20</DATA>
<SUMA>22.00 zł</SUMA>
</DOSTAWA>
<DOSTAWA>
<DATA>2001.10.25</DATA>
<SUMA>34.00 zł</SUMA>
</DOSTAWA>
</REKORD>
</KLIENT>
<KLIENT>
<NAZWISKO>Mark</NAZWISKO>
<REKORD>
<ID_KLIENTA>58707</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Mięso</DZIAŁ>
<PRODUKT>Wołowina</PRODUKT>
<DOSTAWA>
<DATA>2001.10.20</DATA>
<SUMA>15.80 zł</SUMA>
</DOSTAWA>
<DOSTAWA>
<DATA>2001.10.25</DATA>
<SUMA>27.90 zł</SUMA>
</DOSTAWA>
</REKORD>
</KLIENT>
<KLIENT>
<NAZWISKO>Nancy</NAZWISKO>
<REKORD>
<ID_KLIENTA>58708</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Mrożonki</DZIAŁ>
<PRODUKT>Brokuły</PRODUKT>
<DOSTAWA>
<DATA>2001.10.20</DATA>
<SUMA>7.90 zł</SUMA>
</DOSTAWA>
<DOSTAWA>
<DATA>2001.10.25</DATA>
<SUMA>11.80 zł</SUMA>
</DOSTAWA>
<DOSTAWA>
<DATA>2002.03.05</DATA>
<SUMA>28800.00 zł</SUMA>
</DOSTAWA>
</REKORD>
</KLIENT>
</KLIENCI>
Tak naprawdę nie ma z tym problemu - oto strona, która pozwoli nam wyświetlić dane:
<HTML>
<HEAD>
<TITLE>
Zbiory hierarchiczne zmiennej wielkości
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Zbiory hierarchiczne zmiennej wielkości
</H1>
<XML SRC="różnie.xml" ID=dsoKlient></XML>
<TABLE DATASRC="#dsoKlient" BORDER="1">
<TR>
<TH><DIV DATAFLD="NAZWISKO"></DIV></TH>
<TD>
<TABLE DATASRC="#dsoKlient" DATAFLD="REKORD">
<TR>
<TD>
<TABLE DATASRC="#dsoKlient"
CELLPADDING="3"
DATAFLD="REKORD.DOSTAWA">
<TR ALIGN="LEFT">
<TH>Data</TH>
<TH>Wartość</TH>
</TR>
<TR ALIGN="LEFT">
<TD><DIV DATAFLD="DATA"></DIV></TD>
<TD><DIV DATAFLD="SUMA"></DIV></TD>
</TR>
</TABLE>
</TD>
</TR>
</TABLE>
</TD>
</TR>
</TABLE>
</CENTER>
</BODY>
</HTML>
Wyniki pokazano na rysunku 6.8 - każdy zbiór rekordów DOSTAWA wyświetlany jest prawidłowo mimo różnej ich wielkości.
Rysunek 6.8. Hierarchiczne zbiory rekordów w Internet Explorerze |
|
Ten sam wynik można by uzyskać stosując zamiast wysp danych XML aplet DSO XML:
<HTML>
<HEAD>
<TITLE>
Zbiory hierarchiczne zmiennej wielkości
</TITLE>
</HEAD>
<BODY>
<CENTER>
<H1>
Zbiory hierarchiczne zmiennej wielkości
</H1>
<APPLET CODE="com.ms.xml.dso.XMLDSO.class"
ID="klienci”
WIDTH="0" HEIGHT="0"
MAYSCRIPT="true">
<PARAM NAME="URL" VALUE="różnie.xml">
</APPLET>
<TABLE DATASRC="#klienci” BORDER="1">
<TR>
<TH><DIV DATAFLD="NAZWISKO"></DIV></TH>
<TD>
<TABLE DATASRC="#klienci” DATAFLD="REKORD">
<TR ALIGN="CENTER">
<TD>Sprzedaż</TD>
</TR>
<TR>
.
.
.
</TR>
</TABLE>
</TD>
</TR>
</TABLE>
</CENTER>
</BODY>
</HTML>
Przeszukiwanie danych XML
Stosując zbiory rekordów można zrobić wiele ciekawych rzeczy, czym zresztą w tym rozdziale się zajmowaliśmy. Na koniec jeszcze przyjrzymy się możliwością wyszukiwania specyficznych danych w bazie danych. Będziemy wyszukiwać klienta, którego nazwisko pasować będzie do podanych przez użytkownika warunków wyboru.
Zmodyfikujemy nasz plik klient.xml - dodamy drugiego klienta o nazwisku Nancy, aby upewnić się, że zawsze „wyłapujemy” wszystkie przypadki wystąpienia poszukiwanej danej. Nowy plik będzie nazywał się wiele.xml:
<?xml version="1.0" encoding="iso-8859-2"?>
<KLIENCI>
<KLIENT>
<NAZWISKO>Charles</NAZWISKO>
<ID_KLIENTA>58704</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Mięso</DZIAŁ>
<PRODUKT>Szynka</PRODUKT>
</KLIENT>
<KLIENT>
<NAZWISKO>Franklin</NAZWISKO>
<ID_KLIENTA>58705</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Warzywa</DZIAŁ>
<PRODUKT>Pomidory</PRODUKT>
</KLIENT>
<KLIENT>
<NAZWISKO>Phoebe</NAZWISKO>
<ID_KLIENTA>58706</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Mięso</DZIAŁ>
<PRODUKT>Indyk</PRODUKT>
</KLIENT>
<KLIENT>
<NAZWISKO>Mark</NAZWISKO>
<ID_KLIENTA>58707</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Mięso</DZIAŁ>
<PRODUKT>Wołowina</PRODUKT>
</KLIENT>
<KLIENT>
<NAZWISKO>Nancy</NAZWISKO>
<ID_KLIENTA>58708</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Mrożonki</DZIAŁ>
<PRODUKT>Brokuły</PRODUKT>
</KLIENT>
<KLIENT>
<NAZWISKO>Nancy</NAZWISKO>
<ID_KLIENTA>58709</ID_KLIENTA>
<DATA_ZAKUPU>2001.10.15</DATA_ZAKUPU>
<DZIAŁ>Warzywa</DZIAŁ>
<PRODUKT>Pomidory</PRODUKT>
</KLIENT>
</KLIENCI>
Po przygotowaniu wyspy danych i powiązaniu jej z plikiem wiele.xml utworzymy nową funkcję znajdzPasujace, która wyszukiwać będzie nazwisko klienta, który interesuje użytkownika. Wprawdzie zbiory rekordów ADOR mają metodę find służącą do przeszukiwania baz danych, ale warunki wyszukiwania podaje się tej metodzie w postaci wyrażenia SQL (język SQL jest typowym językiem do obsługi baz danych), natomiast Internet Explorer takich wyrażeń nie potrafi obsłużyć. Wobec tego utworzymy pętlę języka JavaScript, w której będziemy wyszukiwać pasujące nazwiska klientów.
Użytkownik może podać nazwisko, które chce znaleźć, w polu tekstowym - nazwiemy je text1. Kiedy użytkownik kliknie przycisk, wywołana zostanie funkcja znajdzPasujace. Podane przez użytkownika nazwisko zamienimy na małe litery (użyjemy metody toLowerCase obiektu String), aby wynik wyszukiwania nie zależał od sposobu zapisania danych, wynik konwersji zapiszemy w zmiennej szukajTego:
<HTML>
<HEAD>
<TITLE>
Wyszukiwanie danych w bazach XML
</TITLE>
<XML ID="klienci” SRC="wiele.xml"></XML>
<SCRIPT LANGUAGE="JavaScript">
function znajdzPasujace()
{
var szukajTego = form1.text1.value.toLowerCase()
.
.
.
Teraz zrobimy pętlę działającą na wszystkich rekordach ze zbioru, wartość pola NAZWISKO z każdego rekordu zapisywać będziemy w zmiennej obecnaNazwa, przy czym nazwisko to zamieniać będziemy na małe litery:
<HTML>
<HEAD>
<TITLE>
Wyszukiwanie danych w bazach XML
</TITLE>
<XML ID="klienci” SRC="wiele.xml"></XML>
<SCRIPT LANGUAGE="JavaScript">
function znajdzPasujace()
{
var szukajTego = form1.text1.value.toLowerCase()
while (!klienci.recordset.EOF) {
var obecnaNazwa = new String(klienci.recordset("NAZWISKO"))
obecnaNazwa = obecnaNazwa.toLowerCase()
.
.
.
klienci.recordset.moveNext()
}
}
</SCRIPT>
</HEAD>
.
.
.
Aby sprawdzić, czy bieżące nazwisko pasuje do nazwiska poszukiwanego przez użytkownika, użyjemy metody indexOf obiektu String. Metoda ta zwróci wartość 0 lub większą, jeśli napis da się dopasować:
<HTML>
<HEAD>
<TITLE>
Wyszukiwanie danych w bazach XML
</TITLE>
<XML ID="klienci” SRC="wiele.xml"></XML>
<SCRIPT LANGUAGE="JavaScript">
function znajdzPasujace()
{
var szukajTego = form1.text1.value.toLowerCase()
while (!klienci.recordset.EOF) {
var obecnaNazwa = new String(klienci.recordset("NAZWISKO"))
obecnaNazwa = obecnaNazwa.toLowerCase()
if (obecnaNazwa.indexOf(szukajTego) >= 0) {
.
.
.
}
klienci.recordset.moveNext()
}
}
</SCRIPT>
</HEAD>
.
.
.
Teraz pozostaje już tylko wyświetlić pasujące rekordy przy pomocy elementu <DIV>, jak to robiliśmy dotąd. Trzeba też dodać przycisk i pole tekstowe, aby użytkownik mógł z naszym kodem się porozumieć:
<HTML>
<HEAD>
<TITLE>
Wyszukiwanie danych w bazach XML
</TITLE>
<XML ID="klienci” SRC="wiele.xml"></XML>
<SCRIPT LANGUAGE="JavaScript">
function znajdzPasujace()
{
var szukajTego = form1.text1.value.toLowerCase()
while (!klienci.recordset.EOF) {
var obecnaNazwa = new String(klienci.recordset("NAZWISKO"))
obecnaNazwa = obecnaNazwa.toLowerCase()
if (obecnaNazwa.indexOf(szukajTego) >= 0) {
komunikatDiv.innerHTML +=
klienci.recordset("NAZWISKO") + " (ID " +
klienci.recordset("ID_KLIENTA") + ") kupił(a) " +
klienci.recordset("PRODUKT") + " z działu " +
klienci.recordset("DZIAŁ") + " dnia " +
klienci.recordset("DATA_ZAKUPU") + ".<BR>"
}
klienci.recordset.moveNext()
}
}
</SCRIPT>
</HEAD>
<BODY>
<CENTER>
<H1>
Wyszukiwanie danych w bazach XML
</H1>
<FORM ID="form1">
Szukane nazwisko: <INPUT TYPE="TEXT" NAME="text1">
<BR>
<BR>
<INPUT TYPE="BUTTON" VALUE="Wyszukaj"
ONCLICK="znajdzPasujace()">
</FORM>
</CENTER>
<DIV ID="komunikatDiv"></DIV>
</BODY>
</HTML>
Wyniki pokazano na rysunku 6.9 - odnalezione zostały oba rekordy, które znalezione być powinny.
Rysunek 6.9. Wyszukiwanie danych w bazach danych XML |
|
W tym przykładzie użyliśmy wysp danych, ale oczywiście równie dobrze do załadowania danych z pliku wiele.xml można byłoby użyć apletu DSO XML. Tym razem pokażemy jeszcze jedną cechę tego apletu: jak dotąd podawaliśmy zerową wysokość i zerową szerokość, ale przez to aplet ten nie wyświetla wyników swojego działania, a wystarczyłoby przyznać mu nieco miejsca na stronie:
<HTML>
<HEAD>
<TITLE>
Wyszukiwanie danych w bazach XML
</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function znajdzPasujace()
{
var szukajTego = form1.text1.value.toLowerCase()
while (!klienci.recordset.EOF) {
var obecnaNazwa = new String(klienci.recordset("NAZWISKO"))
obecnaNazwa = obecnaNazwa.toLowerCase()
if (obecnaNazwa.indexOf(szukajTego) >= 0) {
komunikatDiv.innerHTML +=
klienci.recordset("NAZWISKO") + " (ID " +
klienci.recordset("ID_KLIENTA") + ") kupił(a) " +
klienci.recordset("PRODUKT") + " z działu " +
klienci.recordset("DZIAL") + " dnia " +
klienci.recordset("DATA_ZAKUPU") + ".<BR>"
}
klienci.recordset.moveNext()
}
}
</SCRIPT>
</HEAD>
<BODY>
<CENTER>
<H1>
Wyszukiwanie danych w bazach XML
</H1>
<APPLET CODE="com.ms.xml.dso.XMLDSO.class"
ID="klienci”
WIDTH="400" HEIGHT="50"
MAYSCRIPT="true">
<PARAM NAME="URL" VALUE="wiele.xml">
</APPLET>
<FORM ID="form1">
Szukane nazwisko: <INPUT TYPE="TEXT" NAME="text1">
<BR>
<BR>
<INPUT TYPE="BUTTON" VALUE="Wyszukaj"
ONCLICK="znajdzPasujace()">
</FORM>
</CENTER>
<DIV ID="komunikatDiv"></DIV>
</BODY>
</HTML>
Wyniki pokazano na rysunku 6.10. Obiekt DSO XML wyświetlił komunikat o prawidłowym załadowaniu pliku XML (Successfully loaded XML from...), tło apletu jest zielone, gdyż nie wystąpił żaden błąd - gdyby jakiś się pojawił, pojawiłby się w aplecie jego komunikat.
Rysunek 6.10. Wyszukiwanie danych w bazach XML przy użyciu DSO XML |
|
I w ten oto sposób zakończyliśmy omawianie wiązania danych w Internet Explorerze.
Niestety, pojawiają się w tym przypadku kłopoty z polskimi literami, co widać na rysunku. Niepoprawnie wyświetlone są polskie litery w tabeli z danymi, choć są już poprawne w statycznym kodzie HTML. Co gorsza, nie są obsługiwane znaczniki zawierające polskie litery, w naszym przypadku element DZIAŁ. Dlatego w kodzie stosujemy element DZIAL, taka sama zmiana była oczywiście konieczna także w źródle danych, czyli w dokumencie klient.xml. (przyp. tłum.)
Pamiętać trzeba o braku obsługi polskich liter w przypadku Javy na Windows 98 - konieczna była korekta pliku XML (zmiana DZIAŁ na DZIAL) (przyp. tłum.)
Jeśli nie zmienisz znaczników <DZIAŁ> na <DZIAL>, to mimo poprawnego kodowania polskich liter zgodnie z normą ISO 8859-2 tło apletu będzie czerwone i komunikat poinformuje nas o wystąpieniu nieprawidłowego znaku. (przyp. tłum.)
32 Część I ♦ Podstawy obsługi systemu WhizBang (Nagłówek strony)
Rozdział 1 ♦ Pierwsze kroki (Nagłówek strony)
32 C:\Moje dokumenty\Wojtek Romowicz\Książki\XML Vademecum profesjonalisty\r06-01.doc
C:\Moje dokumenty\Wojtek Romowicz\Książki\XML Vademecum profesjonalisty\r06-01.doc 1