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


Rozdział --> 5[Author:T] .
Obsługa dokumentów XML w JavaScripcie

Kiedy już znasz JavaScript, przynajmniej w zakresie potrzebnym do naszych potrzeb, możemy zacząć pracę z Obiektowym modelem dokumentu (DOM), standardem interfejsu programistycznego do obsługi dokumentów XML opracowanym przez W3C. Zanim powstał standard DOM, parsery i procesory różnie traktowały dokumenty XML, a co gorsza wszystko się stale zmieniało. Wraz z przedstawieniem DOM XML nareszcie wprowadzono jakiś standard obsługi. Pamiętaj, że w tym rozdziale opieramy się na Internet Explorerze Microsoftu, w którym standard DOM został najpełniej zaimplementowany i udostępniony przez JavaScript.

DOM W3C

W referencji DOM W3C powiedziano, że dokument XML ma być traktowany jako drzewo węzłów. Każdy fragment danych jest węzłem, elementy dzieci i tekst zawarty w elementach stają się podwęzłami. Traktowanie dokumentu XML jako drzewa jest rozwiązaniem dobrym (choć nie jedynym, o czym przekonamy się, kiedy przejdziemy do Javy), gdyż stosunkowo łatwo jest wskazać, które elementy zawarte są w których - element zawarty w innym jest jego podwęzłem. W modelu DOM wszystko, co znajduje się w dokumencie, staje się węzłem: elementy, atrybuty, tekst i tak dalej. Oto rodzaje węzłów przewidziane w specyfikacji DOM W3C:

Przyjrzyj się na przykład takiemu oto dokumentowi:

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

<DOKUMENT>

<POZDROWIENIA>

Witaj w XML

<KOMUNIKAT>

</POZDROWIENIA>

Witaj w pokręconym świecie XML.

</KOMUNIKAT>

</DOKUMENT>

Mamy tu węzeł instrukcji przetwarzania i węzeł elementu głównego DOKUMENT. Węzeł DOKUMENT ma dwa podwęzły, POZDROWIENIA i KOMUNIKAT. Oba te węzły dzieci określane są jako bliźniacze. Zarówno węzeł POZDROWIENIA, jak i KOMUNIKAT mają po jednym podwęźle - są to węzły tekstowe zawierające dane tekstowe. W tym rozdziale będziemy dokumenty traktować właśnie jako takie drzewa węzłów; drzewo tego dokumentu pokazano na rysunku 5.1.

Rysunek 5.1.

Dokument jako drzewo węzłów

<DOKUMENT>

< POZDROWIENIA >

< KOMUNIKAT >

Witaj w XML

Witaj w pokręconym
świecie XML.

DOKUMENT

POZDROWIENIA

KOMUNIKAT

Witaj w XML

Witaj w pokręconym
świecie XML.

Każdy fragment danych traktowany jest jako węzeł. Używając metod zdefiniowanych w DOM W3C można poruszać się po poszczególnych gałęziach drzewa dokumentu - przykładem takiej metody jest nextChild powodująca przesunięcie się do następnego dziecka lub lastSibling powodująca przeniesienie do ostatniego węzła bliźniaczego danego węzła bieżącego. Taka praca z dokumentem wymaga nieco praktyki, dlatego właśnie temu zagadnieniu będzie poświęcony cały ten rozdział.

Istnieje szereg różnych poziomów (Level) DOM:

Praktycznie rzecz biorąc jedyną względnie kompletną implementacją DOM XML jest implementacja w Internet Explorerze w wersji 5 i nowszych. Dokumentacja DOM Microsoftu obecnie dostępna jest pod adresem http://msdn.microsoft.com/library/psdk/xmlsdk/xmld20ab.htm, ale strony tej firmy notorycznie są reorganizowane, więc być może będziesz musiał sam tej dokumentacji poszukać. Jeśli tak się stanie, wejdź po prostu na stronę http://msdn.microsoft.com i wyszukaj frazy „xml dom” (należy przyjąć, że adresom URL ze stron Microsoftu nie należy ufać dłużej niż przez dwa miesiące).

Jako że Internet Explorer dobrze obsługuje DOM Level 1, to tej wersji będziemy używać w tym rozdziale. Należy mieć nadzieję, że przełożenie tego na inną przeglądarkę zgodną ze specyfikacją W3C nie okaże się zmaganiem z augiaszowymi stajniami.

Obiekty DOM XML

Oto obiekty DOM W3C Level 1:

Obiekt

Opis

Document

Cały dokument.

DocumentFragment

Fragment dokumentu.

DocumentType

Odwołanie do znacznika <!DOCTYPE>.

EntityReference

Odwołanie do encji.

Element

Element.

Attr

Atrybut.

ProcessingInstruction

Instrukcja przetwarzania.

Comment

Treść komentarza XML.

Text

Treść elementu lub wartość atrybutu.

CDATAsection

Sekcja CDATA.

Entity

Encja parsowana lub nieparsowana.

Notation

Notacja

Node

Węzeł drzewa.

NodeList.

Lista obiektów Node. Umożliwia realizację iteracji oraz operacje dostępu przez indeksy.

NamedNodeMap

Umożliwia iteracje i sięganie przez nazwę do zestawu atrybutów.

Microsoft używa do tych obiektów innych nazw, a także dodaje własne obiekty. W szczególności zdefiniowano „obiekty podstawowe”, które stanowią fundament całego DOM XML. Obiektem najwyższego poziomu jest DOMDocument, jest to jedyny obiekt, który można stworzyć bezpośrednio - dostęp do wszystkich innych realizowany jest za jego pośrednictwem. Oto lista obiektów podstawowych Internet Explorera:

Obiekt

Opis

DOMDocument

Węzeł główny drzewka DOM.

XMLDOMNode

Pojedynczy węzeł drzewa dokumentu. Zawiera informacje o typach danych, przestrzeniach nazw, DTD i schematach XML.

XMLDOMNodeList

Lista obiektów węzłów. Umożliwia realizację iteracji i dostęp przez indeksy.

XMLDOMNamedNodeMap

Umożliwia iteracje i dostęp do zestawu atrybutów przez nazwę.

XMLDOMParseError

Informacja o ostatnim błędzie. Zawiera numer błędu, numer wiersza, numer znaku oraz tekst opisowy.

XMLHttpRequest

Umożliwia komunikowanie się z serwerami HTTP.

XTLRuntime

Obsługuje metody, które można wywoływać z arkuszy stylów XSL.

Oprócz obiektów podstawowych DOM XML Microsoftu zawiera także obiekty XML DOM, którymi posługuje się podczas pracy z dokumentami. Są to między innymi różne rodzaje węzłów, takie jak XMLDOMAttribute, XMLDOMCharacterData i XMLDOMElement:

Obiekt

Opis

XMLDOMAttribute

Obiekt atrybutu.

XMLDOMCDATASection

Sekcja CDATA, której treść nie jest interpretowana.

XMLDOMCharacterData

Zawiera metody umożliwiające operacje na tekście.

XMLDOMComment

Podaje treść komentarza XML.

XMLDOMDocumentFragment

Niewielki obiekt wygodny do wstawiania fragmentów drzewka.

XMLDOMDocumentType

Informacje związane z deklaracją typu dokumentu.

XMLDOMElement

Obiekt elementu.

XMLDOMEntity

Oznacza parsowaną lub nieparsowaną encję dokumentu.

XMLDOMEntityReference

Węzeł odwołania do encji.

XMLDOMImplementation

Metody ogólne DOM.

XMLDOMNotation

Notacja (zadeklarowana w DTD lub w schemacie XML).

XMLDOMProcessingInstruction

Instrukcja przetwarzania.

XMLDOMText

Treść elementu lub wartość atrybutu.

W tym rozdziale wykorzystamy wiele spośród tych obiektów. Zobaczysz, jak za pomocą DOM XML Microsoftu dokumenty XML parsować i wykorzystywać, a także jak obsługiwać zdarzenia podczas ładowania dokumentu. Zobaczysz też, jak na bieżąco modyfikować dokument XML.

Podana wyżej lista obiektów jest bardzo ważna, każdy z tych obiektów ma zdefiniowane przez W3C właściwości, metody i zdarzenia, wiele dodał także od siebie Microsoft (zatem te dodatki są niestandardowe). Jeśli mamy pracować w DOM XML, konieczne jest dobre zrozumienie znaczenia tych elementów. Teraz dokładniej omówimy najważniejsze obiekty, zaczniemy oczywiście od obiektu głównego - DOMDocument.

Obiekt DOMDocument

Obiekt DOMDocument to główny obiekt, z którym przyjdzie Ci pracować, reprezentuje on węzeł główny drzewka dokumentu. Jest to jedyny obiekt, do którego podczas pracy z DOM odwołujesz się bezpośrednio.

Dokumenty można w Internet Explorerze tworzyć na dwa sposoby: przy pomocy klasy Microsoft.XMLDOM i stosując wyspy danych XML. W przypadku tworzenia obiektu dokumentu za pomocą klasy Microsoft.XMLDOM jawnie ładuje się dokumentu za pomocą metody load:

function wczytajDokumentXML()

