Rozdział 2.
Tworzenie poprawnie sformułowanych dokumentów XML
W poprzednim rozdziale naszą znajomość z XML zaczęliśmy od dowiedzenia się, na czym polega strukturyzacja dokumentów w XML, czym ten język w ogóle jest i jak się go używa. Teraz czas przyjrzeć się XML dokładniej - na tyle dokładnie, aby stać się specjalistą.
W HTML mamy około 100 predefiniowanych elementów. Przeglądarka może odczytać HTML z witryny i wyświetlić go zgodnie ze swoją interpretacją. W XML autor ma więcej swobody, wobec czego większa jest też jego odpowiedzialność. Definiuje się samemu elementy i autor musi zdecydować, jak mają być używane. Jednak dokumenty - mimo że tak ogólne - podlegają szeregowi ścisłych ograniczeń, które sprawiają, że dokumenty te są proste w użyciu dzięki ich jednolitej postaci.
Tak naprawdę wymagania względem dokumentów XML są znacznie większe niż względem dokumentów HTML. Jak wspomniano w rozdziale 1, jeśli procesor nie jest w stanie w pełni zrozumieć dokumentu XML, nie ma on niczego się domyślać o dokumencie - ma po prostu zakończyć swoje działanie i ewentualnie zwrócić kod błędu.
Wspomniano też, że dokumenty XML podlegają dwóm rodzajom ograniczeń: poprawności sformułowania oraz walidacji. Zgodnie z wykładnią W3C poprawność jest wymaganiem bardziej elementarnym. W specyfikacji XML określono, że dokumentu nie można nawet nazwać dokumentem XML, jeśli nie jest on poprawnie sformułowany.
Obiekt z danymi jest dokumentem XML, jeśli jest poprawnie sformułowany, jak to zdefiniowano w niniejszej specyfikacji. Jeśli dokument spełnia pewne dodatkowe warunki, może być walidowany.
Czemu poprawność sformułowania jest tak ważna? Czemu W3C zabrania procesorom XML próbować naprawiać źle sformułowane dokumenty?
Chodzi o to, aby procesory XML uniknęły pułapki, w którą wpadły przeglądarki HTML: usiłują możliwie dużo poprawiać, ale kosztem tego jest faktycznie istnienie różnych wersji HTML, z których każda jest obsługiwana w innym narzędziu.
W tym rozdziale zastanowimy się, co stanowi o poprawności sformułowania dokumentu XML, czyli minimum wymagań. Drugim wymaganiem względem dokumentu XML może być walidacja, czyli zgodność dokumentu z definicją typu dokumentu (DTD) lub schematem, czyli zachowanie wymaganej składni. W tym rozdziale skupimy się na opisaniu poprawności sformułowania.
Teraz mówimy o tworzeniu dokumentów formalnie, więc zaczniemy od samego początku, aby dać dobre podstawy - tak więc zaczniemy od W3C.
World Wide Web Consortium
Wiemy już, że to W3C jest odpowiedzialne za dokładne określenie, czym jest XML, ale czym właściwie jest W3C? Nie jest to agenda rządowa, jest to grupa organizacji członkowskich (obecnie jest ich ponad 400) zainteresowanych WWW. W3C ma siedziby w Laboratorium nauk komputerowych na Politechnice Massachusetts (MIT/LCS) w Stanach Zjednoczonych, w Narodowym Instytucie Informatyki i Automatyki (INRIA) w Europie oraz na Uniwersytecie Keio Sonan Fujisawa Campus w Japonii. Obecnie W3C zatrudnia ponad 50 pełnoetatowych pracowników.
Jak W3C określa specyfikacje dla Sieci? Otóż są one publikowane w postaci HTML (a ostatnio XHTML) w Sieci, w witrynie www.w3.org. Specyfikacje te mogą mieć trzech różnych rodzajów:
Powiadomienia. Są to specyfikacje przysłane do W3C przez organizację członkowską, które organizacja zdecydowała się opublikować, choć niekoniecznie W3C musi je popierać. Na przykład powiadomienie o specyfikacji Microsoftu Wektorowego języka znaczników (VML) dostępne jest pod adresem www.w3.org/TR/NOTE-VML.
Szkice robocze. Szkic roboczy to specyfikacja, która cały czas jest opracowywana i można do niej zgłaszać swoje uwagi. Takich specyfikacji nie należy traktować jako standardów czy czegokolwiek innego - są to szkice robocze. Przykładem szkicu roboczego jest specyfikacja XHTML 1.1 dostępna pod adresem www.w3.org/TR/xhtml11/.
Rekomendacje. Szkice robocze, które zostały w W3C zaakceptowane, stają się rekomendacjami. W3C używa właśnie terminu rekomendacja, a nie standard, gdyż W3C nie jest organizacją rządową i nie ma uprawnień do publikowania standardów. Przykładem rekomendacji jest XML 1.0 dostępna pod adresem www.w3.org/TR/REC-xml.
Niezależnie od owych oficjalnych typów specyfikacji istnieje jeszcze w W3C pojęcie rekomendacji proponowanej, która jest szkicem roboczym, który został zaproponowany już jako rekomendacja, ale nie został jeszcze zaakceptowany. Istnieją też rekomendacje towarzyszące, które uzupełniają normalne rekomendacje. Istnieje mnóstwo rekomendacji towarzyszących związanych z XML (schematy XML, XLinks, XPointers i tak dalej), ich listę znajdziesz pod adresem www.w3c.org/xml.
Rekomendacja definiująca XML 1.0 znajduje się pod adresem www.w3.org/TR/REC-xml. Dla naszej książki ta rekomendacja jest najważniejsza. Wraz ze związanymi z nią standardami (Unicode i ISO/IEC 10646 z opisem znaków, Internet RFC 1766 ze znacznikami identyfikującymi języki, ISO 639 z kodami nazw języków oraz ISO 3166 z kodami nazw krajów) rekomendacja ta zapewnia wszystko, co jest potrzebne do zrozumienia XML w wersji 1.0 i tworzenia dokumentów XML. Teraz czas tę rekomendację wykorzystać tworząc poprawnie sformułowane dokumenty.
Czym jest poprawnie sformułowany dokument XML?
W3C, twórca terminu poprawność sformułowania, definiuje to pojęcie w rekomendacji XML 1.0:
Obiekt tekstowy jest poprawnie sformułowanym dokumentem, jeśli:
Proszę o kontrolę poniższego punktu.
Jako całość spełnia definicję dokumentu etykietowego.
Zgodny jest z regułami poprawności sformułowania podanymi w specyfikacji (www.w3.org/TR/REC-xml).
Każda parsowana encja (część), do której w dokumencie jest odwołanie bezpośrednie lub pośrednie, jest poprawnie sformułowana.
W3C nazywa poszczególne specyfikacje szkicu roboczego lub rekomendacji definicjami. W tym wypadku, aby być poprawnie sformułowanym, dokument musi być zgodny z definicją dokumentu, co oznacza, że sam dokument musi mieć trzy części: prolog (może być pusty), element główny i opcjonalną część końcową.
Prolog, który wkrótce będzie omawiany, może i powinien zawierać deklarację XML (<?xml version="1.0"?>) oraz opcjonalną część końcową zawierającą komentarze, instrukcje przetwarzania i tak dalej. Element główny dokumentu zawierać może inne elementy - trudno zresztą wyobrazić sobie użyteczny dokument XML, w którym element główny nie zawiera już żadnych innych elementów. Poprawnie sformułowany dokument zawiera zawsze dokładnie jeden element główny, wszystkie inne elementy muszą być w elemencie głównym zawarte (nie dotyczy to oczywiście prologu, gdyż instrukcje przetwarzania czy komentarze nie są elementami).
Część końcowa zawierać może komentarze, instrukcje przetwarzania i białe znaki (spacje, tabulatory i tak dalej). Dalej zajmiemy się dokładniej prologiem, elementem głównym i częścią końcową.
Następnie żąda się, aby dokument XML był poprawnie sformułowany zgodnie z regułami podanymi w specyfikacji XML 1.0 Oznacza to, że dokument XML musi spełniać wymagania składniowe określone w rekomendacji XML 1.0. Reguły te omówimy też w tym rozdziale.
Wymagania poprawności sformułowania
Jeśli przejrzysz specyfikację XML 1.0, zauważysz, że odpowiednie wymagania oznaczone są słowami „Well-Formedness Constraint”.
W końcu wymaga się, aby każda parsowana encja (część) była sama poprawnie sformułowana. Co to znaczy?
Części dokumentu XML nazywa się encjami. Encja to część dokumentu, która zawierać może tekst lub dane binarne (ale nie jedno i drugie). Encja odwoływać się może do innych encji i w ten sposób włączać je do dokumentu. Encje mogą być parsowane (dane tekstowe) lub nieparsowane (albo dane tekstowe zawierające coś innego niż kod XML, albo dane binarne, których procesor XML nie będzie analizował). Krótko mówiąc encja to ogólne określenie jednostki składowej w XML. Na przykład plik z kilkoma elementami XML jest encją ale jeśli nie jest poprawnie sformułowany, nie jest dokumentem.
Reguła dotycząca encji parsowanych mówi, że jeśli odwołujesz się do encji i włączasz do dokumentu dane tej encji (które zawierać mogą dane ze źródeł zewnętrznych), te włączane dane muszą być poprawnie sformułowane.
Taka jest definicja poprawnie sformułowanego dokumentu, ale jeszcze daleko nam do pełnej jasności co do jej znaczenia. Jakie są owe wymagania poprawności, których trzeba się trzymać? Co dokładnie może wystąpić w prologu? Aby odpowiedzieć na te i podobne pytania, w dalszej części tego rozdziału omówimy wszystko dokładniej.
Zaczniemy od przyjrzenia się dokumentowi XML, który będziemy omawiali w tym rozdziale zastanawiając się, jakie warunki trzeba spełnić, aby był on poprawnie sformułowany. Będziemy zapisywać w dokumencie order.xml dane o pewnych zakupach. Zaczynamy oczywiście od deklaracji XML:
<?xml version="1.0" encoding="iso-8859-2"?>
Użyliśmy deklaracji <?xml?>, aby wskazać, że tworzymy dokument XML, wskazaliśmy też wersję - jedyną obecnie istniejącą, czyli 1.0. Dokumenty umieszczane w tym rozdziale będą samodzielne (czyli nie będą odwoływały się ani nie będą zawierały żadnych encji zewnętrznych), więc można ustawić wartość atrybutu standalone (samodzielny) na yes (tak):
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
Atrybut ten, który może być przez parser użyty lub nie, wskazuje, czy dokument jest całkowicie samodzielny. Formalnie rzecz biorąc dokumenty XML nie muszą zaczynać się od deklaracji XML, ale W3C zaleca jej stosowanie.
Następnie dodajemy element główny, będzie to DOKUMENT - nazwa jednak mogłaby być dowolna:
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<DOKUMENT>
.
.
.
</DOKUMENT>
Element główny może oczywiście zawierać inne elementy. Dodamy na razie trzy elementy opisujące klientów:
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<DOKUMENT>
<KLIENT>
.
.
.
</KLIENT>
<KLIENT>
.
.
.
</KLIENT>
<KLIENT>
.
.
.
</KLIENT>
</DOKUMENT>
Będziemy zapisywać nazwiska klientów - w elemencie IMIĘNAZWISKO umieścimy elementy NAZWISKO i IMIĘ:
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<DOKUMENT>
<KLIENT>
<IMIĘNAZWISKO>
<NAZWISKO>Smith</NAZWISKO>
<IMIĘ>Sam</IMIĘ>
</IMIĘNAZWISKO>
.
.
.
</KLIENT>
<KLIENT>
.
.
.
</KLIENT>
<KLIENT>
.
.
.
</KLIENT>
</DOKUMENT>
Szczegóły dotyczące zamówień klientów umieścimy w elementach DATA oraz ZAMÓWIENIA:
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<DOKUMENT>
<KLIENT>
<IMIĘNAZWISKO>
<NAZWISKO>Smith</NAZWISKO>
<IMIĘ>Sam</IMIĘ>
</IMIĘNAZWISKO>
<DATA>15 października 2001</DATA>
<ZAMÓWIENIA>
.
.
.
</ZAMÓWIENIA>
.
.
.
</KLIENT>
<KLIENT>
.
.
.
</KLIENT>
<KLIENT>
.
.
.
</KLIENT>
</DOKUMENT>
Z kolei każdy zakup opisywać będziemy w elemencie POZYCJA, który z kolei rozbity będzie na elementy PRODUKT, ILOŚĆ i CENA:
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<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>
<KLIENT>
.
.
.
</KLIENT>
<KLIENT>
.
.
.
</KLIENT>
</DOKUMENT>
Tak wyglądają dane jednego klienta, natomiast kompletny dokument z danymi wszystkich trzech klientów będzie miał postać:
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<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>
<KLIENT>
<IMIĘNAZWISKO>
<NAZWISKO>Jones</NAZWISKO>
<IMIĘ>Polly</IMIĘ>
</IMIĘNAZWISKO>
<DATA>20 października 2001</DATA>
<ZAMÓWIENIA>
<POZYCJA>
<PRODUKT>Chleb</PRODUKT>
<ILOŚĆ>12</ILOŚĆ>
<CENA>28.80zł</CENA>
</POZYCJA>
<POZYCJA>
<PRODUKT>Jabłka</PRODUKT>
<ILOŚĆ>6</ILOŚĆ>
<CENA>6.00zł</CENA>
</POZYCJA>
</ZAMÓWIENIA>
</KLIENT>
<KLIENT>
<IMIĘNAZWISKO>
<NAZWISKO>Weber</NAZWISKO>
<IMIĘ>Bill</IMIĘ>
</IMIĘNAZWISKO>
<DATA>25 października 2001</DATA>
<ZAMÓWIENIA>
<POZYCJA>
<PRODUKT>Asparagus</PRODUKT>
<ILOŚĆ>12</ILOŚĆ>
<CENA>11.90zł</CENA>
</POZYCJA>
<POZYCJA>
<PRODUKT>Sałata</PRODUKT>
<ILOŚĆ>6</ILOŚĆ>
<CENA>31.50zł</CENA>
</POZYCJA>
</ZAMÓWIENIA>
</KLIENT>
</DOKUMENT>
Tego typu dokumenty mogą być bardzo długie i mogą zawierać wiele poziomów zagnieżdżenia elementów. Obsługa takich dokumentów nie stanowi dla procesora XML problemu, byle tylko dokument był poprawnie sformułowany (a w przypadku parsera walidującego także dał się walidować). W tym rozdziale będziemy się do pokazanego dokumentu odwoływać, modyfikować go i przyglądać się jego częściom - zastanowimy się, dlaczego ten dokument uznać można za poprawnie sformułowany.
Teraz możemy już nasz dokument rozebrać na kawałeczki. Zaczniemy od podstaw i przerobimy prolog, element główny, elementy zawarte wewnątrz i tak dalej. Wszystko to omówimy w tym rozdziale.
Upraszczając rzecz jak najbardziej dokument XML traktować można jako połączenie znaczników i danych znakowych. Zaczniemy od tego właśnie podziału.
Znaczniki i dane znakowe
Dokumenty XML składają się ze znaczników i danych znakowych. Być może kiedyś dane binarne też znajdą się w dokumentach XML, ale na razie nie jest to potrzebne. Na razie można odwoływać się do zewnętrznych danych binarnych przez odwołania do encji, co omówimy później.
Znaczniki w dokumencie określają jego strukturę. Znaczniki to znaczniki początkowe, końcowe, znaczniki elementów pustych, odwołania do encji, odwołania do encji znakowych, komentarze, ograniczniki sekcji CDTA (o tym wkrótce), deklaracje typu dokumentu i instrukcje przetwarzania. Czym są zatem dane znakowe w dokumencie XML? Są to po prostu wszystkie napisy nie będące znacznikami.
Oto krótki przykład - już nam dobrze znany - zawierający znaczniki i dane znakowe:
<?xml version="1.0" encoding="iso-8859-2"?>
<DOKUMENT>
<POZDROWIENIA>
Witaj w XML
</POZDROWIENIA>
<KOMUNIKAT>
Witaj w pokręconym świecie XML.
</KOMUNIKAT>
</DOKUMENT>
Znacznik zaczyna się znakiem <, kończy się znakiem >, więc łatwo zauważyć, że występują tutaj znaczniki <?xml version="1.0" encoding="iso-8859-2"?>, <DOKUMENT> i tak dalej. Z kolei napisy Witaj w XML oraz Witaj w pokręconym świecie XML. są danymi znakowymi.
Jednak znaczniki nie muszą być zawarte między znakami < i >, ale mogą zaczynać się od & i kończyć się ; - są to odwołania do encji ogólnych (odwołania takie podczas parsowania są zamieniane na treść odpowiadających im encji), mogą zaczynać się od % i kończyć ; - są to odwołania do encji parametrycznych używanych w DTD. Używając odwołań do encji można spowodować, że niektóre znaczniki staną się podczas przetwarzania dokumentu zwykłymi danymi znakowymi. Na przykład znacznik > to odwołanie do encji ogólnej, które podczas parsowania dokumentu zostanie zamienione na znak >, natomiast znacznik < zamieniony zostanie na znak <. Oto przykład:
<?xml version="1.0" encoding="iso-8859-2"?>
<DOKUMENT>
<POZDROWIENIA>
Ten tekst znajduje się za znacznikiem <POZDROWIENIA>.
</POZDROWIENIA>
</DOKUMENT>
Dokument ten w Internet Explorerze możesz obejrzeć na rysunku 2.1. Znacznik > zamieniony został na znak >, a < na znak <.
Rysunek 2.1. Użycie znaczników w Internet Explorerze |
|
Z uwagi na to, że podczas parsowania część znaczników może zostać zamieniona na dane znakowe, dane znakowe powstające po zakończeniu parsowania całości, a także znaczniki, które mają być zamienione na dane znakowe, mają specjalną nazwę: parsowane dane znakowe.
Białe znaki
Jeśli zastanawiasz się, jakich znaków można używać w dokumentach XML, odpowiedź znajdziesz w samej specyfikacji XML 1.0 przy definicji o nazwie Char. Warto zwrócić uwagę na to, że w XML spacje, znaki końca wiersza i powrotu karetki oraz tabulatory uważane są w XML za białe znaki. Przyjrzyjmy się 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>
Dokument ten równoważny jest dokumentowi następującemu:
<?xml version="1.0" encoding="iso-8859-2"?>
<DOKUMENT><POZDROWIENIA>Witaj w XML</POZDROWIENIA>
<KOMUNIKAT>Witaj w pokręconym świecie XML.</KOMUNIKAT></DOKUMENT>
Warto też zauważyć, że w rekomendacji XML zaleca się kończenie wierszy zgodnie z konwencją obowiązującą w systemie UNIX, czyli umieszczanie na końcu wiersza jedynie znaku nowego wiersza (kod ASCII 10), podczas gdy w systemie DOS na koniec wiersza dodaje się znaki powrotu karetki i dopiero nowego wiersza (kody ASCII 13 i 10) mimo, że w trakcie analizy takich dokumentów traktuje się te pliki tak, jakby na końcu miały jedynie pojedynczy znak nowego wiersza.
Obsługa białych znaków
W elemencie można użyć atrybutu xml:space, który nakazuje zachowanie w danym dokumencie odstępu znaków (jeśli zamierzasz użyć tego atrybutu w dokumencie posiadającym DTD, musisz go zadeklarować). Jeśli odpowiada Ci domyślny sposób traktowania odstępów, możesz atrybutowi temu nadać wartość default, natomiast jeśli chcesz wszystkie spacje w dokumencie zachować bez zmian, atrybut ten powinien mieć wartość preserve.
W ten sposób zaczynamy zajmować się dokumentami XML: znacznikami i danymi znakowymi. Czas pójść krok dalej i zacząć pracę z samym dokumentem, od prologu poczynając.
Prolog
Prolog znajduje się na samym początku dokumentu XML. Jeśli dokument ma być poprawnie sformułowany, nie musi mieć prologu. Jednak rekomendacja W3C zaleca włączenie przynajmniej deklaracji XML, w której podana jest stosowana wersja XML. Prolog zawiera deklarację XML, komentarze, instrukcje przetwarzania, białe znaki i deklarację (lub deklaracje) typu dokumentu.
Oto przykład: zaznaczyłem cały prolog dokumentu zawierający deklarację XML, instrukcję przetwarzania oraz DTD:
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<?xml-stylesheet type="text.css" href="greeting.css"?>
<!DOCTYPE DOKUMENT [
<!ELEMENT DOKUMENT (KLIENT)*>
<!ELEMENT KLIENT (IMIĘNAZWISKO,DATA,ZAMÓWIENIA)>
<!ELEMENT IMIĘNAZWISKO (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>
.
.
.
Przyjrzymy się dokładniej każdej części prologu (oprócz deklaracji typu dokumentu).
Deklaracja XML
Dokument XML może (a zgodnie z wytycznymi W3C powinien) zaczynać się od deklaracji XML, która ma poinformować, że dokument w XML jest napisany. Jeśli używasz deklaracji XML, powinna się ona znaleźć w pierwszym wierszu i nie powinno się nic przed nią pojawić. Oto przykład:
<?xml version="1.0" standalone="yes" encoding="UTF-8"?>
W deklaracji XML używa się --> instrukcji przetwarzania[Author:T] <?xml?>. We wcześniejszych wersjach specyfikacji XML używano zapisu <?XML?>, ale w ostatecznej wersji się to zmieniło, więc użycie wielkich liter jest błędem. Nadal natrafić można na aplikacje, w których użyto wersji zapisanej wielkimi literami i na przykład przeglądarka Internet Explorer taki zapis dopuszcza, przez co nie jest w pełni zgodna z rekomendacją W3C.
W deklaracji XML użyć można trzech atrybutów:
version. Używana wersja XML; obecnie może to być tylko 1.0. Jeśli podaje się deklarację XML, atrybut ten jest obowiązkowy.
encoding. Sposób kodowania znaków w dokumencie. Jak to omówiono w rozdziale 1, ustawieniem domyślnym jest UTF-8. Można też użyć Unicode, UCS-2 lub UCS-4 oraz wielu innych zestawów znaków, przede wszystkim zestawów ISO. Atrybut ten jest opcjonalny.
standalone. Jeśli ma wartość yes, dokument nie odwołuje się do encji zewnętrznych; w przeciwnym wypadku ma wartość no. Jest to atrybut opcjonalny.
Komentarze
Komentarze XML są bardzo podobne do komentarzy HTML. W komentarzach umieszczać można dodatkowe objaśnienia dotyczące dokumentu, które są ignorowane przez parser XML. Komentarze mogą pojawiać się w dowolnym miejscu dokumentu, byle na zewnątrz wszystkich znaczników. Tak jak w HTML, komentarze zaczyna się od <!--, kończy -->. Oto przykład:
<?xml version="1.0" encoding="iso-8859-2"?>
<DOKUMENT>
<!--Zaczynamy dokument poza elementem POZDROWIENIA.-->
<POZDROWIENIA>
<!--Tutaj będzie tekst pozdrowień.-->
Witaj w XML
</POZDROWIENIA>
</DOKUMENT>
Kiedy dodajesz do dokumentu XML komentarze, musisz pamiętać o kilku zasadach. Komentarze nie mogą pojawić się przed deklaracją XML, zatem poniższy przykład jest błędny:
<!--Oto mój dokument-->
<?xml version="1.0" encoding="iso-8859-2"?>
<DOKUMENT>
<POZDROWIENIA>
Witaj w XML
</POZDROWIENIA>
</DOKUMENT>
Nie wolno także umieszczać komentarzy wewnątrz znaczników:
<?xml version="1.0" encoding="iso-8859-2"?>
<DOKUMENT <!--Początek dokumentu-->>
<POZDROWIENIA>
Witaj w XML
</POZDROWIENIA>
</DOKUMENT>
Co więcej, w komentarzach nie można używać zestawu znaków --, gdyż parser szukając końca komentarza takiego właśnie takiego ciągu będzie wyszukiwał. Dlatego właśnie poniższy przykład jest niepoprawny:
<?xml version="1.0" encoding="iso-8859-2"?>
<DOKUMENT>
<!-- Zaczynamy dokument bardzo grzecznie -- od pozdrowień.-->
<POZDROWIENIA>
Witaj w XML
</POZDROWIENIA>
</DOKUMENT>
Komentarzy można używać do wyłączania fragmentów dokumentów, byle tylko owe fragmenty same nie zawierały żadnych komentarzy. W poniższym przykładzie wyłączono czasowo element KOMUNIKAT:
<?xml version="1.0" encoding="iso-8859-2"?>
<DOKUMENT>
<POZDROWIENIA>
Witaj w XML
</POZDROWIENIA>
<!--
<KOMUNIKAT>
Witaj w pokręconym świecie XML.
</KOMUNIKAT>
-->
</DOKUMENT>
Parser pokaże ten dokument w postaci następującej:
<?xml version="1.0" encoding="iso-8859-2"?>
<DOKUMENT>
<POZDROWIENIA>
Witaj w XML
</POZDROWIENIA>
</DOKUMENT>
Instrukcje przetwarzania
Instrukcje przetwarzania - zgodnie ze swoją nazwą - to instrukcje dla procesora XML. Zaczynają się od <? i kończą ?>. Jedynym ograniczeniem jest niemożność stosowania zarezerwowanych nazw instrukcji <?xml?> ani <?XML?>. Instrukcje przetwarzania są przeznaczone dla procesora XML, więc są różne dla różnych procesorów, nie wchodzą w skład specyfikacji XML.
Bardzo powszechnie stosowaną i zwykle rozumianą instrukcją przetwarzania jest <?xml-stylesheet?> łącząca dokument XML z arkuszem stylów (oczywiście ona także nie należy do rekomendacji XML 1.0). Oto przykład jej użycia:
<?xml version="1.0" encoding="iso-8859-2"?>
<?xml-stylesheet type="text/css" href="greeting.css"?>
<DOKUMENT>
<POZDROWIENIA>
Witaj w XML
</POZDROWIENIA>
<KOMUNIKAT>
Witaj w pokręconym świecie XML.
</KOMUNIKAT>
</DOKUMENT>
Procesory XML - takie, jak te używane w Internet Explorerze 5 czy Netscape Navigatorze 6 - już rozumieją instrukcję <?xml-stylesheet?>.
Skończyliśmy właśnie omawiać elementy, które może zawierać prolog XML: deklaracje XML, komentarze, instrukcje przetwarzania i białe znaki (pominęliśmy jedynie DTD). Teraz czas przyjrzeć się dokładniej podstawowej strukturze dokumentu XML, czyli znacznikom i elementom.
Znaczniki i elementy
Strukturę dokumentu XML określa się za pomocą znaczników wyznaczających elementy. Element XML składa się ze znacznika początkowego oraz znacznika końcowego --> oraz treści[Author:T] , czyli tego, co się między tymi znacznikami znajduje. Wyjątkiem są elementy puste, które mogą składać się tylko z jednego znacznika o specyficznej konstrukcji.
Znacznik początkowy (czasem nazywany także znacznikiem otwierającym) zaczyna się od < i kończy >. Znacznik końcowy (czasem nazywany zamykającym) zaczyna się od </ i kończy >.
Nazwy elementów
Specyfikacja XML bardzo dokładnie określa, jak mają wyglądać nazwy elementów: muszą zaczynać się od litery, podkreślenia lub dwukropka. Dalej mogą się znajdować litery, cyfry, podkreślenia, kreski (myślniki), kropki i średniki, nie mogą natomiast pojawić się żadne białe znaki.
Unikaj dwukropków w nazwach
Wprawdzie w rekomendacji XML 1.0 takiego zalecenia nie znajdziesz, to powinieneś zdecydowanie unikać umieszczania dwukropków w nazwach elementów, gdyż przyjęto za ich pomocą oznaczać przestrzenie nazw (będziemy o tym jeszcze w tym rozdziale mówili).
--> Oto kilka przykładowych, poprawnych znaczników XML:[Author:T]
<DOKUMENT>
<dokument>
<_Zapis>
<klient>
<NUMER.PRODUKTU>
Pamiętaj, że dla procesorów XML istotna jest wielkość liter, więc znacznik <DOKUMENT> jest czymś całkiem innym niż znacznik <dokument>. Zresztą możliwości jest więcej - <DoKuMeNt> też jest poprawnym znacznikiem, choć takiego stosowania wielkich liter zdecydowanie nie zalecam.
Oto znaczniki końcowe odpowiadające podanym wyżej znacznikom początkowym:
</DOKUMENT>
</dokument>
</_Zapis>
</klient>
</NUMER.PRODUKTU>
Z kolei poniższe znaczniki są nieprawidłowe:
<2001DOKUMENT>
<.dokument>
<Numer zapisu>
<nazwisko*klienta>
<PRODUKT(ID)>
Za pomocą znaczników początkowych i końcowych możesz tworzyć elementy - w naszym przykładzie mamy trzy elementy: DOKUMENT, POZDROWIENIA i KOMUNIKAT:
<?xml version="1.0" encoding="iso-8859-2"?>
<?xml-stylesheet type="text/css" href="greeting.css"?>
<DOKUMENT>
<POZDROWIENIA>
Witaj w XML
</POZDROWIENIA>
<KOMUNIKAT>
Witaj w pokręconym świecie XML.
</KOMUNIKAT>
</DOKUMENT>
Można także tworzyć elementy bez używania znaczników końcowych - dotyczy to elementów zadeklarowanych jako puste.
Elementy puste
Elementy puste mają jeden tylko znacznik, nie mają zwykłych znaczników początkowego i końcowego. Elementy puste zapewne dobrze Ci są znane z HTML, przykładami są choćby znaczniki <IMG>, <LI>, <HR> i <BR>. Są one puste, czyli nie zawierają żadnej treści (danych znakowych ani innych znaczników).
Elementom pustym odpowiada jeden tylko znacznik. W HTML po prostu nie podaje się znacznika końcowego, w XML element trzeba zadeklarować jako pusty. W takim wypadku znacznik takiego elementu można od razu zakończyć nie >, lecz /> - wtedy znacznik końcowy jest zbędny. Jeśli element POZDROWIENIA byłby pusty, miałby następującą postać:
<?xml version="1.0" encoding="iso-8859-2"?>
<DOKUMENT>
<POZDROWIENIA TEKST="Witaj w XML"/>
</DOKUMENT>
Taki zapis w pierwszej chwili może wyglądać dość dziwnie, ale w ten sposób zapewnia się, że procesor XML nie będzie usiłował odszukać nieistniejącego znacznika końcowego. Tak naprawdę w XHTML zamiast znanych z HTML znaczników <IMG>, <LI>, <HR> i <BR> stosuje się wyprowadzone z XML <img/>, <li/>, <hr/> i <br/>. Dodatkowy ukośnik nie wydaje się sprawiać przeglądarkom jakichś szczególnych trudności.
Element główny
Poprawnie sformułowany dokument XML musi zawierać jeden element, który będzie zawierał wszystkie inne elementy - jest to element główny. Element ten jest w dokumentach XML bardzo ważny, szczególnie z punktu widzenia programisty, gdyż parsowanie zawsze zaczyna się od tego właśnie elementu. W pliku order.xml, który tworzyliśmy na początku tego rozdziału, elementem głównym jest DOKUMENT (ale element główny może się dowolnie nazywać):
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<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>Sałata</PRODUKT>
<ILOŚĆ>6</ILOŚĆ>
<CENA>31.50zł</CENA>
</POZYCJA>
</ZAMÓWIENIA>
</KLIENT>
</DOKUMENT>
Atrybuty
Atrybuty XML są bardzo podobne do atrybutów HTML - są to pary nazw i wartości umożliwiające wstawianie dodatkowych informacji w znacznikach początkowym i elementu pustego. Aby przypisać atrybutowi wartość, używa się znaku równości.
Na przykład poniżej każdemu elementowi KLIENT dodajemy atrybut STATUS, w którym opisujemy klienta jako kredytobiorcę:
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<DOKUMENT>
<KLIENT STATUS="Rzetelny kredytobiorca">
<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>
<KLIENT STATUS="Kredytobiorca niesolidny">
<IMIĘNAZWISKO>
<NAZWISKO>Jones</NAZWISKO>
<IMIĘ>Polly</IMIĘ>
</IMIĘNAZWISKO>
<DATA>20 października 2001</DATA>
<ZAMÓWIENIA>
<POZYCJA>
<PRODUKT>Chleb</PRODUKT>
<ILOŚĆ>12</ILOŚĆ>
<CENA>28.80zł</CENA>
</POZYCJA>
<POZYCJA>
<PRODUKT>Jabłka</PRODUKT>
<ILOŚĆ>6</ILOŚĆ>
<CENA>6.00zł</CENA>
</POZYCJA>
</ZAMÓWIENIA>
</KLIENT>
<KLIENT STATUS="Rzetelny kredytobiorca">
<IMIĘNAZWISKO>
<NAZWISKO>Weber</NAZWISKO>
<IMIĘ>Bill</IMIĘ>
</IMIĘNAZWISKO>
<DATA>25 października 2001</DATA>
<ZAMÓWIENIA>
<POZYCJA>
<PRODUKT>Asparagus</PRODUKT>
<ILOŚĆ>12</ILOŚĆ>
<CENA>11.90zł</CENA>
</POZYCJA>
<POZYCJA>
<PRODUKT>Sałata</PRODUKT>
<ILOŚĆ>6</ILOŚĆ>
<CENA>31.50zł</CENA>
</POZYCJA>
</ZAMÓWIENIA>
</KLIENT>
</DOKUMENT>
Dokument ten załadowany do Internet Explorera wraz z atrybutami i ich wartościami obejrzeć możesz na rysunku 2.2.
Rysunek 2.2. Użycie atrybutów w Internet Explorerze |
|
Procesor XML odczytuje atrybuty i ich wartości, można ich następnie używać w aplikacji. Później zajmiemy się czytaniem atrybutów w Javie i JavaScripcie.
Częste toczone są debaty, czy dane lepiej przechowywać w atrybutach, czy w elementach. Na tak postawione nie ma jednoznacznej odpowiedzi, jednak pewne ogólne zasady można podać.
Po pierwsze, zbyt duża liczba atrybutów niewątpliwie utrudni czytanie dokumentu. Spójrz na przykład na poniższy element:
<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>
</ZAMÓWIENIA>
</KLIENT>
Nietrudno się domyślić, o co tutaj chodzi. Jeśli jednak spróbujesz te same dane zapisać w postaci atrybutów, dostaniesz coś takiego:
<KLIENT NAZWISKO="Smith" IMIĘ="Sam"
DATA="15 października 2001" ZAKUP="Pomidory"
ILOŚĆ="8" CENA="5zł"/>
Kiedy elementów takich będzie więcej, zrobi się kompletny bałagan.
Warto też zauważyć, że w przypadku zapisywania danych w atrybutach nie jesteś w stanie utworzyć struktury dokumentu. W naszym przykładzie z klientami dla jednego klienta przechowujemy kolejne zakupy. Nazwy atrybutów nie mogą się jednak powtarzać, zatem dane takie, jak pokazano poniżej, będzie w postaci atrybutów bardzo trudno zapisać:
<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>
Tak więc stwierdzić należy, że przechowywanie danych w atrybutach lub w elementach jest kwestią gustu, choć przekroczenie ilości kilku atrybutów na każdy element świadczy, że coś jest nie tak. Jeśli używasz (podkreślam: używasz, a nie deklarujesz) powyżej czterech atrybutów na element, zastanów się nad rozbiciem elementu na szereg elementów w sobie zawartych. Dzięki temu struktura dokumentu będzie znacznie prostsza w interpretacji i łatwiej będzie dokument edytować.
Nazwy atrybutów
Zgodnie ze specyfikacją XML 1.0 nazwy atrybutów podlegają tym samym regułom, które dotyczą nazw elementów, zatem atrybut zaczynać się może od litery, podkreślenia lub dwukropka, dalej mogą być litery, cyfry, podkreślenia, kreski (myślniki), kropki i dwukropki, nie mogą za to wystąpić białe znaki. Przyjrzyjmy się poniższym przykładom elementów z prawidłowymi atrybutami:
<koło środek_x="10.0" środek_y="20.0" promień="10.0"/>
<obrazek src="obrazek1.jpg">
<pisak kolor="czerwony" szerokość="5">
<książka stron="1231">
Poniższe atrybuty prawidłowe już nie są:
<koło 1środek_x="10.0" 1środek_y="20.0" 1promień="10.0"/>
<obrazek src name="obrazek1.jpg">
<pisak kolor@="czerwony" szerokość="5">
<książka stron(bez wstępu)="1231">
Wartości atrybutów
Znaczniki zawsze są tekstem, więc i wartości atrybutów są tekstem. Nawet jeśli atrybutowi przypiszesz liczbę, liczba ta będzie traktowana jako napis, który należy podawać w cudzysłowie:
<koło środek_x="10.0" środek_y="20.0" promień="10.0"/>
Oznacza to między innymi, że procesor XML wszystkie wartości atrybutów będzie zwracał jako tekst. Jeśli chcesz dane te traktować jako liczby, konieczne będzie sprawdzenie, czy uzyskana wartość faktycznie liczbę reprezentuje - stosuje się do tego typowe metody używane w różnych językach oprogramowania.
W XML wartości atrybutów ujmować trzeba w cudzysłowy. Zwykle używa się cudzysłowów podwójnych, ale jeśli sam atrybut zawierałby cudzysłów, to procesor XML nie wiedziałby, gdzie się tekst kończy. W takim wypadku cały tekst można objąć pojedynczym cudzysłowem:
<cytat tekst='"Nie tak!"-powiedział'/>
A co zrobić, jeśli atrybut zawiera zarówno pojedynczy, jak i podwójny cudzysłów? W takim wypadku używa się predefiniowanej encji znakowej ' do zastąpienia cudzysłowu pojedynczego lub " zamiast cudzysłowu podwójnego (same encje będą omówione później). Aby zatem zapisać wartość atrybutu 1'=stopa, 1"=cal, piszemy:
<jednostki usa="1'=stopa, 1"=cal"/>
Przypisywanie atrybutom wartości
Jeśli chcesz używać atrybutów, musisz przypisywać im wartości. Jeśli tego nie zrobisz, będzie to potraktowane jako błąd poprawności sformułowania. W XML nie wolno stosować „samodzielnych” atrybutów, jak BORDER w HTML, który bez wartości doskonale mógł się obejść.
Przydatny atrybut xml:lang
Warto wspomnieć o pewnym ogólnie stosowanym atrybucie, xml:lang. Często przydatne jest wskazanie języka, w jakim zapisana jest treść dokumentu i wartości atrybutów - jest to szczególnie potrzebne programom takim, jak przeglądarki sieciowe. W znacznikach XML język można wskazać podając atrybut xml:lang (w przypadku walidacji dokumentu atrybut ten, podobnie jak wszystkie inne, musi być przed użyciem zadeklarowany).
Atrybut xml:lang może mieć jedną z następujących wartości:
Dwuliterowy kod języka zgodnie z normą ISO 639.
Identyfikator języka zatwierdzony przez IANA - identyfikatory takie zaczynają się od i- lub I-.
Identyfikatora języka zdefiniowanego przez autora dokumentu przeznaczonego na potrzeby prywatne. Te identyfikatory zaczynają się od x- lub X-.
W ramach przykładu pokażemy element zapisany w języku angielskim:
<p xml:lang="en">The color should be brown.</p>
Można też używać subkodów języków - za kodem dodaje się kreskę i dalej subkod, czyli wyróżnik lokalnej odmiany języka. Oto przykład, w którym rozróżniono element zapisany brytyjskim angielskim od elementu zapisanego angielskim amerykańskim:
<p xml:lang="en-GB">The colour should be brown.</p>
<p xml:lang="en-US">The color should be brown.</p>
Atrybut xml:lang określa nie tylko język zawartości elementu, ale też język wartości atrybutów - oto przykład z wartością zapisaną po niemiecku:
<p farbe="braun" xml:lang="de">
Tworzenie struktury poprawnie sformułowanego dokumentu
Wiele już wiemy o składni i zasadach tworzenia dokumentów XML na poziomie elementów i danych znakowych. Teraz trzeba przejść krok wyżej: zająć się strukturą dokumentu.
Konsorcjum W3C określiło szereg reguł mówiących, jak dokument należy tworzyć, aby był poprawnie sformułowany. Na razie będziemy omawiać jedynie dokumenty samodzielne (standalone="yes").
Kontrola poprawności sformułowania
Jeśli nie jesteś pewien, czy Twój dokument jest poprawnie sformułowany, użyj działającego w Sieci walidatora, na przykład dostępnego pod adresem www.stg.brown.edu/service/xmlvalid/. Otrzymasz pełny opis poprawności swojego dokumentu oraz wynik przeprowadzania walidacji. Reguły dotyczące poprawności sformułowania przedstawione przez W3C w specyfikacji XML znajdziesz wyszukując fragmenty oznaczone „Well-Formedness Constraint”.
Dokument XML powinien zacząć się od deklaracji XML
Pierwszą regułą poprawności dokumentu jest żądanie rozpoczęcia go deklaracją XML. Formalnie rzecz biorąc deklaracji nie musisz podawać, ale jeśli to zrobisz, to musi być ona na samym początku dokumentu - przed nią nie może pojawić się nawet żaden biały znak:
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<DOKUMENT>
<KLIENT STATUS="Rzetelny kredytobiorca">
<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>
.
.
.
Po co jest deklaracja XML?
W3C twierdzi, że dokumenty XML powinny mieć na początku deklarację XML, ale nie zawsze tak jest. Jeśli na przykład łączysz ze sobą dokumenty XML posiadające to samo kodowanie w jeden duży dokument, to nie chcesz, żeby każda część tego dokumentu zbiorczego zaczynała się deklaracją XML.
Umieść w dokumencie co najmniej jeden element
Aby dokument był poprawnie sformułowany, musi zawierać co najmniej jeden element. Pierwszy element w dokumencie to oczywiście element główny, w nim zamknięte są wszystkie inne elementy. Wszystkie pokazywane dotąd przykłady zawierały wiele elementów:
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<DOKUMENT>
<POZDROWIENIA>
Witaj w XML
</POZDROWIENIA>
<KOMUNIKAT>
Witaj w pokręconym świecie XML.
</KOMUNIKAT>
</DOKUMENT>
Podawaj znaczniki początkowy i końcowy elementów niepustych
W HTML przeglądarki często muszą sobie radzić z pominiętymi znacznikami końcowymi, nawet jeśli zgodnie ze specyfikacją znaczniki te powinny występować. Jeśli na przykład użyjesz znacznika <p>, a potem bez znacznika końcowego </p> użyjesz następnego znacznika <p>, przeglądarka nie będzie miała z interpretacją kodu żadnego problemu.
W XML jest całkiem inaczej. Aby zapewnić poprawne sformułowanie dokumentu, każdy niepusty element musisz zaczynać znacznikiem początkowym i kończyć końcowym:
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<DOKUMENT>
<POZDROWIENIA>
Witaj w XML
</POZDROWIENIA>
<KOMUNIKAT>
Witaj w pokręconym świecie XML.
</KOMUNIKAT>
</DOKUMENT>
Jest to właśnie kolejna reguła poprawności sformułowania: wszystkim znacznikom początkowym odpowiadać muszą znaczniki końcowe.
Znaczniki elementów pustych zamykaj />
Elementy puste nie mają znacznika końcowego. Elementy puste nie mają żadnej treści, czyli nie ma w nich żadnych danych znakowych ani znaczników. Elementy puste składają się z jednego tylko znacznika:
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<DOKUMENT>
<POZDROWIENIA TEKST="Witaj w XML"/>
</DOKUMENT>
W XML elementy puste należy zawsze kończyć />, jak to pokazano tutaj. Obecnie większość przeglądarek dobrze radzi sobie z elementami takimi, jak <BR /> - i całe szczęście, gdyż w przeciwnym wypadku konieczne byłoby zapisywanie <BR></BR>, co mogłoby być nieco mylące. Niektóre przeglądarki - w tym Netscape - taki zapis zinterpretują jako dwa znaczniki <BR>.
Element główny musi zawierać wszystkie inne elementy
W poprawnie sformułowanym dokumencie XML jeden element - element główny - zawierać musi wszystkie inne elementy. Oto przykład, w którym mamy element główny KSIĄŻKI:
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<KSIĄŻKI>
<KSIĄŻKA>
<TYTUŁ>
--> XML dla profesjonalistów[Author:T]
</TYTUŁ>
<OPINIA>
Doskonała
</OPINIA>
</KSIĄŻKA>
<KSIĄŻKA>
<TYTUŁ>
Inna książka o XML
</TYTUŁ>
<OPINIA>
Może być
</OPINIA>
</KSIĄŻKA>
</KSIĄŻKI>
W tym przykładzie element główny zawiera wszystkie inne elementy (choć na zewnątrz mogą pozostać deklaracja XML, komentarze i inne części dokumentu nie będące znacznikami elementów). Dzięki temu procesor XML może przetwarzać dokumenty jako drzewa, zaczynając właśnie od elementu głównego.
Prawidłowo zagnieżdżaj elementy
Bardzo ważną częścią zapewniania poprawności sformułowania dokumentu jest zapewnienie prawidłowego zagnieżdżania się elementów (zresztą stąd między innymi w ogóle wzięło się pojęcie poprawności sformułowania). Chodzi o to, że jeśli jakiś element zawiera znacznik początkowy innego elementu, to powinien także zawierać jego znaczniki końcowy.
Na przykład poniższy fragment jest prawidłowy:
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<DOKUMENT>
<POZDROWIENIA>
Witaj w XML
</POZDROWIENIA>
<KOMUNIKAT>
Witaj w pokręconym świecie XML.
</KOMUNIKAT>
</DOKUMENT>
Jednak w przykładzie poniższym już jest błąd, gdyż znacznik <KOMUNIKAT> pojawia się przed znacznikiem </POZDROWIENIA>:
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<DOKUMENT>
<POZDROWIENIA>
Witaj w XML
<KOMUNIKAT>
</POZDROWIENIA>
Witaj w pokręconym świecie XML.
</KOMUNIKAT>
</DOKUMENT>
Z uwagi na to, że elementy muszą być prawidłowo zagnieżdżane, a procesor XML nie może przetwarzać dokumentów nieprawidłowo sformułowanych, możesz bezpiecznie założyć, że każdy niegłówny element zawiera dokładnie jeden element rodzica go zawierający. W przedostatnim fragmencie kodu elementy POZDROWIENIA oraz KOMUNIKAT zawierały tego samego rodzica - element DOKUMENT, czyli element główny. Pamiętaj przy tym, że element może mieć dowolną liczbę elementów dzieci - od zera poczynając.
Nazwy atrybutów nie mogą się powtarzać
Jednym z wymagań specyfikacji XML jest to, że nazwa atrybutu nie może pojawić się więcej niż raz w jednym znaczniku początkowym lub znaczniku elementu pustego. Trudno sobie wyobrazić, jak mógłbyś tę regułę naruszyć inaczej niż przez pomyłkę, ale wyobraź sobie, że osoba ma dwa imiona:
<OSOBA IMIĘ="Arkadiusz" IMIĘ="January">
Z uwagi na to, że w XML wielkość liter ma znaczenie, atrybuty, których nazwy zapisano literami różnej wielkości uważane są za różne:
<OSOBA IMIĘ="Arkadiusz" imię="January">
Jednak używanie nazw atrybutów różniących się jedynie wielkością liter jest bardzo złym pomysłem.
Używać wolno tylko pięciu predefiniowanych encji
W XML istnieje pięć predefiniowanych odwołań do encji. Odwołanie takie jest umieszczane tam, gdzie wystąpić ma w przetwarzanym dokumencie sama encja. Być może znasz odwołania do encji z HTML - na przykład wiesz, że © zastąpione zostanie symbolem ©.
Odwołania do encji ogólnych XML zaczynają się od znaku & i kończą średnikiem, odwołania do encji parametrycznych używanych w DTD zaczynają się znakiem procentu i także kończą się średnikiem. W XML istnieje pięć predefiniowanych encji ogólnych podmienianych podczas parsowania dokumentu na odpowiednie znaki:
& znak &
< znak mniejszości, <
> znak większości, >
' apostrof, '
" cudzysłów podwójny prosty, "
Zwykle obsługa powyższych znaków w XML jest dość trudna, gdyż procesor XML przypisuje im specjalne znaczenie - i tak znaki < i > otaczają znaczniki, cudzysłowy pojedyncze i podwójne otaczają wartości atrybutów, natomiast znak & (ampersand) zaczyna odwołanie do encji. Podmiana odpowiednich znaków w dokumencie na odpowiadające im encje zabezpiecza je przed zinterpretowaniem przez procesor XML.
Załóżmy na przykład, że chcesz użyć w dokumencie nazwy firmy S&O Railway - można to zrobić stosując encję &:
<TRASA NAGŁÓWEK="S&O Railway"/>
W XML wprawdzie jest tylko pięć predefiniowanych encji, ale nic nie stoi na przeszkodzie, aby definiować nowe - robi się to w DTD.
Końcowy średnik w odwołaniu do encji
Przeglądarki HTML często pozwalają pominąć w odwołaniu do encji końcowy średnik, jeśli za tym odwołaniem znajduje się biały znak. W XML tego końcowego średnika pomijać nie wolno.
Ujmuj wartości atrybutów w cudzysłowy
W HTML, jeśli pominiesz cudzysłowy dookoła wartości atrybutu, nic się nie stanie (przynajmniej jeśli wartości te nie zawierają białych znaków). Na przykład poniższy znacznik w HTML zostanie zinterpretowany prawidłowo:
<IMG SRC=obrazek.jpg>
Jednak procesor XML odmówi zaakceptowania takiego elementu właśnie z powodu pominięcia cudzysłowów dookoła wartości atrybutu. Oto jak ten sam element powinien wyglądać w XML:
<IMG SRC="obrazek.jpg"/>
Można też użyć cudzysłowu pojedynczego:
<IMG SRC='obrazek.jpg'/>
Jeśli wartość atrybutu zawiera cudzysłów podwójny, to użycie cudzysłowu pojedynczego do ujęcia atrybutu jest nawet wskazane:
<cytat tekst='"Nie tak!" - powiedział'/>
Jak już wspomniano wcześniej, XML zapewnia środki obsługi cudzysłowów pojedynczych i podwójnych w wartościach atrybutów - cudzysłowy te zastąpić należy odwołaniami do odpowiednich encji: apostrofu ' oraz cudzysłowu ". Aby na przykład na anglosaski sposób zapisać wymiar jako 5'6", można napisać:
<wymiar miara="5'6""/>
W XHTML, który zapisano w XML na podstawie HTML 4.0, wymaga się obejmowania wszystkich wartości atrybutów cudzysłowami. Należy się spodziewać, że właśnie to będzie jednym z największych utrapień autorów witryn sieciowych, gdyż o tych cudzysłowach naprawdę łatwo jest zapomnieć.
Jest jeszcze kilka innych zastrzeżeń poprawności sformułowania dotyczących atrybutów. Wartości atrybutów nie mogą zawierać bezpośrednich ani pośrednich odwołań do encji zewnętrznych, nie można w nich używać znaku mniejszości. Jeśli znak ten jest Ci potrzebny, zastąpić go musisz odwołaniem <, jak to pokazano w poniższym przykładzie, w którym chcemy uzyskać atrybut o wartości <--:
<STRZAŁKA LEWA="<--"/>
Zakaz używania znaku mniejszości gdziekolwiek indziej poza początkiem znacznika rozciąga się znacznie dalej niż tylko na wartości atrybutów, znak ten nie powinien występować w dokumencie w żadnej innej roli. Więcej na ten temat w następnym punkcie.
Używaj znaków < i & tylko w znacznikach początkowych i w encjach
Procesor XML zakłada, że znak < zawsze zaczyna znacznik, a znak & zawsze zaczyna encję, więc należy używać stosowania tych znaków gdziekolwiek indziej. Już widziałeś użycie encji & w napisie S&O Railway:
<TRASA NAGŁÓWEK="S&O Railway"/>
Starannie trzeba też unikać znaku < w tekście nie należącym do znaczników. Czasem może być trudne w XHTML, gdyż znaku tego używa się jako operatora porównania w JavaScripcie:
<?xml version="1.0" encoding="iso-8859-2"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Użycie w JavaScripcie instrukcji if
</title>
</head>
<body>
<script language="javascript">
var budget
budget = 234.77
if (budget < 0) {
document.writeln("Ojej.")
}
</script>
<center>
<h1>
<Użycie instrukcji if w JavaScripcie
</h1>
</center>
</body>
</html>
W takich wypadkach W3C sugeruje zamknięcie kodu JavaScript w sekcji CDATA, dzięki czemu kod ten zostanie przez procesor XML zignorowany. Niestety, większość dostępnych obecnie przeglądarek sekcji CDATA nie potrafi zinterpretować. Inna możliwość to przekształcenie kodu na komentarz umieszczany między <!-- a -->, jednak W3C tego rozwiązania nie zaleca, gdyż procesorom XML wolno przed przekazaniem dokumentu aplikacji wszystkie komentarze całkowicie wyrzucić, co spowodowałoby kompletne wycięcie JavaScriptu z dokumentu.
Można w końcu podać operator < jako encję <:
<?xml version="1.0" encoding="iso-8859-2"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Użycie w JavaScripcie instrukcji if
</title>
</head>
<body>
<script language="javascript">
var budget
budget = 234.77
if (budget < 0) {
document.writeln("Ojej.")
}
</script>
<center>
<h1>
<Użycie instrukcji if w JavaScripcie
</h1>
</center>
</body>
</html>
Jednak większość przeglądarek będzie miała z takim zapisem problemy, choć takie właśnie rozwiązanie jest najlepsze, jeśli spojrzeć na rzecz bardziej przyszłościowo. Jakoś radzić sobie trzeba, można więc cały skrypt umieścić w odrębnym pliku, na przykład o nazwie skrypt.js:
<?xml version="1.0" encoding="iso-8859-2"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Użycie w JavaScripcie instrukcji if
</title>
</head>
<body>
<script language="javascript" src="skrypt.js">
</script>
<center>
<h1>
<Użycie instrukcji if w JavaScripcie
</h1>
</center>
</body>
</html>
Sekcje CDATA
Jak już zatem wiesz, procesor XML jest wyjątkowo wrażliwy na znaki < i &. Co zatem zrobić, kiedy trzeba wpisać duży blok danych z mnóstwem tych znaków, które nie mają być interpretowane? Można oczywiście wszystkie znaki zastąpić encjami < i &, ale w długim fragmencie jest to i uciążliwe, i trudne do późniejszego czytania. Właśnie tutaj z pomocą przychodzi użycie sekcji CDATA.
Sekcje CDATA zawierają znaki, które mają nie być przetwarzane przez procesor XML. Jest to wygodna metoda wstawiania do XML danych, w których jest dużo znaków takich, jak < i &. Użycie takiej sekcji informuje po prostu procesor, że zawarty w niej tekst ma bez zmian przekazać aplikacji, dla której dane XML są przeznaczone.
Sekcję CDATA zaczyna się pisząc <![CDATA, kończy ]]>. Wynika stąd, że w treści takiej sekcji nie mogą pojawić się znaki ]]>, zatem nie możesz też sekcji CDATA zagnieżdżać w sobie nawzajem.
Oto przykład - dodaliśmy do dokumentu ZNACZNIKI, który to element zawiera znaczniki, które mają być zachowane jako zwykłe dane tekstowe (załóżmy, że chcemy wydrukować jakiś przykład kodu XML). Aby zapewnić, że znaczniki te zostaną zachowane bez zmian, zamykamy cały fragment w sekcji CDATA:
<?xml version="1.0" encoding="iso-8859-2" standalone="yes"?>
<DOKUMENT>
<ZNACZNIKI>
<![CDATA
<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>
]]>
</ZNACZNIKI>
</DOKUMENT>
Jak widać, sekcje CDATA są bardzo silnym narzędziem, gdyż umożliwiają wstawianie do XML fragmentów kodu nie podlegającego w ogóle interpretacji. Normalnie dokumenty XML parsowane są przez procesor XML i stają się parsowanymi danymi znakowymi.
Oto przykład kolejny. Tym razem zmodyfikowano dokument z kodem JavaScript z poprzedniego punktu, aby pokazać, jak W3C zamierza obsługiwać kod programów w stronach XHTML - właśnie przez umieszczanie go w sekcjach CDATA:
<?xml version="1.0" encoding="iso-8859-2"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Użycie w JavaScripcie instrukcji if
</title>
</head>
<body>
<script language="javascript">
<![CDATA
var budget
budget = 234.77
if (budget < 0) {
document.writeln("Ojej.")
}
]]>
</script>
<center>
<h1>
<Użycie instrukcji if w JavaScripcie
</h1>
</center>
</body>
</html>
Niestety, jak już wspomniano wcześniej, sekcje CDATA pozostają dla większości przeglądarek całkowicie niezrozumiałe. Kiedy przeglądarki te będą w stanie obsługiwać XHTML, sytuacja ulegnie poprawie.
Przestrzenie nazw
W XML łatwo można definiować nowe znaczniki, jednak w miarę powstawania coraz liczniejszych aplikacji, pojawiać się będzie problem nieprzewidziany przez twórców pierwotnej wersji specyfikacji XML: konflikty nazw znaczników.
Jak to widzieliśmy w rozdziale 1, popularność zdobyły już dwie aplikacje XML: XHTML stworzony na podobieństwo HTML 4.0 oraz MathML umożliwiający wyświetlanie równań. XHTML jest przydatny, gdyż pozwala stosować wszystkie znaczniki HTML 4.0, natomiast MathML jest nieoceniony, jeśli chodzi o prezentację równań. A co, jeśli trzeba wstawić równania do strony sieciowej zapisanej w XHTML? Jest to problem, gdyż część znaczników obu tych języków tak samo się nazywa (powtarzają się między innymi elementy var oraz select).
Rozwiązaniem tego problemu są przestrzenie nazw. Umożliwiają one uniknięcie konfliktów między poszczególnymi zbiorami znaczników. Przestrzenie działają w ten sposób, że nazwę znacznika i atrybutu poprzedza się nazwą przestrzeni nazw z dwukropkiem; w ten sposób faktycznie zmienia się sam znacznik i konflikty się już nie pojawiają.
Przestrzenie nazw XML są jedną ze specyfikacji towarzyszących samej rekomendacji XML. Specyfikację przestrzeni nazw znajdziesz pod adresem www.w3.org/TR/REC-xml-names/. Nadal toczą się o przestrzeniach nazw ożywione debaty (głównie dlatego, że przestrzenie utrudniają tworzenie DTD), ale teraz już jest to oficjalna rekomendacja W3C.
Tworzenie przestrzeni nazw
Oto przykład, w którym używamy fikcyjnej aplikacji XML przeznaczonej do katalogowania książek, gdzie elementem głównym jest biblioteka. Do każdej książki dodamy recenzje. Zaczynamy od opisania w tej fikcyjnej aplikacji książki:
<biblioteka>
<książka>
<tytuł>
Trzęsienia ziemi na śniadanie
</tytuł>
</książka>
</biblioteka>
Teraz chcemy do elementu książka dodawać swoje komentarze. Zaczynamy od przypisania książkowej aplikacji XML jej własnej przestrzeni nazw, do której będziemy używać przedrostka książki:. Aby zdefiniować przestrzeń nazw, używa się atrybutu xmlns:przedrostek, gdzie przedrostek będzie używany do identyfikacji naszej przestrzeni:
<biblioteka
xmlns:książki="http://www.zadziwiająceksiążki.com/spec">
<książka>
<tytuł>
Trzęsienia ziemi na śniadanie
</tytuł>
</książka>
</biblioteka>
W celu zdefiniowania przestrzeni nazw przypisaliśmy atrybutowi xmlns:przedrostek niepowtarzalny identyfikator, który zwykle ma postać adresu URI (u nas był to po prostu adres URL). Pod tym adresem może (choć nie musi) znajdować się DTD definiowanej przestrzeni nazw. Teraz każdy znacznik i atrybut naszej nowej przestrzeni nazw poprzedzamy przedrostkiem książki:
<książki:biblioteka
xmlns:książki="http://www.zadziwiająceksiążki.com/spec">
<książki:książka>
<książki:tytuł>
Trzęsienia ziemi na śniadanie
</książki:tytuł>
</książki:książka>
</książki:biblioteka>
Teraz nazwy znaczników i atrybutów zostały zmienione - na przykład z punktu widzenia procesora XML dawny <biblioteka> ma teraz postać <książki:biblioteka> (jeśli znaczniki i atrybuty zdefiniowałeś w DTD dokumentu, musisz zmienić ich definicje, aby podać prawidłowe nazwy).
Teraz wszystkie znaczniki i atrybuty przestrzeni nazw książki należą do osobnej przestrzeni nazw, można do dokumentu dodać drugą przestrzeń, w której do książek dodawane będą komentarze. Zaczynamy od utworzenia nowej przestrzeni nazw opinie:
<książki:biblioteka
xmlns:książki="http://www.zadziwiająceksiążki.com/spec"
xmlns:opinie="http://www.gwiezdnypył.com/książki">
<książki:książka>
<książki:tytuł>
Trzęsienia ziemi na śniadanie
</książki:tytuł>
</książki:książka>
</książki:biblioteka>
Teraz w przestrzeni nazw opinie możemy dodać nowe elementy nie zaburzając innych znaczników:
<książki:biblioteka
xmlns:książki="http://www.zadziwiająceksiążki.com/spec"
xmlns:opinie="http://www.gwiezdnypył.com/książki">
<książki:książka>
<książki:tytuł>
Trzęsienia ziemi na śniadanie
</książki:tytuł>
<opinie:opinia>
Książka niezła, ale bez specjalnych wstrząsów.
</opinie:opinia>
</książki:książka>
</książki:biblioteka>
Można też używać w przestrzeni nazw opinie atrybutów, byle tylko były też poprzedzone przedrostkiem:
<książki:biblioteka
xmlns:książki="http://www.zadziwiająceksiążki.com/spec"
xmlns:opinie="http://www.gwiezdnypył.com/książki">
<książki:książka>
<książki:tytuł>
Trzęsienia ziemi na śniadanie
</książki:tytuł>
<opinie:opinia opinie:ID="1000034">
Książka niezła, ale bez specjalnych wstrząsów.
</opinie:opinia>
</książki:książka>
</książki:biblioteka>
I do tego właśnie służą przestrzenie nazw - rozdzielają znaczniki, nawet znaczniki o takich samych nazwach. Jak widać, swobodnie można w jednym dokumencie używać wielu przestrzeni nazw - po prostu należy w zawierającym całość elemencie umieścić odpowiednie atrybuty xmlns.
xmlns w elementach potomnych
Tak naprawdę za pomocą atrybutu xmlns można przedefiniować przestrzeń nazw w elemencie potomnym na inną niż używana w elemencie go zawierającym.
Tworzenie lokalnych przestrzeni nazw
Atrybutu xmlns nie trzeba używać w elemencie głównym, równie dobrze można go zastosować w dowolnym innym elemencie. W poniższym przykładzie definicję przestrzeni nazw opinie przeniesiono do elementu, w którym przestrzeń ta jest używana:
<książki:biblioteka
xmlns:książki="http://www.zadziwiająceksiążki.com/spec">
<książki:książka>
<książki:tytuł>
Trzęsienia ziemi na śniadanie
</książki:tytuł>
<opinie:opinia
xmlns:opinie="http://www.gwiezdnypył.com/książki"
opinie:ID="1000034" --> >[Author:T]
Książka niezła, ale bez specjalnych wstrząsów.
</opinie:opinia>
</książki:książka>
</książki:biblioteka>
Przedrostki przestrzeni nazw to po prostu tekst poprzedzający właściwe nazwy elementów i atrybutów, nazwy przestrzeni zaczynać się mogą od litery lub podkreślenia i dalej zawierać mogą podkreślenia, litery, cyfry, kreski i kropki. Dwukropki teoretycznie są dopuszczalne, ale oczywiste jest, że nie należy ich stosować. Oprócz tego zarezerwowane są dwie przestrzenie nazw: xml oraz xmlns. Zwróć uwagę, że skoro przestrzenie nazw to zwykły tekst, dwukropek jest w nazwach dopuszczalny, to całość jest dla procesora o przestrzeniach nazw nie mającego pojęcia zwykłą, poprawną nazwą elementu lub atrybutu.
Nazwy atrybutów w przestrzeniach nazw
Jedną przestrzeń nazw możesz określać za pomocą dwóch nazw. Jednak z uwagi na konieczność używania atrybutów o niepowtarzalnych nazwach, nie będziesz mógł użyć atrybutów o takich samych nazwach z tych dwóch przestrzeni w jednym elemencie.
Domyślne przestrzenie nazw
Teraz wrócimy do przykładu, od którego ten temat zaczęliśmy: włączania MathML i XHTML do jednego dokumentu. Załóżmy, że w dokumencie XHTML chcemy wyświetlić równanie. Zaczynamy od dokumentu XHTML w następującej postaci:
<?xml version="1.0" encoding="iso-8859-2"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Zagnieżdżanie MathML w XHTML
</title>
</head>
<body>
<center>
<h1>
Zagnieżdżanie MathML w XHTML
</h1>
</center>
Oto MathML:
</body>
</html>
W dokumencie tym znajduje się znacznik <!DOCTYPE>, który służy do powiązania dokumentu z DTD, natomiast w znaczniku <html> za pomocą atrybutu xmlns zadeklarowano przestrzeń nazw. Zwróć uwagę, że tym razem atrybutu xmlns użyto samodzielnie, bez wskazywania przedrostka. Kiedy właśnie używasz atrybutu xmlns bez podawania przedrostka, definiujesz domyślną przestrzeń nazw. Zakłada się, że wszystkie elementy znajdujące się wewnątrz elementu z atrybutem xmlns do tej przestrzeni domyślnej należą.
W dokumentach XHTML jako przestrzeń domyślną dokumentu zwykle podaje się przestrzeń XHTML W3C, http://www.w3.org/1999/xhtml. Jeśli tak jest, standardowych znaczników HTML można używać nie poprzedzając ich żadnym przedrostkiem, jak to robimy w przykładzie.
Jednak w tym dokumencie chcemy skorzystać też ze znaczników MathML, wobec czego konieczne jest dodanie nowej przestrzeni nazw - nazwiemy ją m - którą W3C przeznaczyło dla MathML: http://www.w3.org/TR/REC-MathML/:
<?xml version="1.0" encoding="iso-8859-2"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
xmlns:m="http://www.w3.org/TR/REC-MathML/">
<head>
<title>
Zagnieżdżanie MathML w XHTML
</title>
</head>
<body>
<center>
<h1>
Zagnieżdżanie MathML w XHTML
</h1>
</center>
Oto MathML:
</body>
</html>
Teraz możemy dodawać potrzebny kod MathML, trzeba go tylko umieszczać w przestrzeni nazw m:
<?xml version="1.0" encoding="iso-8859-2"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
xmlns:m="http://www.w3.org/TR/REC-MathML/">
<head>
<title>
Zagnieżdżanie MathML w XHTML
</title>
</head>
<body>
<center>
<h1>
Zagnieżdżanie MathML w XHTML
</h1>
</center>
Oto MathML:
<m:math>
<m:mrow>
<m:mn>3</m:mn>
<m:mo>⁢</m:mo>
<m:msup>
<m:mi>Z</m:mi>
<m:mn>2</m:mn>
</m:msup>
<m:mo>-</m:mmo>
<m:mrow>
<m:mn>6</m:mn>
<m:mo>⁢</m:mo>
<m:mi>Z</m:mi>
</m:mrow>
<m:mo>+</m:mo>
<m:mn>12</m:mn>
</m:mrow>
<m:mo>=</m:mo>
<m:mn>0</m:mn>
</m:mrow>
</m:math>
</body>
</html>
Dokument działa poprawnie, co widać na rysunku 2.3, na którym przedstawiono ten dokument w przeglądarce Amaya.
Rysunek 2.3. MathML w przeglądarce Amaya |
|
Przestrzeni nazw używa się w różnych sytuacjach, choćby podczas tworzenia arkuszy stylów XSL.
Zbiory informacji
Przy okazji omawiania budowy dokumentów XML warto wspomnieć o nowej specyfikacji zbiorów danych XML, którą znajdziesz pod adresem www.w3.org/TR/xml-infoset.
Dokumenty XML świetnie nadają się do przechowywania danych i to pchnęło jego twórców do zastanowienia się, czy XML nie jest przypadkiem w stanie poradzić sobie z odwiecznym problemem informatyki: bezpośredniego porównywania i klasyfikowania danych z wielu dokumentów. Zastanówmy się na przykład nad obecną strukturą Sieci: są tam tysiące dokumentów na poszczególne tematy, ale jak je ze sobą porównać? Na przykład wyszukiwanie słowa XML da w wyniku około 675 000 odpowiedzi, ale napisanie programu porównującego uzyskane wyniki byłoby wyjątkowo trudne, gdyż dane są przechowywane w różnych formatach.
Pomysł zbiorów informacji XML polega na opracowaniu uogólnionego spojrzenia na dokumenty XML, które dzięki temu można ze sobą porównywać. Aby uzyskać zbiór informacji, w znacznikach dokumentów nie wolno używać dwukropków inaczej niż do oznaczania przestrzeni nazw. Dokumentów nie trzeba walidować, ale muszą one być poprawnie sformułowane.
Zbiór informacji dokumentu XML składa się z dwóch lub więcej pozycji (zbiór informacji dowolnego poprawnego dokumentu XML zawiera przynajmniej informacje o dokumencie i o elementach). Informacje dokumentu to skrót niektórych części dokumentu, każda część zbioru danych zawiera zestaw właściwości, z których niektóre uważane są za krytyczne, inne zaś za dodatkowe.
Zbiór informacji XML zawiera 15 różnych części (fragmentów) informacyjnych wyszczególnionych w specyfikacji W3C Infoset:
Informacje o dokumencie (krytyczne)
Informacje o elementach (krytyczne)
Informacje o atrybutach (krytyczne)
Informacje o instrukcjach przetwarzania (krytyczne)
Informacje o odwołaniach do pominiętych encji (krytyczne)
Informacje o znakach (krytyczne)
Informacje o komentarzach (dodatkowe)
Informacje o deklaracji typu dokumentu (dodatkowe)
Informacje o encjach (krytyczne dla encji nieparsowanych, dodatkowe dla pozostałych)
Informacje o notacjach (krytyczne)
Informacje o znaczniku początkowym encji (dodatkowe)
Informacje o znaczniku końcowym encji (dodatkowe)
Informacje o znaczniku początkowym CDATA (dodatkowe)
Informacje o znaczniku końcowym CDATA (dodatkowe)
Informacje o deklaracji przestrzeni nazw (krytyczne)
W zbiorze informacji zawsze jest jeden fragment informacji. Oto lista właściwości krytycznych informacji o dokumencie:
[children]: ta właściwość zawiera uporządkowaną listę odwołań do informacji o dzieciach w kolejności zgodnej z kolejnością w dokumencie pierwotnym.
[notations]: zawiera nieuporządkowaną listę odwołań do informacji o notacjach.
[entities]: zawiera nieuporządkowany zestaw odwołań do informacji o encjach, po jednym dla każdej deklaracji nieparsowanej encji w DTD.
Informacje o dokumencie mogą zawierać także właściwości dodatkowe:
[base URI]: Zawiera bezwzględny adres URI encji dokumentu.
[children-comments]: zawiera odwołania do informacji o komentarzach znajdujących się poza elementem głównym.
[children-doctype]: zawiera odwołanie do informacji o deklaracji typu dokumentu.
[entities-other]: Zawiera odwołania do informacji o każdej parsowanej encji ogólnej z DTD.
Pozostałe fragmenty informacji zawierają podobne listy właściwości.
Obecnie żadna aplikacja nie potrafi tworzyć ani korzystać ze zbiorów informacji. Jednak w dokumentacji W3C często do informacji zawartych w dokumentach XML odwołuje się jako do odpowiednich zbiorów informacji, więc pojęcie to trzeba znać. Obecnie ze zbiorami informacji najczęściej stykać się będziesz odwołując się do kanonicznego XML.
Kanoniczny XML
Zbiory informacji to doskonały pomysł, ale są one jednak tylko wyciągiem informacji z dokumentu XML. Jak zatem można porównywać dokumenty XML nie uciekając się do redukcji ich do postaci zbioru informacji?
Okazuje się, że jest na to sposób: użyć należy kanonicznego XML. Jest to standard towarzyszący samemu XML, komplet informacji na ten temat znajdziesz pod adresem www.w3.org/TR/xml-c14n. Kanoniczne XML ściśle zgodne jest ze składnią XML, dokumenty zapisane w kanonicznej postaci można ze sobą bezpośrednio porównywać. W dokumencie w kanonicznej postaci XML zapisywane są takie same informacje, jakie znalazłyby się w zbiorze danych.
Jak już wiesz, dokumenty XML zawierające takie same informacje mogą być różnie zapisane. Różna może być ich struktura, kolejność atrybutów, a nawet system kodowania znaków. Oznacza to, że takie dokumenty bardzo trudno jest ze sobą porównać. Jeśli jednak dokumenty te przekształcone zostaną na postać kanoniczną ,można je porównywać bajt po bajcie. Zapisane zgodnie ze składnią kanonicznego XML dokumenty logicznie sobie odpowiadające są identyczne co do bajta.
Kanoniczna składnia XML jest bardzo wymagająca formalnie, na przykład dopuszczalne jest jedynie kodowanie UTF-8, pary znaków powrót karetki + nowy wiersz zastąpione muszą być przez sam znak nowego wiersza, tabulatory w sekcjach CDATA zastępowane są spacjami, rozwinięte muszą być wszystkie odwołania do encji i tak dalej. Z uwagi na to, że dokumenty XML w postaci kanonicznej muszą być zgodne ze specyfikacją co do bajta, do konwersji dokumentów na taką postać używać należy oprogramowania, a nie należy robić tego ręcznie.
Jeden z pakietów pozwalających przekształcać zwykły XML na postać kanoniczną jest dostarczany wraz z XML for Java, dostępnym ze strony AlphaWorks IBM'a (www.alphaworks.ibm.com/tech/xml4j). Z oprogramowaniem tym zetknęliśmy się już w rozdziale 1 i będziemy go jeszcze używać później, kiedy będziemy omawiać XML DOM. Wraz z XML for Java dostarczany jest program Javy DOMWriter konwertujący dokumenty na kanoniczną postać XML. Aby tego programu użyć, konieczna jest walidacja dokumentu, co oznacza, że trzeba też podać DTD, względem którego dokument ma być sprawdzany. Zamiast DTD można użyć też schematu XML. W naszym przykładzie posłużymy się plikiem order.xml uzupełnionym Definicją typu dokumentu:
<?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 (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>
<KLIENT>
<IMIĘNAZWISKO>
<NAZWISKO>Jones</NAZWISKO>
<IMIĘ>Polly</IMIĘ>
</IMIĘNAZWISKO>
<DATA>20 października 2001</DATA>
<ZAMÓWIENIA>
<POZYCJA>
<PRODUKT>Chleb</PRODUKT>
<ILOŚĆ>12</ILOŚĆ>
<CENA>28.80zł</CENA>
</POZYCJA>
<POZYCJA>
<PRODUKT>Jabłka</PRODUKT>
<ILOŚĆ>6</ILOŚĆ>
<CENA>6.00zł</CENA>
</POZYCJA>
</ZAMÓWIENIA>
</KLIENT>
<KLIENT>
<IMIĘNAZWISKO>
<NAZWISKO>Weber</NAZWISKO>
<IMIĘ>Bill</IMIĘ>
</IMIĘNAZWISKO>
<DATA>25 października 2001</DATA>
<ZAMÓWIENIA>
<POZYCJA>
<PRODUKT>Asparagus</PRODUKT>
<ILOŚĆ>12</ILOŚĆ>
<CENA>11.90zł</CENA>
</POZYCJA>
<POZYCJA>
<PRODUKT>Sałata</PRODUKT>
<ILOŚĆ>6</ILOŚĆ>
<CENA>31.50zł</CENA>
</POZYCJA>
</ZAMÓWIENIA>
</KLIENT>
</DOKUMENT>
Teraz można uruchomić program DOMWriter ze specjalnym przełącznikiem -c, co pozwoli skonwertować dokument na postać kanoniczną. > canonical.xml na końcu polecenia oznacza przekazanie wyników działania programu do pliku canonical.xml (ustawianie zmiennej środowiska Javy classpath zostanie opisane w rozdziale 8).
%java dom.DOMWriter -c order.xml > canonical.xml
java -cp xml4j.jar;xerces.jar;xercesSamples.jar dom.DOMWriter -c order.xml > canonical.xml
Oto uzyskane wyniki. Zwróć uwagę na to, że DOMWriter zachował wszystkie białe znaki, encja to kod nowego wiersza w UTF-8. Tego typu kody mogą być też wstawiane jako liczby szesnastkowe oznaczane literą „x” przed liczbą: 
.
<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>
<KLIENT> <IMIĘNAZWISKO>
<NAZWISKO>Jones</NAZWISKO>
<IMIĘ>Polly</IMIĘ> </IMIĘNAZWISKO>
<DATA>20 października 2001</DATA> <ZAMÓWIENIA>
<POZYCJA> <PRODUKT>Chleb</PRODUKT>
<ILOŚĆ>12</ILOŚĆ> <CENA>28.80zł</CENA>
</POZYCJA> <POZYCJA>
<PRODUKT>Jabłka</PRODUKT> <ILOŚĆ>6</ILOŚĆ>
<CENA>6.00zł</CENA> </POZYCJA>
</ZAMÓWIENIA> </KLIENT> <KLIENT>
<IMIĘNAZWISKO> <NAZWISKO>Weber</NAZWISKO>
<IMIĘ>Bill</IMIĘ> </IMIĘNAZWISKO>
<DATA>25 października 2001</DATA>
<ZAMÓWIENIA> <POZYCJA>
<PRODUKT>Asparagus</PRODUKT>
<ILOŚĆ>12</ILOŚĆ> <CENA>11.90zł</CENA>
</POZYCJA> <POZYCJA>
<PRODUKT>Sałata</PRODUKT> <ILOŚĆ>6</ILOŚĆ>
<CENA>31.50zł</CENA> </POZYCJA>
</ZAMÓWIENIA> </KLIENT> </DOKUMENT>
Dokumenty zapisane w postaci kanonicznej można porównywać bezpośrednio, wszystkie różnice między nimi od razu się uwidocznią --> .[Author:T]
<?xml version="1.0" encoding="iso-8859-2"?> - tak powinien wyglądać nagłówek dla dokumentów zawierających polskie znaki diakrytyczne (przyp. tłum.)
tabulatory i odstępy poziome jak i pionowe - przyp. red.
Najlepiej od razu zdecydować się na jakąś konwencję - stosować w znacznikach tylko małe lub tylko wielkie litery. Pozwoli to uniknąć wielu błędów - zresztą wystarczy przyjrzeć się istniejącym aplikacjom XML, takim jak XHTML czy MathML. (przyp.tłum.)
Jednak równie poprawny zapis elementu pustego składa się z następujących bezpośrednio po sobie znacznika początkowego i końcowego, na przykład <P></P>. Między tymi znacznikami nie mogą wystąpić żadne znaki, nawet spacja czy znak końca wiersza. (przyp. tłum.)
Z tego właśnie powodu zdecydowanie odradza się stosować dwukropki w nazwach elementów, gdyż przez ich umieszczanie można spowodować, że nazwy znaczników nawet wzbogaconych przestrzenią nazw będą się powtarzały. (przyp. tłum.)
4 Część I ♦ Podstawy obsługi systemu WhizBang (Nagłówek strony)
Rozdział 1 ♦ Pierwsze kroki (Nagłówek strony)
4 C:\Moje dokumenty\Wojtek Romowicz\Książki\XML Vademecum profesjonalisty\r02-01.doc
C:\Moje dokumenty\Wojtek Romowicz\Książki\XML Vademecum profesjonalisty\r02-01.doc 1