{

var xmldoc

xmldoc = newActiveXObject("Microsoft.XMLDOM")

xmldoc.load("spotkania.xml")

.

.

.

Później zobaczysz, jak za pomocą znacznika HTML <XML> można stworzyć wyspę danych w Internet Explorerze i jak stosując właściwość XMLDocument tego elementu uzyskać dostęp do obiektu dokumentu:

<XML ID="spotkaniaXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

function wczytajDokumentXML()

{

xmldoc = document.all("spotkaniaXML").XMLDocument

.

.

.

DOM XML i programy wielowątkowe

Istnieje też --> „wielowątkowa”[Author:T] wersja klasy Microsoft.XMLDOM, której można używać w programach wielowątkowych:

var xmldoc = new ActiveXObject("Microsoft.FreeThreadedXMLDOM")

Więcej informacji na ten temat znajdziesz na stronie Microsoftu http://msdn.microsoft.com/library/psdk/xmlsdk/xmld20ab.htm (pamiętaj o możliwości zmiany tego adresu).

Oto właściwości tego obiektu (gwiazdką oznaczono rozszerzenia Microsoftu; druga kolumna oznacza rodzaj właściwości: O=tylko do odczytu, OZ=do odczytu i zapisu):

Obiekt

O/Z

Opis

async*

OZ

Czy dopuszczalne jest ładowanie asynchroniczne.

attributes

O

Lista atrybutów węzła.

baseName*

O

Nazwa bazy kwalifikowana przestrzenią nazw.

childNodes

O

Lista węzłów zawierająca węzły dzieci, które mogą mieć własne dzieci.

dataType*

OZ

Typ danych węzła.

definition*

O

Definicja węzła w DTD lub schemacie.

doctype

O

Typ węzła dokumentu - wskazuje DTD.

documentElement

OZ

Element główny dokumentu.

firstChild

O

Pierwsze dziecko bieżącego węzła.

implementation

O

Obiekt XMLDOMImplementation danego dokumentu.

lastChild

O

Ostatni węzeł dziecko węzła bieżącego.

namespaceURI*

O

Adres URI przestrzeni nazw.

nextSibling

O

Następny węzeł bliźniaczy węzła bieżącego.

nodeName

O

Kwalifikowana nazwa elementu, atrybutu lub odwołania do encji. Dla innych rodzajów węzłów zawiera tekst stały.

nodeType

O

Rodzaj węzła DOM XML.

nodeTypedValue*

OZ

Wartość węzła.

nodeTypeString*

O

Typ węzła w postaci napisu.

nodeValue

O

Tekst węzła.

ondataavailable*

OZ

Procedura obsługi zdarzenia ondataavailable.

onreadystatechange*

OZ

Procedura obsługi zdarzenia, kiedy zmienia się wartość właściwości readyState.

ontransformnode*

OZ

Procedura obsługi zdarzenia ontransformnode.

ownerDocument

O

Węzeł główny dokumentu zawierającego węzeł bieżący.

parentNode

O

Węzeł rodzic (tylko dla węzłów mających rodzica).

parsed*

O

Ma wartość true, jeśli wszyscy potomkowie węzła zostali już przeanalizowani; w przeciwnym wypadku ma wartość false.

parseError*

O

Obiekt XMLDOMParseError zawierający informacje o błędzie, jaki wystąpił ostatnio.

prefix*

O

Przedrostek przestrzeni nazw.

preserveWhiteSpace*

OZ

Jeśli podczas przetwarzania zachowane mają być białe znaki, ma wartość true.

previousSibling

O

Poprzedni węzeł bliźniaczy węzła bieżącego.

readyState*

O

Bieżący stan dokumentu XML.

resolveExternals*

OZ

Czy definicje zewnętrzne mają być rozwijane podczas parsowania.

specified*

O

Czy węzeł został podany jawnie, czy też wygenerowany na podstawie wartości domyślnej.

text*

OZ

Zawartość tekstowa węzła i jego poddrzewek.

url*

O

Kanoniczna postać adresu URL ostatnio ładowanego dokumentu XML.

validateOnParse*

OZ

Czy parser ma przeprowadzić także walidację dokumentu.

xml*

O

Reprezentacja węzła i jego potomków jako kodu XML.

Oto metody tego obiektu (gwiazdką oznaczono rozszerzenia Microsoftu):

Metoda

Opis

abort*

Przerywa ładowanie asynchroniczne.

appendChild

Dodaje dziecko jako ostatnie dziecko bieżącego węzła.

cloneNode

Zwraca nowy węzeł będący kopią węzła wskazanego.

createAttribute

Zwraca nowy atrybut o danej nazwie.

createCDATASection

Zwraca węzeł sekcji CDATA zawierającej przekazane dane.

createComment

Zwraca węzeł komentarza.

createDocumentFragment

Zwraca pusty obiekt DocumentFragment.

createElement

Zwraca element węzła o podanej nazwie.

createEntityReference

Zwraca obiekt EntityReference.

createNode*

Zwraca węzeł określonego typu, o danej nazwie i przestrzeni nazw.

createProcessingInstruction

Zwraca węzeł instrukcji przetwarzania.

createTextNode

Zwraca węzeł tekstowy zawierający przekazane dane.

getElementsByTagName

Tworzy kolekcję elementów o danej nazwie.

hasChildNodes

Zwraca true, jeśli węzeł ma dzieci.

insertBefore

Wstawia węzeł dziecko przed danym węzłem.

load*

Ładuje dokument XML spod danego adresu.

loadXML*

Ładuje dokument XML podany w przekazanym napisie.

nodeFromID*

Pobiera węzły, których atrybut ID pasuje do podanej wartości.

removeChild

Usuwa dany węzeł dziecko spośród listy dzieci.

replaceChild

Podmienia dany węzeł dziecko na nowy węzeł o podanych właściwościach.

save*

Zapisuje dokument XML pod podanym adresem.

selectNodes*

Stosuje podaną operację dopasowywania wzorca do kontekstu węzła, zwraca listę pasujących węzłów.

selectSingleNode*

Stosuje podaną operację dopasowywania wzorca do kontekstu węzła, zwraca pierwszy pasujący węzeł.

transformNode*

Przekształca węzeł i jego dzieci stosując podany arkusz stylów XSL.

transformNodeToObject*

Przekształca węzeł i jego dzieci na obiekt za pomocą danego arkusza stylów XSL.

Oto zdarzenia tego obiektu (gwiazdką oznaczono rozszerzenia Microsoftu):

Zdarzenie

Opis

ondataavailable*

Informuje, że dane dokumentu XML są już dostępne.

onreadystatechange*

Informuje o zmianie właściwości readyState.

ontransformnode*

Zachodzi przed zastosowaniem arkusza stylów do kolejnych węzłów źródłowego XML.

Obiekt XMLDOMNode

Obiekt Microsoftu XMLDOMNode stanowi rozszerzenie podstawowego interfejsu aplikacji węzła DOM XML, gdyż dodaje typy danych, przestrzenie nazw, DTD i schematy. Podczas analizy drzewa dokumentu często będziemy tego obiektu odwoływali.

Oto właściwości tego obiektu (gwiazdką oznaczono rozszerzenia Microsoftu; druga kolumna oznacza rodzaj właściwości: O=tylko do odczytu, OZ=do odczytu i zapisu):

Obiekt

O/Z

Opis

attributes

O

Lista atrybutów danego węzła.

baseName*

O

Bazowa nazwa kwalifikowana przestrzenią nazw.

childNodes

O

Lista węzłów zawierająca węzły dzieci węzła bieżącego.

dataType*

OZ

Typ danych bieżącego węzła.

definition*

O

Definicja węzła w DTD lub schemacie.

firstChild

O

Pierwsze dziecko bieżącego węzła.

lastChild

O

Ostatnie dziecko bieżącego węzła.

namespaceURI*

O

Adres URI przestrzeni nazw.

nextSibling

O

Następny węzeł bliźniaczy węzła bieżącego.

nodeName

O

Kwalifikowana nazwa elementu, atrybutu lub odwołania się do encji, w przypadku innych typów węzłów napis.

nodeType

O

Rodzaj węzła DOM XML.

nodeTypedValue*

OZ

Wartość węzła.

nodeTypeString*

O

Typ węzła w postaci napisu.

nodeValue

OZ

Tekst związany z węzłem.

ownerDocument

O

Element główny dokumentu.

parentNode

O

Węzeł rodzic.

parsed*

O

Ma wartość true, jeśli dany węzeł i wszyscy jego potomkowie byli parsowani, w przeciwnym wypadku false.

prefix*

O

Przedrostek przestrzeni nazw.

previousSibling

O

Poprzedni węzeł bliźniaczy węzła bieżącego.

specified*

OZ

Czy wartość węzła podana została jawnie, czy określono ją na podstawie wartości domyślnej.

text*

OZ

Tekstowa zawartość węzła i jego poddrzewek.

xml*

O

Węzeł wraz ze swoimi potomkami w postaci kodu XML.

Oto metody tego obiektu (gwiazdką oznaczono rozszerzenia Microsoftu):

Metoda

Opis

appendChild

Dodaje nowe dziecko jako ostatnie dziecko danego węzła.

cloneNode

Tworzy nowy węzeł będący kopią bieżącego.

hasChildNodes

Zwraca wartość true, jeśli węzeł ma dzieci.

insertBefore

Wstawia węzeł dziecko przed węzłem danym.

removeChild

Usuwa dany węzeł dziecko.

replaceChild

Podmienia dany węzeł dziecko na inny nowy węzeł.

selectNodes*

Przeprowadza operację dopasowywania wzorca na kontekście węzła, zwraca listę pasujących węzłów.

selectSingleNode*

Przeprowadza operację dopasowywania wzorca na kontekście węzła, zwraca pierwszy pasujący węzeł.

transformNode*

Przekształca dany węzeł i jego dzieci za pomocą podanego arkusza stylów XSL.

transformNodeToObject*

Przekształca węzeł i jego dzieci przy pomocy podanego arkusza stylów XSL, zwraca wynik w postaci obiektu.

Z obiektem tym nie są związane żadne zdarzenia.

Obiekt XMLDOMNodeList

Z obiektu XMLDOMNodeList korzysta się w celu obsługi listy węzłów. Listy węzłów są przydatne przede wszystkim dlatego, że każdy węzeł może mieć wiele węzłów dzieci i stosując listę możesz wszystkie dzieci przetwarzać jednocześnie.

W poniższym przykładzie ładujemy dokument i pobieramy do listy węzłów wszystkie elementy OSOBA, używamy metody getElementsByTagName:

function readXMLDocument()

{

var xmldoc, nodeList

xmldoc = new ActiveXObject("Microsoft.XMLDOM")

xmldoc.load("spotkania.xml")

nodeList = xmlDoc.getElementsByTagName("OSOBA")

.

.

.

Obiekt XMLDOMNodeList ma tylko jedną właściwość, length, która określa liczbę pozycji w kolekcji, jest to właściwość tylko do odczytu.

Oto metody tego obiektu (gwiazdką oznaczono rozszerzenia Microsoftu):

Metoda

Opis

item

Umożliwia swobodny dostęp do węzłów kolekcji.

nextNode*

Wskazuje następny węzeł w kolekcji.

reset*

Powoduje przerwanie iteracji listy.

Z obiektem tym nie są związane żadne zdarzenia.

Obiekt XMLDOMNamedNodeMap

DOM XML Microsoftu zawiera także obiekt XMLDOMNamedNodeMap do obsługi przestrzeni nazw.

Obiekt ten ma następujące właściwości (gwiazdką oznaczono rozszerzenia Microsoftu; druga kolumna oznacza rodzaj właściwości: O=tylko do odczytu, OZ=do odczytu i zapisu):

Obiekt

O/Z

Opis

length

O

Podaje liczbę pozycji w kolekcji.

item

O

Umożliwia dostęp swobodny do węzłów kolekcji.

Oto metody tego obiektu (gwiazdką oznaczono rozszerzenia Microsoftu):

Metoda

Opis

getNamedItem

Pobiera atrybut o podanej nazwie.

getQualifiedItem*

Pobiera atrybut o danej nazwie z podanej przestrzeni nazw.

nextNode

Pobiera następny węzeł.

removeNamedItem

Usuwa atrybut.

removeQualifiedItem

Usuwa atrybut o danej nazwie z podanej przestrzeni nazw.

reset

Powoduje przerwanie iteracji listy.

setNamedItem

Dodaje podany węzeł.

Z obiektem tym nie są związane żadne zdarzenia.

Obiekt XMLDOMParseError

Microsoftowy obiekt XMLDOMParseError zawiera informacje dotyczące błędu parsowania, który wystąpił jako ostatni. Wśród tych informacji jest numer błędu, numer wiersza, pozycja znaku i opis tekstowy. Choć nie jest to oczywiste dla osób ładujących dokument XML do Internet Explorera, przeglądarka przeprowadza walidację względem załączonego DTD lub schematu XML - po prostu Explorer domyślnie nie wyświetla żadnych komunikatów dotyczących walidacji. Stosując jednak obiekt XMLDOMParseError można odczytać pełny raport z walidacji, czym zajmiemy się dalej w tym rozdziale.

Oto właściwości tego obiektu (druga kolumna oznacza rodzaj właściwości: O=tylko do odczytu, OZ=do odczytu i zapisu):

Obiekt

O/Z

Opis

errorCode

O

Kod błędu parsowania, który ostatnio wystąpił.

filepos

O

Położenie błędu w pliku.

line

O

Numer wiersza zawierającego błąd.

linepos

O

Położenie znaku w wierszu, w którym wystąpił błąd.

reason

O

Przyczyna wystąpienia błędu.

srcText

O

Pełny tekst wiersza z błędem.

url

O

Adres URL dokumentu XML zawierającego błąd, który ostatnio wystąpił.

Zwróć uwagę, że obiekt ten nie ma żadnych metod ani nie są z nim związane żadne zdarzenia, obiekt ten nie odpowiada żadnemu obiektowi należącemu do specyfikacji DOM W3C.

Obiekt XMLDOMAttribute

W DOM W3C, jak i w DOM Microsoftu obiekty atrybutów to obiekty węzłów (czyli są oparte na obiekcie node), nie są one jednak węzłem dzieckiem elementu i nie traktuje się ich jako części drzewa dokumentu. Atrybuty traktuje się jako właściwości elementów, z którymi są związane (oznacza to, że właściwości takie jak parentNode, previousSibling czy nextSibling dla atrybutów nie mają znaczenia). W tym rozdziale przyjrzymy się też, jak się atrybutów używa.

Oto właściwości tego obiektu (gwiazdką oznaczono rozszerzenia Microsoftu; druga kolumna oznacza rodzaj właściwości: O=tylko do odczytu, OZ=do odczytu i zapisu):

Obiekt

O/Z

Opis

attributes

O

Lista atrybutów węzła.

baseName*

O

Bazowa nazwa kwalifikowana przestrzenią nazw.

childNodes

O

Lista węzłów zawierająca węzły dzieci.

dataType*

OZ

Typ danych w węźle.

definition*

O

Definicja węzła w DTD lub schemacie.

firstChild

O

Pierwsze dziecko bieżącego węzła.

lastChild

O

Ostatnie dziecko bieżącego węzła.

name

O

Nazwa atrybutu.

namespaceURI*

O

Adres URI przestrzeni nazw.

nextSibling

O

Następny węzeł bliźniaczy węzła bieżącego.

nodeName

O

Kwalifikowana nazwa elementu, atrybutu lub odwołania do encji, w innych przypadkach napis.

nodeType

O

Rodzaj węzła XML DOM.

nodeTypedValue*

OZ

Wartość węzła.

nodeTypeString*

O

Typ węzła w postaci napisu.

nodeValue

OZ

Tekst związany z węzłem.

onwerDocument

O

Węzeł główny dokumentu.

parentNode

O

Węzeł rodzic (tylko w przypadku węzłów mających rodzica).

parsed*

O

Jeśli węzeł i wszyscy jego potomkowie byli już parsowani, ma wartość true.

prefix*

O

Przedrostek przestrzeni nazw.

previousSibling

O

Poprzedni węzeł bliźniaczy węzła bieżącego.

specified

O

Wskazuje, czy wartość węzła (zwykle atrybutu) podana została jawnie, czy określono ją na podstawie wartości domyślnej.

text

OZ

Tekstowa zawartość węzła i jego poddrzewka.

value

OZ

Wartość atrybutu.

xml

O

Węzeł i wszyscy jego potomkowie w postaci kodu XML.

Oto metody tego obiektu:

Metoda

Opis

appendChild

Dodaje nowe dziecko jako ostatnie dziecko danego węzła.

cloneNode

Zwraca nowy węzeł będący kopią węzła bieżącego.

hasChildNodes

Jeśli węzeł ma dzieci, ma wartość true.

insertBefore

Wstawia węzeł dziecko przed węzłem bieżącym.

removeChild

Usuwa dany węzeł dziecko z listy.

replaceChild

Podmienia dany węzeł dziecko na inny nowy węzeł.

selectNodes

Stosuje podaną operację dopasowania wzorca do kontekstu węzła, zwraca listę dopasowanych węzłów.

selectSingleNode

Stosuje podaną operację dopasowania wzorca do kontekstu węzła, zwraca pierwszy dopasowany węzeł.

transformNode

Przekształca węzeł i jego dzieci zgodnie z podanym arkuszem stylów XSL.

transformNodeToObject

Przekształca węzeł i jego dzieci zgodnie z podanym arkuszem stylów XSL, zwraca obiekty wynikowy.

Z obiektem tym nie są związane żadne zdarzenia.

Obiekt XMLDOMElement

Obiekty XMLDOMElement reprezentują elementy i są zapewne najczęściej spotykanymi obiektami węzłów. Jako że atrybuty nie są traktowane jako węzły dzieci węzłów elementów, do pobierania atrybutów używa się specjalnych metod - na przykład getAttribute, która zwraca XMLDOMNameNodeMap zawierający wszystkie atrybuty elementu.

Oto właściwości tego obiektu (gwiazdką oznaczono rozszerzenia Microsoftu; druga kolumna oznacza rodzaj właściwości: O=tylko do odczytu, OZ=do odczytu i zapisu):

Obiekt

O/Z

Opis

attributes

O

Lista atrybutów danego węzła.

baseName*

O

Bazowa nazwa kwalifikowana przestrzenią nazw.

childNodes

O

Lista węzłów zawierająca dzieci.

dataType*

OZ

Typ danych węzła.

definition*

O

Definicja węzła w DTD lub schemacie.

firstChild

O

Pierwsze dziecko danego węzła.

lastChild

O

Ostatnie dziecko danego węzła.

namespaceURI*

O

Adres URI przestrzeni nazw.

nextSibling

O

Następny węzeł bliźniaczy węzła bieżącego.

nodeName

O

Kwalifikowana nazwa elementu, atrybutu lub odwołania do encji, w przypadku innych typów węzłów napis.

nodeType

O

Określenie typu węzła DOM XML.

nodeTypeString*

O

Typ węzła w postaci napisu.

nodeValue

OZ

Tekst związany z węzłem.

ownerDocument

O

Węzeł główny dokumentu.

parentNode

O

Węzeł rodzic węzła bieżącego.

parsed*

O

Jeśli węzeł i wszyscy jego potomkowie już byli parsowani, ma wartość true.

prefix*

O

Przedrostek przestrzeni nazw.

previousSibling

O

Poprzedni element bliźniaczy danego węzła.

specified*

O

Podaje, czy wartość węzła określona została jawnie, czy określono ją na podstawie wartości domyślnej.

tagName

O

Nazwa elementu.

text*

OZ

Zawiera treść tekstu węzła i jego poddrzewek.

xml*

O

Zawiera reprezentację kodu XML odpowiadającego węzłowi i wszystkim jego potomkom.

Oto metody tego obiektu (gwiazdką oznaczono rozszerzenia Microsoftu):

Metoda

Opis

appendChild

Dodaje nowe dziecko jako ostatnie dziecko węzła bieżącego.

cloneNode

Zwraca nowy węzeł będący kopią węzła bieżącego.

getAttribute

Pobiera wartość atrybutu o podanej nazwie.

getAttributeNode

Pobiera węzeł atrybutu o podanej nazwie.

getElementsByTagName

Zwraca listę wszystkich elementów potomków o podanej nazwie.

hasChildNodes

Jeśli węzeł ma dzieci, zwraca true.

insertBefore

Wstawia węzeł dziecko przed danym węzłem.

normalize

Normalizuje wszystkie elementy potomne łącząc dwa lub więcej kolejnych węzłów tekstowych w pojedynczy węzeł tekstowy.

removeAttribute

Usuwa lub przenosi atrybut o podanej nazwie.

removeAttributeNode

Usuwa dany atrybut z elementu.

removeChild

Usuwa dany węzeł dziecko.

replaceChild

Zamienia dany węzeł dziecko na podany nowy węzeł.

selectNodes*

Stosuje podaną operację dopasowania wzorca do kontekstu węzła, zwraca listę dopasowanych węzłów.

selectSingleNode*

Stosuje podaną operację dopasowania wzorca do kontekstu węzła, zwraca pierwszy dopasowany węzeł.

setAttribute

Ustawia wartość atrybutu o podanej nazwie.

setAttributeNode

Dodaje lub zmienia dany węzeł atrybutu na podany.

transformNode*

Przekształca dany węzeł i jego dzieci zgodnie z danym arkuszem stylów XSL.

transformNodeToObject*

Przekształca dany węzeł i jego dzieci zgodnie z podanym arkuszem stylów, zwraca obiekt powstały w wyniku tego przekształcenia.

Z obiektem tym nie są związane żadne zdarzenia.

Obiekt XMLDOMText

Obiekt XMLDOMText zawiera tekstową zawartość elementu lub atrybutu. Jeśli w elemencie nie znajdują się żadne znaczniki, a tylko tekst, element zawierał będzie jeden tylko węzeł - węzeł tekstowy z całością danych znakowych (w przypadku elementów o zawartości mieszanej węzły tekstowe mogą mieć węzły bliźniacze elementów).

Podczas pierwszego udostępniania dokumentu w DOM XML cały tekst jest znormalizowany, co oznacza, że każdemu blokowi tekstu odpowiada jeden obiekt tekstu. Węzły tekstowe można tworzyć także tak, aby do siebie przylegały, choć nie będą one wczytane jako osobne przy następnym otwarciu dokumentu (warto zaznaczyć, że obiekt XMLDOMElement ma metodę normalize, który łączy przylegające do siebie węzły tekstowe w pojedynczy węzeł.

Oto właściwości tego obiektu (gwiazdką oznaczono rozszerzenia Microsoftu; druga kolumna oznacza rodzaj właściwości: O=tylko do odczytu, OZ=do odczytu i zapisu):

Obiekt

O/Z

Opis

attributes

O

Lista atrybutów węzła.

baseName*

O

Bazowa nazwa kwalifikowana przestrzenią nazw.

childNodes

O

Lista węzłów zawierająca węzły dzieci.

data

OZ

Dane węzła (faktyczna zawartość węzła zależy od jego rodzaju).

dataType*

OZ

Rodzaj danych węzła.

definition*

O

Definicja węzła w DTD lub schemacie.

firstChild

O

Pierwsze dziecko węzła bieżącego.

lastChild

O

Ostatnie dziecko węzła bieżącego.

length

O

Długość danych w znakach.

namespaceURI*

O

Adres URI przestrzeni nazw.

nextSibling

O

Następny węzeł bliźniaczy węzła danego.

nodeName

O

Kwalifikowana nazwa elementu, atrybutu lub odwołania do encji. w przypadku innych typów węzłów napis.

nodeType

O

Typ węzła według DOM XML.

nodeTypedValue*

OZ

Wartość węzła.

nodeTypeString*

O

Typ węzła w postaci napisu.

nodeValue

OZ

Tekst związany z węzłem.

ownerDocument

O

Węzeł główny dokumentu.

parentNode

O

Węzeł rodzic.

parsed*

O

Jeśli węzeł i wszyscy jego potomkowie byli już parsowani, zawiera wartość true.

prefix*

O

Przedrostek przestrzeni nazw.

previousSibling

O

Poprzedni węzeł bliźniaczy węzła danego.

specified

O

Informuje, czy wartość danego węzła podano jawnie, czy została ona określona na podstawie wartości domyślnej.

text*

OZ

Tekstowa zawartość węzła i jego poddrzewka.

xml*

O

Węzeł i jego potomkowie w postaci kodu XML.

Oto metody tego obiektu (gwiazdką oznaczono rozszerzenia Microsoftu):

Metoda

Opis

appendChild

Dodaje nowe dziecko jako ostatnie dziecko bieżącego węzła.

appendData

Dodaje podany napis do istniejących już danych.

cloneNode

Zwraca nowy węzeł będący kopią węzła bieżącego.

deleteData

Usuwa podany napis z danych.

hasChildNodes

Jeśli węzeł ma dzieci, zwraca true.

insertBefore

Przed wskazanym węzłem wstawia węzeł dziecko.

insertData

Wstawia podany napis na wskazanej pozycji w danych.

removeChild

Usuwa podany węzeł dziecko z listy dzieci.

replaceChild

Podmienia podany węzeł dziecko na nowy węzeł.

selectNodes*

--> Stosuje podaną operację dopasowania wzorca do kontekstu węzła, zwraca listę dopasowanych węzłów.[Author:T]

selectSingleNode*

--> Stosuje podaną operację dopasowania wzorca do kontekstu węzła, zwraca pierwszy dopasowany węzeł.[Author:T]

specified*

--> Określa, czy wartość danego węzła podano jawnie, czy też określono ją na podstawie wartości domyślnej.[Author:T]

splitText

Rozbija węzeł tekstowy na dwa węzły tekstowe.

substringData

Zwraca część napisu danych.

transformNode*

Przekształca dany węzeł i jego dzieci zgodnie z danym arkuszem stylów XSL.

transformNodeToObject*

Przekształca dany węzeł i jego dzieci zgodnie z podanym arkuszem stylów, zwraca obiekt powstały w wyniku tego przekształcenia.

Z obiektem tym nie są związane żadne zdarzenia.

I tak oto zapoznaliśmy się z najważniejszymi obiektami modelu DOM XML Microsoftu. Teraz czas tę wiedzę wykorzystać, co zajmie nam już resztę tego rozdziału. Zaczniemy od samego początku, czyli od ładowania dokumentu XML.

Ładowanie dokumentów XML

Pierwszym krokiem jest załadowanie z kodu dokumentu XML do Internet Explorera i utworzenie obiektu dokumentu. Za pomocą tego obiektu będziemy w stanie do tego dokumentu dowolnie sięgać.

Jak już wspomniano wcześniej, dokument XML do Internet Explorera można załadować na dwa sposoby tak, aby móc z niego korzystać za pomocą JavaScriptu. Aby sprawdzić, jak to wszystko działa, użyjemy dokumentu spotkania.xml, w którym opisano spotkania w interesach wraz z osobami obecnymi i z datami:

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

<SPOTKANIA>

<SPOTKANIE TYP="nieformalne">

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

<NUMER>2079</NUMER>

<TEMAT>XML</TEMAT>

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

<OSOBY>

<OSOBA STATUS="obecna">

<IMIE>Edward</IMIE>

<NAZWISKO>Samson</NAZWISKO>

</OSOBA>

<OSOBA STATUS="nieobecna">

<IMIE>Ernestyna</IMIE>

<NAZWISKO>Johnson</NAZWISKO>

</OSOBA>

<OSOBA STATUS="obecna">

<IMIE>Betty</IMIE>

<NAZWISKO>Richardson</NAZWISKO>

</OSOBA>

</OSOBY>

</SPOTKANIE>

</SPOTKANIA>

Pierwsza metoda ładowania dokumentu XML do Internet Explorera to utworzenie obiektu document przy użyciu klasy Microsoft.XMLDOM.

Aby zobaczyć, jak to działa, utworzymy przykład odczytujący plik spotkania.xml i pobierający dane trzeciej osoby z dokumentu (Betty Richardson). Zaczynamy od utworzenia nowego obiektu dokumentu za pomocą operatora new:

<HTML>

<HEAD>

<TITLE>

Odczytywanie wartości elementów XML

</TITLE>

<SCRIPT LANGUAGE="JavaScript">

function readXMLDocument()

{

var xmldoc

xmldoc = new ActiveXObject("Microsoft.XMLDOM")

.

.

.

</HEAD>

</HTML>

Teraz możemy dokument spotkania.xml załadować:

<HTML>

<HEAD>

<TITLE>

Odczytywanie wartości elementów XML

</TITLE>

<SCRIPT LANGUAGE="JavaScript">

function readXMLDocument()

{

var xmldoc

xmldoc = new ActiveXObject("Microsoft.XMLDOM")

xmldoc.load("spotkania.xml")

.

.

.

</HEAD>

</HTML>

Następnym krokiem będzie pobranie obiektu węzła odpowiadającego elementowi głównemu dokumentu, czyli SPOTKANIA. Użyjemy do tego metody documentElement:

<HTML>

<HEAD>

<TITLE>

Odczytywanie wartości elementów XML

</TITLE>

<SCRIPT LANGUAGE="JavaScript">

function readXMLDocument()

{

var xmldoc, meetingsNode

xmldoc = new ActiveXObject("Microsoft.XMLDOM")

xmldoc.load("spotkania.xml")

meetingsNode = xmldoc.documentElement

.

.

.

</HEAD>

</HTML>

Teraz już możemy dowolnie hasać po dokumencie stosując metody firstChild, nextChild, previousChild i lastChild, które umożliwiają dostęp do elementów dzieci, oraz metody firstSibling, nextSibling, previousSibling i lastSibling umożliwiające sięgnięcie do elementów na takim samym poziomie zagnieżdżenia (elementów bliźniaczych). Na przykład element SPOTKANIE jest pierwszym dzieckiem elementu głównego SPOTKANIA, więc do sięgnięcia do niego odpowiednia będzie metoda firstChild:

<HTML>

<HEAD>

<TITLE>

Odczytywanie wartości elementów XML

</TITLE>

<SCRIPT LANGUAGE="JavaScript">

function readXMLDocument()

{

var xmldoc, meetingsNode, meetingNode

xmldoc = new ActiveXObject("Microsoft.XMLDOM")

xmldoc.load("spotkania.xml")

meetingsNode = xmldoc.documentElement

meetingNode = meetingsNode.firstChild

.

.

.

</HEAD>

</HTML>

Chcemy wybrać trzeci element OSOBA z elementu OSOBY. OSOBY to ostatnie dziecko elementu SPOTKANIE, zatem możemy się doń tak oto odwołać:

<HTML>

<HEAD>

<TITLE>

Odczytywanie wartości elementów XML

</TITLE>

<SCRIPT LANGUAGE="JavaScript">

function readXMLDocument()

{

var xmldoc, meetingsNode, meetingNode, peopleNode

xmldoc = new ActiveXObject("Microsoft.XMLDOM")

xmldoc.load("spotkania.xml")

meetingsNode = xmldoc.documentElement

meetingNode = meetingsNode.firstChild

peopleNode = meetingNode.lastChild

.

.

.

</HEAD>

</HTML>

Potrzebna jest nam trzecia osoba z elementu OSOBY, czyli ostatnie dziecko tego elementu - użyjemy zatem jeszcze raz metody lastChild:

<HTML>

<HEAD>

<TITLE>

Odczytywanie wartości elementów XML

</TITLE>

<SCRIPT LANGUAGE="JavaScript">

function readXMLDocument()

{

var xmldoc, meetingsNode, meetingNode, peopleNode

var personNode

xmldoc = new ActiveXObject("Microsoft.XMLDOM")

xmldoc.load("spotkania.xml")

meetingsNode = xmldoc.documentElement

meetingNode = meetingsNode.firstChild

peopleNode = meetingNode.lastChild

personNode = peopleNode.lastChild

.

.

.

</HEAD>

</HTML>

W końcu należałoby sięgnąć do imienia i nazwiska wybranej osoby - skorzystamy z metod firstChild i nextSibling:

<HTML>

<HEAD>

<TITLE>

Odczytywanie wartości elementów XML

</TITLE>

<SCRIPT LANGUAGE="JavaScript">

function readXMLDocument()

{

var xmldoc, meetingsNode, meetingNode, peopleNode

var personNode, first_nameNode, last_nameNode

xmldoc = new ActiveXObject("Microsoft.XMLDOM")

xmldoc.load("spotkania.xml")

meetingsNode = xmldoc.documentElement

meetingNode = meetingsNode.firstChild

peopleNode = meetingNode.lastChild

personNode = peopleNode.lastChild

first_nameNode = personNode.firstChild

last_nameNode = first_nameNode.nextSibling

.

.

.

</HEAD>

</HTML>

Tak więc jesteśmy już przy tych elementach, o które nam chodziło. Jednak interesują nas węzły tekstowe znajdujące się wewnątrz węzłów elementów IMIĘ i NAZWISKO, zatem należy się dostać do pierwszych dzieci tych elementów, a żeby odczytać sam tekst, użyć należy właściwości nodeValue.

Aby wyświetlić imię i nazwisko wybranej osoby, wygenerujemy nieco dynamicznego kodu HTML - użyjemy elementu DIV i jego właściwości innerHTML (zawiera ona tekst elementu DIV):

<HTML>

<HEAD>

<TITLE>

Odczytywanie wartości elementów XML

</TITLE>

<SCRIPT LANGUAGE="JavaScript">

function readXMLDocument()

{

var xmldoc, meetingsNode, meetingNode, peopleNode

var personNode, first_nameNode, last_nameNode, outputText

xmldoc = new ActiveXObject("Microsoft.XMLDOM")

xmldoc.load("spotkania.xml")

meetingsNode = xmldoc.documentElement

meetingNode = meetingsNode.firstChild

peopleNode = meetingNode.lastChild

personNode = peopleNode.lastChild

first_nameNode = personNode.firstChild

last_nameNode = first_nameNode.nextSibling

outputText = "Trzecia osoba: " +

first_nameNode.firstChild.nodeValue + ' ' +

last_nameNode.firstChild.nodeValue

messageDIV.innerHTML = outputText

}

</SCRIPT>

</HEAD>

<BODY>

<CENTER>

<H1>

Odczytywanie wartości elementów XML

</H1>

<INPUT TYPE="BUTTON" VALUE="Pobierz nazwisko trzeciej osoby"

ONCLICK="readXMLDocument()">

<P>

<DIV ID="messageDIV"></DIV>

</CENTER>

</BODY>

</HTML>

Dodaliśmy jeszcze przycisk, który uruchomi naszą funkcję readXMLDocument, a ta funkcja odczyta dokument i wyświetli żądane informacje.

Na rysunku 5.2 pokazano tę stronę w działaniu. Kiedy użytkownik klika przycisk, wczytywany jest dokument spotkania.xml, jest parsowany, odczytywane i wyświetlane są dane o trzeciej osobie - całkiem nieźle jak na początek.

Rysunek 5.2.

Odczyt elementu XML w Internet Explorerze

0x01 graphic

Użycie wysp danych XML

W Internet Explorerze 5 możesz też do włączenia danych XML do stron HTML użyć wysp danych XML. Explorer 5 obsługuje znacznik <XML> (nie należący do standardu HTML), który pozwala po prostu umieścić wewnątrz cały dokument XML:

<XML ID="pozdrowienia">

<DOKUMENT>

<POZDROWIENIA>Witamy XML!</POZDROWIENIA>

</DOKUMENT>

</XML>

Znacznik <XML> ma pewne atrybuty, o których warto wspomnieć:

Atrybut

Opis

ID

Identyfikator, według którego do znacznika <XML> można się odwoływać w kodzie. Wartością jest napis ASCII.

NS

Adres URI przestrzeni nazw XML używanej we wstawianym dokumencie XML.

PREFIX

Przedrostek przestrzeni nazw treści XML. Wartością jest napis ASCII.

SRC

Jeśli używany jest zewnętrzny dokument XML, podaje się tu jego adres URI.

Kiedy używasz elementu XML, w kodzie odwołujesz się do niego stosując identyfikator ID. Aby sięgnąć do elementu, można użyć kolekcji all przekazując identyfikator elementu, w powyższym przykładzie będzie to document.all("pozdrowienia"). Aby pobrać obiekt dokumentu odpowiadający tak wczytanemu dokumentowi XML, można użyć właściwości XMLDocument. Oto jak należy przekształcić poprzedni przykład, aby zamiast obiektu Microsoft.XMLDOM użyć wysp danych:

<HTML>

<HEAD>

<TITLE>

Użycie wysp danych XML do odczytu wartości elementów

</TITLE>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

function readXMLDocument()

{

var xmldoc, meetingsNode, meetingNode, peopleNode

var personNode, first_nameNode, last_nameNode, outputText

xmldoc = document.all("meetingsXML").XMLDocument

meetingsNode = xmldoc.documentElement

meetingNode = meetingsNode.firstChild

peopleNode = meetingNode.lastChild

personNode = peopleNode.lastChild

first_nameNode = personNode.firstChild

last_nameNode = first_nameNode.nextSibling

outputText = "Trzecia osoba: " +

first_nameNode.firstChild.nodeValue + ' ' +

last_nameNode.firstChild.nodeValue

messageDIV.innerHTML = outputText

}

</SCRIPT>

</HEAD>

<BODY>

<CENTER>

<H1>

Użycie wysp danych XML do odczytu wartości elementów

</H1>

<INPUT TYPE="BUTTON" VALUE="Pobierz nazwisko trzeciej osoby"

ONCLICK="readXMLDocument()">

<P>

<DIV ID="messageDIV"></DIV>

</CENTER>

</BODY>

</HTML>

Spójrz na rysunek 5.3 - ten przykład działa tak samo, jak poprzedni.

Rysunek 5.3.

Użycie wysp danych XML w Internet Explorerze

0x01 graphic

W ostatnim przykładzie użyliśmy zewnętrznego dokumentu XML, spotkania.xml, do jego odczytania użyliśmy atrybutu SRC znacznika <XML>. Można jednak w elemencie XML zamknąć także cały dokument:

<HTML>

<HEAD>

<TITLE>

Użycie wysp danych XML do odczytu wartości elementów

</TITLE>

<XML ID="meetingsXML">

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

<SPOTKANIA>

<SPOTKANIE TYP="nieformalne">

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

<NUMER>2079</NUMER>

<TEMAT>XML</TEMAT>

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

<OSOBY>

<OSOBA STATUS="obecna">

<IMIE>Edward</IMIE>

<NAZWISKO>Samson</NAZWISKO>

</OSOBA>

<OSOBA STATUS="nieobecna">

<IMIE>Ernestyna</IMIE>

<NAZWISKO>Johnson</NAZWISKO>

</OSOBA>

<OSOBA STATUS="obecna">

<IMIE>Betty</IMIE>

<NAZWISKO>Richardson</NAZWISKO>

</OSOBA>

</OSOBY>

</SPOTKANIE>

</SPOTKANIA>

</XML>

<SCRIPT LANGUAGE="JavaScript">

function readXMLDocument()

{

var xmldoc, meetingsNode, meetingNode, peopleNode

var personNode, first_nameNode, last_nameNode, outputText

xmldoc = document.all("meetingsXML").XMLDocument

meetingsNode = xmldoc.documentElement

meetingNode = meetingsNode.firstChild

peopleNode = meetingNode.lastChild

personNode = peopleNode.lastChild

first_nameNode = personNode.firstChild

last_nameNode = first_nameNode.nextSibling

outputText = "Trzecia osoba: " +

first_nameNode.firstChild.nodeValue + ' ' +

last_nameNode.firstChild.nodeValue

messageDIV.innerHTML = outputText

}

</SCRIPT>

</HEAD>

<BODY>

<CENTER>

<H1>

Użycie wysp danych XML do odczytu wartości elementów

</H1>

<INPUT TYPE="BUTTON" VALUE="Pobierz nazwisko trzeciej osoby"

ONCLICK="readXMLDocument()">

<P>

<DIV ID="messageDIV"></DIV>

</CENTER>

</BODY>

</HTML>

Jak dotąd do pobrania obiektu dokumentu używaliśmy właściwości XMLDocument obiektu odpowiadającego wyspie danych XML, można jednak użyć też bezpośrednio właściwości documentElement wyspy danych:

<HTML>

<HEAD>

<TITLE>

Użycie wysp danych XML do odczytu wartości elementów

</TITLE>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

function readXMLDocument()

{

var xmldoc, meetingsNode, meetingNode, peopleNode

var personNode, first_nameNode, last_nameNode, outputText

meetingsNode = meetingsXML.documentElement

meetingNode = meetingsNode.firstChild

peopleNode = meetingNode.lastChild

personNode = peopleNode.lastChild

first_nameNode = personNode.firstChild

last_nameNode = first_nameNode.nextSibling

.

.

.

</HTML>

Pobieranie elementów według nazwy

Jak na razie używaliśmy metod nawigacji po dokumencie takich, jak nextSibling czy nextChild. Można jednak do konkretnych elementów odwoływać się przez ich nazwę. Oto przykład; użyjemy metody getElementsByTagName obiektu document, aby uzyskać listę wszystkich obiektów elementów o danej nazwie. Będziemy szukać konkretnie elementów IMIĘ i NAZWISKO, więc użyjemy następującego kodu:

<HTML>

<HEAD>

<TITLE>

Odczytywanie wartości elementów XML

</TITLE>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

function loadDocument()

{

var xmldoc, listNodesFirstName, listNodesLastName

xmldoc = new ActiveXObject("Microsoft.XMLDOM")

xmldoc.load("spotkania.xml")

listNodesFirstName = xmldoc.getElementsByTagName("IMIĘ")

listNodesLastName = xmldoc.getElementsByTagName("NAZWISKO")

.

.

.

</HTML>

Tak jak wszystkie listy węzłów, listy listNodesFirstName i listNodesLastName indeksuje się zaczynając od 0, zatem trzeci element będzie miał numer 2, więc odwoływać się do niego będziemy listNodesLastName.item(2) (pamiętaj, że musimy znaleźć pierwsze dzieci węzłów elementów IMIĘ i NAZWISKO, które są węzłami tekstowymi wywoływanymi metodą firstChild).

<HTML>

<HEAD>

<TITLE>

Odczytywanie wartości elementów XML

</TITLE>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

function loadDocument()

{

var xmldoc, listNodesFirstName, listNodesLastName

var outputText

xmldoc = new ActiveXObject("Microsoft.XMLDOM")

xmldoc.load("spotkania.xml")

listNodesFirstName = xmldoc.getElementsByTagName("IMIĘ")

listNodesLastName = xmldoc.getElementsByTagName("NAZWISKO")

outputText = "Trzecia osoba: " +

listNodesFirstName.item(2).firstChild.nodeValue + ' ' +

listNodesLastName.item(2).firstChild.nodeValue

messageDIV.innerHTML = outputText

}

</SCRIPT>

</HEAD>

<BODY>

<CENTER>

<H1>

Odczytywanie wartości elementów XML

</H1>

<INPUT TYPE="BUTTON" VALUE="Pobierz nazwisko trzeciej osoby"

ONCLICK="loadDocument()">

<P>

<DIV ID="messageDIV"></DIV>

</CENTER>

</BODY>

</HTML>

Już nieco wiemy o użyciu XML, jesteśmy w stanie dokumenty XML wczytywać na różne sposoby i sięgać do poszczególnych elementów w dokumencie. Teraz czas przejść krok dalej - zamiast sięgać do zawartości tekstowej elementów odczytywać ich atrybuty.

Pobieranie wartości atrybutów

Aby zobaczyć, jak odczytywać wartości atrybutów dokumentów XML, przykładowo odczytywać będziemy wartość atrybutu STATUS trzeciej osoby z dokumentu spotkania.xml:

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

<SPOTKANIA>

<SPOTKANIE TYP="nieformalne">

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

<NUMER>2079</NUMER>

<TEMAT>XML</TEMAT>

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

<OSOBY>

<OSOBA STATUS="obecna">

<IMIE>Edward</IMIE>

<NAZWISKO>Samson</NAZWISKO>

</OSOBA>

<OSOBA STATUS="nieobecna">

<IMIE>Ernestyna</IMIE>

<NAZWISKO>Johnson</NAZWISKO>

</OSOBA>

<OSOBA STATUS="obecna">

<IMIE>Betty</IMIE>

<NAZWISKO>Richardson</NAZWISKO>

</OSOBA>

</OSOBY>

</SPOTKANIE>

</SPOTKANIA>

Jak się odczytuje wartości atrybutów? Zaczynamy od pozyskania obiektu nazwanej mapy węzłów z atrybutami interesującego nas węzła. W tym przypadku interesuje nas trzeci element OSOBA, mapę jego węzłów pobieramy następująco:

<HTML>

<HEAD>

<TITLE>

Odczytywanie wartości atrybutów z dokumentu XML

</TITLE>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

function readXMLDocument()

{

var xmldoc, meetingsNode, meetingNode, peopleNode

var personNode, first_nameNode, last_nameNode, outputText

var attributes

xmldoc = document.all("meetingsXML").XMLDocument

meetingsNode = meetingsXML.documentElement

meetingNode = meetingsNode.firstChild

peopleNode = meetingNode.lastChild

personNode = peopleNode.lastChild

first_nameNode = personNode.firstChild

last_nameNode = first_nameNode.nextSibling

attributes = personNode.attributes

.

.

.

</HTML>

Teraz stosując do tak uzyskanej mapy metodę getNamedItem możemy pobrać wartość atrybutu STATUS:

<HTML>

<HEAD>

<TITLE>

Odczytywanie wartości atrybutów z dokumentu XML

</TITLE>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

function readXMLDocument()

{

var xmldoc, meetingsNode, meetingNode, peopleNode

var personNode, first_nameNode, last_nameNode, outputText

var attributes, attendancePerson

xmldoc = document.all("meetingsXML").XMLDocument

meetingsNode = meetingsXML.documentElement

meetingNode = meetingsNode.firstChild

peopleNode = meetingNode.lastChild

personNode = peopleNode.lastChild

first_nameNode = personNode.firstChild

last_nameNode = first_nameNode.nextSibling

attributes = personNode.attributes

attendancePerson = attributes.getNamedItem("STATUS")

.

.

.

</HTML>

Teraz mamy już węzeł odpowiadający atrybutowi STATUS, wartość atrybutu pobrać możemy stosując właściwość value (węzły atrybutów nie mają wewnętrznych węzłów tekstowych):

<HTML>

<HEAD>

<TITLE>

Odczytywanie wartości atrybutów z dokumentu XML

</TITLE>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

function readXMLDocument()

{

var xmldoc, meetingsNode, meetingNode, peopleNode

var personNode, first_nameNode, last_nameNode, outputText

var attributes, attendancePerson

xmldoc = document.all("meetingsXML").XMLDocument

meetingsNode = meetingsXML.documentElement

meetingNode = meetingsNode.firstChild

peopleNode = meetingNode.lastChild

personNode = peopleNode.lastChild

first_nameNode = personNode.firstChild

last_nameNode = first_nameNode.nextSibling

attributes = personNode.attributes

attendancePerson = attributes.getNamedItem("STATUS")

outputText = "Trzecia osoba: " +

first_nameNode.firstChild.nodeValue + ' ' +

last_nameNode.firstChild.nodeValue +

" - " + attendancePerson.value

messageDIV.innerHTML = outputText

.

.

.

</HTML>

I to już wszystko, oto kompletna strona HTML:

<HTML>

<HEAD>

<TITLE>

Odczytywanie wartości atrybutów z dokumentu XML

</TITLE>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

function readXMLDocument()

{

var xmldoc, meetingsNode, meetingNode, peopleNode

var personNode, first_nameNode, last_nameNode, outputText

var attributes, attendancePerson

xmldoc = document.all("meetingsXML").XMLDocument

meetingsNode = meetingsXML.documentElement

meetingNode = meetingsNode.firstChild

peopleNode = meetingNode.lastChild

personNode = peopleNode.lastChild

first_nameNode = personNode.firstChild

last_nameNode = first_nameNode.nextSibling

attributes = personNode.attributes

attendancePerson = attributes.getNamedItem("STATUS")

outputText = "Trzecia osoba: " +

first_nameNode.firstChild.nodeValue + ' ' +

last_nameNode.firstChild.nodeValue +

" - " + attendancePerson.value

messageDIV.innerHTML = outputText

}

</SCRIPT>

</HEAD>

<BODY>

<CENTER>

<H1>

Odczytywanie atrybutów z dokumentów XML

</H1>

<INPUT TYPE="BUTTON" VALUE="Pobierz informacje o trzeciej osobie"

ONCLICK="readXMLDocument()">

<P>

<DIV ID="messageDIV"></DIV>

</CENTER>

</BODY>

</HTML>

Na rysunku 5.4 pokazano wyniki - trzecia osoba była na spotkaniu obecna.

Rysunek 5.4.

Odczytywanie wartości atrybutów w Internet Explorerze

0x01 graphic

Parsowanie dokumentów XML w kodzie

Jak dotąd wybieraliśmy z dokumentu różne konkretne elementy, można jednak dokumenty obsługiwać także inaczej. Można na przykład dokument parsować, czyli odczytywać go i interpretować, cały dokument na raz. W ramach przykładu przetworzymy cały dokument spotkania.xml i wyświetlimy wszystkie jego węzły na stronie HTML.

W celu obsługi dokumentu utworzymy funkcję iterateChildren, która odczyta i wyświetli wszystkie dzieci danego węzła. Tak jak w większości innych parserów, jest to funkcja rekurencyjna, czyli taka, która sama się wywołuje dla kolejnych dzieci przetwarzanego węzła. Aby pobrać nazwę węzła, używamy właściwości nodeName węzła. W celu parsowania całego dokumentu wystarczy naszej funkcji przekazać węzeł główny całego dokumentu, a przetworzone zostanie całe drzewo i wyświetlone zostaną wszystkie węzły:

<HTML>

<HEAD>

<TITLE>

Parsowanie dokumentu XML

</TITLE>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

function parseDocument()

{

documentXML = document.all("meetingsXML").XMLDocument

resultsDIV.innerHTML = iterateChildren(documentXML, "")

}

.

.

.

Zwróć uwagę, że dodatkowo funkcji iterateChildren przekazano pusty napis (""). Parametru tego używamy do robienia odpowiednich wcięć poszczególnych poziomów elementów, dzięki czemu widać będzie, które elementy są w których zagnieżdżane. Zaczynamy od utworzenia nowego napisu składającego się z bieżącego wcięcia (zaczynamy od ciągu pustego - brak wcięcia, później użyjemy odpowiedniej liczby spacji), nazwy bieżącego węzła i elementu <BR>, dzięki któremu przeglądarka przesunie się do następnego wiersza:

<HTML>

<HEAD>

<TITLE>

Parsowanie dokumentu XML

</TITLE>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

function parseDocument()

{

documentXML = document.all("meetingsXML").XMLDocument

resultsDIV.innerHTML = iterateChildren(documentXML, "")

}

function iterateChildren(theNode, indentSpacing)

{

var text = indentSpacing + theNode.nodeName + "<BR>"

.

.

.

return text

}

</SCRIPT>

</HEAD>

.

.

.

Dzieci bieżącego węzła możemy odczytać korzystając z właściwości childNodes, która zawiera listę węzłów dzieci węzła bieżącego. Liczbę dzieci można określić sprawdzając długość tej listy - właściwość length; jeśli jakieś dzieci są, wywołujemy iterateChildren dla wszystkich węzłów dzieci (zwróć uwagę na to, że następny poziom węzłów otrzymuje większe wcięcie - dodatkowe cztery spacje nierozdzielające dostępne jako odwołanie do encji HTML &nbsp;):

<HTML>

<HEAD>

<TITLE>

Parsowanie dokumentu XML

</TITLE>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

function parseDocument()

{

documentXML = document.all("meetingsXML").XMLDocument

resultsDIV.innerHTML = iterateChildren(documentXML, "")

}

function iterateChildren(theNode, indentSpacing)

{

var text = indentSpacing + theNode.nodeName + "<BR>"

if (theNode.childNodes.length > 0) {

for (var loopIndex = 0; loopIndex <

theNode.childNodes.length; loopIndex++) {

text += iterateChildren(theNode.childNodes(loopIndex),

indentSpacing + "&nbsp;&nbsp;&nbsp;&nbsp;")

}

}

return text

}

</SCRIPT>

</HEAD>

.

.

.

I to już właściwie wszystko, oto gotowa strona sieciowa:

<HTML>

<HEAD>

<TITLE>

Parsowanie dokumentu XML

</TITLE>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

function parseDocument()

{

documentXML = document.all("meetingsXML").XMLDocument

resultsDIV.innerHTML = iterateChildren(documentXML, "")

}

function iterateChildren(theNode, indentSpacing)

{

var text = indentSpacing + theNode.nodeName + "<BR>"

if (theNode.childNodes.length > 0) {

for (var loopIndex = 0; loopIndex <

theNode.childNodes.length; loopIndex++) {

text += iterateChildren(theNode.childNodes(loopIndex),

indentSpacing + "&nbsp;&nbsp;&nbsp;&nbsp;")

}

}

return text

}

</SCRIPT>

</HEAD>

<BODY>

<CENTER>

<H1>

Parsowanie dokumentu XML

</H1>

</CENTER>

<CENTER>

<INPUT TYPE="BUTTON" VALUE="Parsowanie i wyświetlenie dokumentu"

ONCLICK="parseDocument()">

</CENTER>

<DIV ID="resultsDIV"></DIV>

</BODY>

</HTML>

Kiedy klikniesz znajdujący się na stronie przycisk, odczytany zostanie plik spotkania.xml i wyświetlona zostanie jego struktura, jak to pokazano na rysunku 5.5. Pokazano wszystkie węzły z odpowiednimi wcięciami. Zwróć uwagę na dodatkowe „metanazwy” wstawione przez Internet Explorera do węzłów dokumentu i tekstowych: #document oraz #text.

Rysunek 5.5.

Parsowanie dokumentu w Internet Explorerze

0x01 graphic

Parsowanie dokumentu XML w celu wyświetlenia typu i zawartości węzła

Kod z poprzedniego przykładu wyliczał nazwy wszystkich węzłów dokumentu spotkania.xml. Można jednak zrobić jeszcze więcej - można użyć właściwości nodeValue do wypisania wartości poszczególnych węzłów i tym się zajmiemy w tym punkcie. Sprawdzając właściwość nodeType można też odczytać typy poszczególnych węzłów - oto dopuszczalne wartości:

Wartość

Opis

1

element

2

atrybut

3

tekst

4

sekcja CDATA

5

odwołanie do encji

6

encja

7

instrukcja przetwarzania

8

komentarz

9

dokument

10

typ dokumentu

11

fragment dokumentu

12

notacja

Oto jak się określa rodzaj danego węzła przy pomocy instrukcji JavaScriptu switch, którą poznaliśmy w poprzednim rozdziale:

<HTML>

<HEAD>

<TITLE>

Parsowanie dokumentu XML, wyświetlanie typów i zawartości węzłów

</TITLE>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

function parseDocument()

{

documentXML = document.all("meetingsXML").XMLDocument

resultsDIV.innerHTML = iterateChildren(documentXML, "")

}

function iterateChildren(theNode, indentSpacing)

{

var typeData

switch (theNode.nodeType) {

case 1:

typeData = "element"

break

case 2:

typeData = "atrybut"

break

case 3:

typeData = "tekst"

break

case 4:

typeData = "sekcja CDATA"

break

case 5:

typeData = "odwołanie do encji"

break

case 6:

typeData = "encja"

break

case 7:

typeData = "instrukcja przetwarzania"

break

case 8:

typeData = "komentarz"

break

case 9:

typeData = "dokument"

break

case 10:

typeData = "typ dokumentu"

break

case 11:

typeData = "fragment dokumentu"

break

case 12:

typeData = "notacja"

break

}

.

.

.

Jeśli węzeł ma niepustą wartość (sprawdza się to porównując nodeValue z wartością null), to wartość tę można wyświetlić:

<HTML>

<HEAD>

<TITLE>

Parsowanie dokumentu XML, wyświetlanie typów i zawartości węzłów

</TITLE>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

function parseDocument()

{

documentXML = document.all("meetingsXML").XMLDocument

resultsDIV.innerHTML = iterateChildren(documentXML, "")

}

function iterateChildren(theNode, indentSpacing)

{

var typeData

switch (theNode.nodeType) {

case 1:

typeData = "element"

break

case 2:

typeData = "atrybut"

break

case 3:

typeData = "tekst"

break

case 4:

typeData = "sekcja CDATA"

break

case 5:

typeData = "odwołanie do encji"

break

case 6:

typeData = "encja"

break

case 7:

typeData = "instrukcja przetwarzania"

break

case 8:

typeData = "komentarz"

break

case 9:

typeData = "dokument"

break

case 10:

typeData = "typ dokumentu"

break

case 11:

typeData = "fragment dokumentu"

break

case 12:

typeData = "notacja"

break

}

var text = indentSpacing + theNode.nodeName + "<BR>"

if (theNode.nodeValue != null) {

text = indentSpacing + theNode.nodeName

+ "&nbsp; = " + theNode.nodeValue

+ "&nbsp; (typ węzła: " + typeData

+ ")<BR>"

}

else {

text = indentSpacing + theNode.nodeName

+ "&nbsp; (Typ węzła: " + typeData

+ ")<BR>"

}

if (theNode.childNodes.length > 0) {

for (var loopIndex = 0; loopIndex <

theNode.childNodes.length; loopIndex++) {

text += iterateChildren(theNode.childNodes(loopIndex),

indentSpacing + "&nbsp;&nbsp;&nbsp;&nbsp;")

}

}

return text

}

</SCRIPT>

</HEAD>

<BODY>

<CENTER>

<H1>

Parsowanie dokumentu XML, wyświetlanie typów i zawartości węzłów

</H1>

</CENTER>

<CENTER>

<INPUT TYPE="BUTTON" VALUE="Parsowanie dokumentu, opisanie węzłów"

ONCLICK="parseDocument()">

</CENTER>

<DIV ID="resultsDIV"></DIV>

</BODY>

</HTML>

I to już wszystko - wyniki pokazano na rysunku 5.6. Pokazany jest cały dokument, a w nim typy wszystkich węzłów. Jeśli tylko któryś węzeł ma wartość, to wartość ta jest wyświetlana.

Rysunek 5.6.

Użycie JavaScriptu do wyświetlania zawartości elementów i ich typu

0x01 graphic

W przykładzie tym pokazano wszystkie elementy dokumentu, ale przecież niektóre z nich mają jeszcze atrybuty i teraz czas się nimi zająć.

Parsowanie dokumentu XML w celu wyświetlenia wartości atrybutów

Do atrybutów każdego elementu można dostać się stosując właściwość attributes. Nazwy atrybutów i ich wartości odczytać można za pomocą właściwości name i value obiektów atrybutów, zresztą właściwości value używaliśmy już wcześniej w tym rozdziale. Warto też pamiętać, że z uwagi na to, że atrybuty same też są węzłami, można też użyć ich właściwości nodeName i nodeValue; zaraz zobaczysz, jak to działa.

Tym razem zmodyfikujemy nieco poprzedni przykład dodając analizę w pętli także atrybutów i ich wyświetlanie (pamiętaj, że właściwości name i value można używać wymiennie z nodeName i nodeValue).

<HTML>

<HEAD>

<TITLE>

Parsowanie dokumentu XML, wyświetlanie typów i zawartości węzłów

</TITLE>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

function parseDocument()

{

documentXML = document.all("meetingsXML").XMLDocument

resultsDIV.innerHTML = iterateChildren(documentXML, "")

}

function iterateChildren(theNode, indentSpacing)

{

var typeData

switch (theNode.nodeType) {

case 1:

typeData = "element"

break

case 2:

typeData = "atrybut"

break

case 3:

typeData = "tekst"

break

case 4:

typeData = "sekcja CDATA"

break

case 5:

typeData = "odwołanie do encji"

break

case 6:

typeData = "encja"

break

case 7:

typeData = "instrukcja przetwarzania"

break

case 8:

typeData = "komentarz"

break

case 9:

typeData = "dokument"

break

case 10:

typeData = "typ dokumentu"

break

case 11:

typeData = "fragment dokumentu"

break

case 12:

typeData = "notacja"

break

}

var text = indentSpacing + theNode.nodeName + "<BR>"

if (theNode.nodeValue != null) {

text = indentSpacing + theNode.nodeName

+ "&nbsp; = " + theNode.nodeValue

+ "&nbsp; (typ węzła: " + typeData

+ ")"

}

else {

text = indentSpacing + theNode.nodeName

+ "&nbsp; (Typ węzła: " + typeData

+ ")"

}

if (theNode.attributes != null) {

if (theNode.attributes.length > 0) {

for (var loopIndex = 0; loopIndex <

theNode.attributes.length; loopIndex++) {

text += " (Atrybut: " +

theNode.attributes(loopIndex).nodeName +

" = \"" +

theNode.attributes(loopIndex).nodeValue

+ "\")"

}

}

}

text += "<BR>"

if (theNode.childNodes.length > 0) {

for (var loopIndex = 0; loopIndex <

theNode.childNodes.length; loopIndex++) {

text += iterateChildren(theNode.childNodes(loopIndex),

indentSpacing + "&nbsp;&nbsp;&nbsp;&nbsp;")

}

}

return text

}

</SCRIPT>

</HEAD>

<BODY>

<CENTER>

<H1>

Parsowanie dokumentu XML, wyświetlanie typów i zawartości węzłów

</H1>

</CENTER>

<CENTER>

<INPUT TYPE="BUTTON" VALUE="Parsowanie dokumentu, opisanie węzłów"

ONCLICK="parseDocument()">

</CENTER>

<DIV ID="resultsDIV"></DIV>

</BODY>

</HTML>

Wyniki pokazano na rysunku 5.7 - pokazane są zarówno elementy, jak i atrybuty.

Rysunek 5.7.

Prezentacja w Internet Explorerze elementów i atrybutów

0x01 graphic

Obsługa zdarzeń występujących podczas ładowania dokumentów

Internet Explorer umożliwia także śledzenie postępów ładowania dokumentu XML do przeglądarki. Można użyć między innymi zdarzeń onreadystatechange oraz ondataavailable. Właściwość readyState zdarzenia onreadystatechange informuje o bieżącym stanie dokumentu. Oto przykład pokazujący, jak to działa:

<HTML>

<HEAD>

<TITLE>

Obsługa zdarzeń ładowania dokumentu

</TITLE>

<SCRIPT LANGUAGE="JavaScript">

var xmldoc

function loadDocument()

{

xmldoc = new ActiveXObject("microsoft.XMLDOM")

xmldoc.ondataavailable = dataAvailableHandler

xmldoc.onreadystatechange = stateChangeHandler

xmldoc.load('spotkania.xml')

}

function dataAvailableHandler()

{

messageDIV.innerHTML += "Stan: dane niedostępne.<BR>"

}

function stateChangeHandler()

{

switch (xmldoc.readyState)

{

case 1:

messageDIV.innerHTML +=

"Stan: dane nie zainicjalizowane.<BR>"

break

case 2:

messageDIV.innerHTML += "Stan: ładowanie danych.<BR>"

break

case 3:

messageDIV.innerHTML += "Stan: dane załadowane.<BR>"

break

case 4:

messageDIV.innerHTML +=

"Stan: zakończono ładowanie danych.<BR>"

if (xmldoc.parseError.errorCode != 0) {

messageDIV.innerHTML += "Stan: błąd.<BR>"

}

else {

messageDIV.innerHTML +=

"Stan: dane załadowano poprawnie.<BR>"

}

break

}

}

</SCRIPT>

</HEAD>

<BODY>

<CENTER>

<H1>

Obsługa zdarzeń ładowania dokumentu

</H1>

</CENTER>

<CENTER>

<INPUT TYPE="BUTTON" VALUE="Załaduj dokument"

ONCLICK="loadDocument()">

</CENTER>

<DIV ID="messageDIV"></DIV>

</BODY>

</HTML>

Wynikiem jest strona pokazana na rysunku 5.8 - widać kolejne etapy ładowania dokumentu na stronę.

Rysunek 5.8.

Monitorowanie zdarzeń ładowania dokumentu XML do Internet Explorera

0x01 graphic

Walidacja dokumentów XML w Internet Explorerze

Domyślnie Internet Explorer podczas ładowania dokumentu XML automatycznie go waliduje, ale jeśli nie sprawdzisz ustawień obiektu parseError, błędów walidacji nie zobaczysz.

Włączanie i wyłączanie walidacji

Walidację dokumentu można włączać i wyłączać stosując właściwość validateOnParse obiektu document; jej wartość domyślna to true.

Oto przykład: ładujemy dokument XML error.xml. Dokument ten nie daje się walidować, gdyż element IMIĘNAZWISKO zadeklarowano jako zawierający jedynie element IMIĘ:

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

<!DOCTYPE DOKUMENT [

<!ELEMENT DOKUMENT (KLIENT)*>

<!ELEMENT KLIENT (IMIĘNAZWISKO,DATA,ZAMÓWIENIA)>

<!ELEMENT IMIĘNAZWISKO (IMIĘ)>

<!ELEMENT NAZWISKO (#PCDATA)>

<!ELEMENT IMIĘ (#PCDATA)>

<!ELEMENT DATA (#PCDATA)>

<!ELEMENT ZAMÓWIENIA (POZYCJA)*>

<!ELEMENT POZYCJA (PRODUKT,ILOŚĆ,CENA)>

<!ELEMENT PRODUKT (#PCDATA)>

<!ELEMENT ILOŚĆ (#PCDATA)>

<!ELEMENT CENA (#PCDATA)>

]>

<DOKUMENT>

<KLIENT>

<IMIĘNAZWISKO>

<NAZWISKO>Smith</NAZWISKO>

<IMIĘ>Sam</IMIĘ>

</IMIĘNAZWISKO>

<DATA>15 paĽdziernika 2001</DATA>

<ZAMÓWIENIA>

<POZYCJA>

<PRODUKT>Pomidory</PRODUKT>

<ILOŚĆ>8</ILOŚĆ>

<CENA>5zł</CENA>

</POZYCJA>

<POZYCJA>

<PRODUKT>Pomarańcze</PRODUKT>

<ILOŚĆ>24</ILOŚĆ>

<CENA>9.98zł</CENA>

</POZYCJA>

</ZAMÓWIENIA>

</KLIENT>

</DOKUMENT>

Oto strona, która odczytuje i sprawdza dokument - do analizy przyczyny błędu używamy właściwości errorCode, url, line, linepos, errorString i reason obiektu parseError:

<HTML>

<HEAD>

<TITLE>

Walidacja dokumentów

</TITLE>

<SCRIPT LANGUAGE="JavaScript">

var xmldoc

function loadDocument()

{

xmldoc = new ActiveXObject("microsoft.XMLDOM")

xmldoc.onreadystatechange = stateChangeHandler

xmldoc.ondataavailable = dataAvailableHandler

xmldoc.load('error.xml')

}

function dataAvailableHandler()

{

messageDIV.innerHTML += "Stan: dane dostępne.<BR>"

}

function stateChangeHandler()

{

if(xmldoc.readyState == 4) {

var errorString = xmldoc.parseError.srcText

errorString =

xmldoc.parseError.srcText.replace(/\</g, "&lt;")

errorString = errorString.replace(/\>/g, "&gt;")

if (xmldoc.parseError.errorCode != 0) {

messageDIV.innerHTML = "Problem z " +

xmldoc.parseError.url +

" wiersz " + xmldoc.parseError.line +

" pozycja " +xmldoc.parseError.linepos +

":<BR>Źródło błędu: " + errorString +

"<BR>" + xmldoc.parseError.reason +

"<BR>" + "Błąd: " +

xmldoc.parseError.errorCode

}

else {

messageDIV.innerHTML =

"Stan: załadowany dokument jest poprawny.<BR>"

}

}

}

</SCRIPT>

</HEAD>

<BODY>

<CENTER>

<H1>

Walidacja dokumentów

</H1>

</CENTER>

<DIV ID="messageDIV"></DIV>

<CENTER>

<INPUT TYPE="BUTTON" VALUE="Załadowanie dokumentu"

ONCLICK="loadDocument()">

</CENTER>

</BODY>

</HTML>

Na rysunku 5.9 pokazano wynik - zgłoszenie błędu walidacji.

Rysunek 5.9.

Walidacja dokumentów w Internet Explorerze

0x01 graphic

Być może zauważyłeś, że właściwość errorString zawiera fragment tekstu XML, który spowodował błąd. Problem jest z tekstem <NAZWISKO>Smith</NAZWISKO>, gdyż przeglądarka spróbuje zinterpretować występujące w nim znaczniki. Aby tego uniknąć, użyliśmy metody replace obiektu String do zamiany znaków < na &lt; i > na &gt; (metodzie replace przekazuje się wyrażenie regularne; zmiana < na &lt; wymaga użycia wyrażenia /\</g; zmiana > na &gt; wymaga użycia wyrażenia /\>/g).

Skrypty obsługi elementów XML

Internet Explorer udostępnia ograniczoną obsługę elementów XML. Można na przykład elementowi xlink z XHTML dodać atrybut onclick (standard XLinks będziemy omawiali później, w rozdziale 10).

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

<?xml-stylesheet TYPE="text/css" href="xlink.css"?>

--> <html>[Author:T]

<head>

</head>

<body>

Czy chcesz zajrzeć do <xlink xml:link="simple"

inline="false" href="http://www.w3c.org"

onclick="location.href='http://www.w3c.org'">W3C</xlink>?

</body>

</html>

W arkuszu stylów xlink.css można nakazać, aby elementy xlink były wyświetlane na niebiesko i podkreślane, jak zwykłe łącza hipertekstowe; możemy także zmienić kształt kursora znajdującego się nad takim łączem na dłoń:

xlink {color: #0000FF; text-decoration: underline; cursor: hand}

Wyniki pokazano na rysunku 5.10: kiedy użytkownik kliknie element xlink, Internet Explorer uruchomi kod z atrybutu onclick. W pokazanym przykładzie załadowana zostanie strona http://www.w3c.org. Jak widać, w Explorerze można wiązać instrukcje z elementami XML - wystarczy dodać atrybuty zdarzeń, takie jak onclick.

Rysunek 5.10.

Tworzenie „hiperłącza” w dokumencie XML w Internet Explorerze

0x01 graphic

Edycja dokumentów XML w Internet Explorerze

W Internet Explorerze można zmieniać treść dokumentu XML. Używa się do tego metod takich, jak createElement, insertBefore, createTextNode i appendChild.

W ramach przykładu zmienimy dokument spotkania.xml wstawiając nowy element, PRZEWODNICZĄCY:

<?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="obecna">

<IMIE>Edward</IMIE>

<NAZWISKO>Samson</NAZWISKO>

</OSOBA>

.

.

.

Zaczniemy od utworzenia nowego węzła odpowiadającego elementowi PRZEWODNICZĄCY i wstawienia go do dokumentu za pomocą metody insertBefore:

<HTML>

<HEAD>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

<!--

function alterDocument()

{

var xmldoc, rootNode, meetingsNode, meetingNode

var createdNode, createdTextNode

xmldoc = document.all.meetingsXML

rootNode = xmldoc.documentElement

meetingsNode = rootNode.firstChild

meetingNode = meetingsNode.firstChild

createdNode = xmldoc.createElement("PRZEWODNICZĄCY")

createdNode = meetingsNode.insertBefore(createdNode, meetingNode)

.

.

.

Teraz wewnątrz nowego elementu utworzymy węzeł tekstowy. Węzeł ten zawierał będzie tekst Ted Bond, utworzymy go stosując metodę createTextNode, następnie nasz nowy element wstawimy metodą appendChild:

<HTML>

<HEAD>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

<!--

function alterDocument()

{

var xmldoc, rootNode, meetingsNode, meetingNode

var createdNode, createdTextNode

xmldoc = document.all.meetingsXML

rootNode = xmldoc.documentElement

meetingsNode = rootNode.firstChild

meetingNode = meetingsNode.firstChild

createdNode = xmldoc.createElement("PRZEWODNICZĄCY")

createdNode = meetingsNode.insertBefore(createdNode, meetingsNode)

createdTextNode = xmldoc.createTextNode("Ted Bond")

createNode.appendChild(createdTextNode)

.

.

.

Dokument już zmodyfikowaliśmy, jednak nowe treści istnieją jedynie wewnątrz obiektu xmldoc. Jak wynik wyświetlić w przeglądarce? Obiekt DOMDocument ma metodę save, która umożliwia zapis dokumentu w nowym pliku, na przykład xmldoc.save("nowy.xml"). Metody tej nie można jednak użyć bez zmiany ustawień bezpieczeństwa Internet Explorera - domyślnie przeglądarce nie wolno zapisywać żadnych plików na lokalnym komputerze.

Zrobimy to inaczej. Treść dokumentu zapiszemy w ukrytej kontrolce formularza HTML (ukryta kontrolka po prostu zawiera tekst niewidoczny dla użytkownika), następnie dane wyślemy z formularza do skryptu ASP (Active Server Pages) znajdującego się na serwerze. Skrypt zwróci treść dokumentu z powrotem do przeglądarki, która go wyświetli. Poniżej pokazano skrypt ASP, echo.asp, w którym ustawiono typ MIME dokumentu text/xml, dodano instrukcję przetwarzania <?xml?> i przekazano dokument zwrotnie do Explorera (skrypty ASP przekraczają w zasadzie zakres tej książki, ale parę słów o nich powiemy w rozdziale 12).

<%@ LANGUAGE="VBSCRIPT" %>

<%

Response.Content.Type = "text/xml"

Response.Write "<?xml version=" & Chr(34) &

"1.0" & Chr(34) & "encoding=\"iso-8859-2\"?>" & Chr(13) & Chr(10)

Response.Write Request("data")

%>

Na moim komputerze działa serwer ASP, więc dokument XML wysłany zostanie pod adres URI http://default.db/echo.asp. Użyjemy metody submit formularza (która działa dokładnie tak, jakby użytkownik kliknął przycisk formularza SUBMIT) wywoływanej po załadowaniu dokumentu XML do ukrytej kontrolki:

<HTML>

<HEAD>

<XML ID="meetingsXML" SRC="spotkania.xml"></XML>

<SCRIPT LANGUAGE="JavaScript">

<!--

function alterDocument()

{

var xmldoc, rootNode, meetingsNode, meetingNode

var createdNode, createdTextNode

xmldoc = document.all.meetingsXML

rootNode = xmldoc.documentElement

meetingsNode = rootNode.firstChild

meetingNode = meetingsNode.firstChild

createdNode = xmldoc.createElement("PRZEWODNICZĄCY")

createdNode = meetingsNode.insertBefore(createdNode, meetingNode)

createdTextNode = xmldoc.createTextNode("Ted Bond")

createdNode.appendChild(createdTextNode)

document.all.data.value = meetingsXML.documentElement.xml

document.form1.submit()

}

//-->

</SCRIPT>

</HEAD>

<BODY>

<CENTER>

<FORM NAME="form1" ACTION="http://default/db/echo.asp" METHOD="POST">

<INPUT TYPE="HIDDEN" NAME="data">

<INPUT TYPE="BUTTON" VALUE="Modyfikacja dokumentu"

onclick="alterDocument()">

</FORM>

</CENTER>

</BODY>

</HTML>

Kiedy teraz użytkownik kliknie przycisk Modyfikacja dokumentu, dokument XML zostanie zmodyfikowany i wysłany na serwer. Wtedy skrypt ASP zwróci przeglądarce dokument XML, a przeglądarka ten dokument wyświetli - pokazano to na rysunku 5.11. Na rysunku widać nowy element, PRZEWODNICZĄCY.

Rysunek 5.11.

Zmiana dokumentu XML w Internet Explorerze

0x01 graphic

W tym rozdziale użyliśmy JavaScriptu do parsowania i obsługi dokumentów XML. W następnym rozdziale użyjemy JavaScriptu do potraktowania danych XML jako obiektów baz danych.

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\r05-01.doc

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



Wyszukiwarka

Podobne podstrony:
r03-01, ## Documents ##, XML Vademecum profesjonalisty
r04-01, ## Documents ##, XML Vademecum profesjonalisty
r07-01, ## Documents ##, XML Vademecum profesjonalisty
r06-01, ## Documents ##, XML Vademecum profesjonalisty
r12-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]
R05-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
Asembler dla procesorow Intel Vademecum profesjonalisty asinvp

więcej podobnych podstron