02-08, Programowanie, ! Java, Java i XML


2

Tworzenie dokumentów XML

Teraz, gdy już wiemy, czym jest XML, do jakich celów może służyć oraz przez jakie interfejsy pro­gramowe Javy jest obsługiwany, pora przenieść tę wiedzę na grunt praktyczny. Ni­niejsza książ­ka nie jest w żadnym razie pełnym podręcznikiem składni języka — nie może nawet służyć jako lek­sykon — nie można jednak omawiać przetwarzania dokumentów XML nie po­siadając umie­jętności tworzenia. Ponadto stosowanie interfejsów Javy do obsługi XML-a wymaga dość dob­rej znajomości składni i struktury tego języka, a także sposobów tworzenia dokumentów, ich zawę­żania i przekształcania. Zanim więc zajmiemy się interfejsami Javy służącymi do obsługi ję­zy­ka XML, zapoznamy się z tymi czynnościami.

W niniejszym rozdziale przyjrzymy się składni dokumentów XML. Rozpoczniemy od najbardziej podstawowych konstrukcji i powiemy, co to jest „poprawnie skonstruowany” dokument XML. Opiszemy różne zasady tworzenia dokumentów XML oraz pułapki składni. Po lekturze rozdziału Czy­telnik będzie potrafił stworzyć dokument nie tylko poprawny, ale także nadający się do prak­ty­cznego zastosowania. Wszystko to będzie stanowiło wstęp do napisania pierwszego programu w Ja­vie (w następnym rozdziale) i zrozumienia, na czym polega przetwarzanie kodu XML oraz jak Java odwołuje się do tego --> procesu[Author:PG] .

Ci, którzy mieli już kiedyś do czynienia z książkami opisującymi składnię języka programowania, zdają sobie sprawę, że takie opisy bywają dość nudne. My spróbujemy podejść do sprawy nieco inaczej. Zamiast rozpoczynać od jedno- czy dwuwierszowego pliku XML i dodawać do niego kolejne elementy (co kończy się stworzeniem długiego, ale bezużytecznego przykładu), roz­pocz­nie­my od pełnego, dość złożonego dokumentu XML. Plik, którego użyjemy jako przy­kła­du, to frag­ment rzeczywistego dokumentu XML reprezentującego spis treści tej książki. Przyj­rzymy mu się wiersz po wierszu i opiszemy poszczególne konstrukcje. Przy omawianiu składni w oparciu o pros­te przykłady rzadko pamięta się o tym, że rozwiązania proste stosowane są w rze­czywistych apli­kacjach bardzo rzadko. Zamiast tego najczęściej trafiają się złożone pliki, nie­zro­zu­miałe dla osób „wychowanych” na prostych przykładach. Trzeba zatem przyzwyczaić się do plików XML za­wierających wszelkie możliwe konstrukcje — i zaczniemy właśnie od takich pra­ktycznych przy­kła­dów. Można mieć nadzieję, że dzięki temu nasze wprowadzenie będzie bliż­sze rzeczywistości.

Zanim zaczniemy, jeszcze jedna uwaga. Rozdział ten nie pretenduje do miana materiału re­fe­ren­cyjnego. Innymi słowy, nie przedstawiamy poszczególnych pojęć wraz z ich definicjami, nie jest to też skrótowe wprowadzenie do standardu XML. Będziemy posuwać się kolejnymi krokami na­przód — definicje podawane będą w kontekście przykładów oraz przedstawionych konstrukcji. Warto natomiast podczas lektury mieć pod ręką dobry leksykon XML-a, co pozwoli uniknąć po­wtarzania przedstawionych tu wiadomości w dalszej części książki, omawiającej sprawy bardziej skomplikowane. Dobrym przykładem takiej pozycji jest książka Roberta Ecksteina XML. Leksy­kon kieszonkowy (Helion, Gliwice 2000).

Dokument XML

Zgodnie z obietnicą zaczniemy od praktycznego dokumentu XML, stanowiącego fragment spisu treś­ci tej książki. Spójrzmy na przykład 2.1.

Przykład 2.1. Plik XML

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

<?xml-stylesheet href="XSL\JavaXML.html.xsl" type="text/xsl"?>

<?xml-stylesheet href="XSL\JavaXML.wml.xsl" type="text/xsl"

media="wap"?>

<?cocoon-process type="xslt"?>

<!DOCTYPE JavaXML:Ksiazka SYSTEM "DTD\JavaXML.dtd">

<!-- Java i XML -->

<JavaXML:Ksiazka xmlns:JavaXML="http://www.oreilly.com/catalog/javaxml/">

<JavaXML:Tytul>Java i XML</JavaXML:Tytul>

<JavaXML:Spis>

<JavaXML:Rozdzial tematyka="XML">

<JavaXML:Naglowek>Wprowadzenie</JavaXML:Naglowek>

<JavaXML:Temat podrozdzialy="7">Co to jest?</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="3">Jak z tego korzystać?</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="4">Dlaczego z tego korzystać?</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="0">Co dalej?</JavaXML:Temat>

</JavaXML:Rozdzial>

<JavaXML:Rozdzial tematyka="XML">

<JavaXML:Naglowek>Tworzenie dokumentów XML</JavaXML:Naglowek>

<JavaXML:Temat podrozdzialy="0">Dokument XML</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="2">Nagłówek</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="6">Zawartość</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="1">Co dalej?</JavaXML:Temat>

</JavaXML:Rozdzial>

<JavaXML:Rozdzial tematyka="Java">

<JavaXML:Naglowek>Przetwarzanie kodu XML</JavaXML:Naglowek>

<JavaXML:Temat podrozdzialy="3">Przygotowujemy się</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="3">Czytniki SAX</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="9">Procedury obsługi zawartości</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="4">Procedury obsługi błędów</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="0">

Lepszy sposób ładowania parsera

</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="4">"Pułapka!"</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="0">Co dalej?</JavaXML:Temat>

</JavaXML:Rozdzial>

<JavaXML:PodzialSekcji/>

<JavaXML:Rozdzial tematyka="Java">

<JavaXML:Naglowek>Struktury publikacji WWW</JavaXML:Naglowek>

<JavaXML:Temat podrozdzialy="4">Wybór struktury</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="4">Instalacja</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="3">

Korzystanie ze struktury publikacji

</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="2">XSP</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="3">Cocoon 2.0 i dalej</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="0">Co dalej?</JavaXML:Temat>

</JavaXML:Rozdzial>

</JavaXML:Spis>

<JavaXML:Copyright>&HelionCopyright;</JavaXML:Copyright>

</JavaXML:Ksiazka7>

Nagłówek

Pierwszy element dokumentu dotyczy samego języka XML. Dokument stworzony w tym języku można podzielić na dwie podstawowe części: nagłówek, który przekazuje parserowi --> [Author:ts] i aplikacjom XML informacje o tym, jak dany dokument ma być obsługiwany, oraz zawartość, czyli same dane XML. Pozwoli nam to odróżnić treść dokumentu XML od instrukcji przekazywanych aplikacjom z jego wnętrza. Zaczniemy od pierwszych kilku linijek przykładu, do miejsca JavaXML: Ksiazka (bez niego). Te początkowe wiersze to właśnie nagłówek dokumentu. Termin „na­głó­wek” nie jest formalnym pojęciem zdefiniowanym w specyfikacji XML, ale jest szeroko stoso­wany. W tej książce również będziemy z niego korzystać.

Instrukcje XML

Pierwszym elementem każdego dokumentu XML jest instrukcja XML. Instrukcje języka XML stanowią określony podzbiór instrukcji przetwarzania (PI), o których mówiliśmy w poprzednim rozdziale. Powiedziano tam, że instrukcje PI są zazwyczaj przekazywane przez parser do aplikacji wywołującej i dopiero tam obsługiwane. Ale instrukcje przetwarzające, w których jako element docelowy podano xml, są przeznaczone dla samego parsera. Określają one rodzaj używanej wersji XML-a, arkusz stylów lub inne informacje potrzebne parserowi do poprawnego przetworzenia danych XML. Oto instrukcja XML:

<?xml version="1.0" standalone="no" encoding="ISO-8859-2"?>

Podobnie jak wszystkie inne instrukcje PI, ma ona postać <?cel instrukcja?> i w tym przypadku określa, że używana wersja standardu XML to 1.0, a dokument nie jest samodzielnym dokumentem XML. Zauważmy, że instrukcja to niekoniecznie jedna para klucz=war­tość; w tym przypadku określamy zarówno wersję dokumentu, jak i to, czy wymaga on jeszcze obecności jakiegoś innego dokumentu lub dokumentów. Kiedy parser „dowiaduje się”, że dany dokument nie jest samodzielny (ang. standalone), wie, że do określenia jego poprawności będzie konieczne wykorzystanie zewnętrznej definicji DTD. Gdyby atrybut standalone miał wartość yes, parser nie musiałby odwoływać się do zewnętrznej definicji DTD. W początkowej instrukcji może też znaleźć się deklaracja sposobu kodowania dokumentu. Tutaj, jak również w przed­sta­wio­nym powyżej przykładowym dokumencie XML, tłumacz dodał informację o kodowaniu (enco­ding="ISO-8859-2") — bez niej w czasie późniejszego przetwarzania dokumentu parser zgła­­szałby błędy po napotkaniu znaków spoza standardowego zestawu ASCII (czyli np. polskich liter ą, ć, ś itp.).

Kolejną grupę stanowią instrukcje XML odwołujące się do arkuszy stylów. W naszym przykładzie mamy dwie takie instrukcje:

<?xml-stylesheet href="XSL\JavaXML.html.xsl" type="text/xsl"?>

<?xml-stylesheet href="XSL\JavaXML.wml.xsl" type="text/xsl" media="wap"?>

Zazwyczaj instrukcja PI rozpoczynająca się od xml-[nazwa] odwołuje się do technologii zwią­za­nej z XML-em i określonej w części [nazwa]. W tym przypadku chodzi o arkusz stylów, toteż instrukcja przekazywana jest do mechanizmu XSLT, a nie do parsera XML-a. W pierwszym wierszu odwołujemy się do domyślnego arkusza stylów, podając jego położenie i typ. W wierszu drugim widzimy odwołanie do alternatywnego arkusza stylów. W tym przypadku podano także atry­but media, który informuje procesor, dla jakiego rodzaju klientów jest przeznaczony dany ar­kusz. Mechanizmy publikacji omówimy w rozdziale 9., Systemy publikacji WWW.

Deklaracje typu dokumentu

Po początkowych instrukcjach XML następuje deklaracja DOCTYPE. Deklaracja ta dysponuje własną, odrębną składnią, ponieważ jest wykorzystywana tylko do jednego celu — określenia de­finicji DTD wykorzystywanej w danym dokumencie XML. Spójrzmy jeszcze raz na deklarację DOCTYPE w naszym przykładzie:

<!DOCTYPE JavaXML:Ksiazka SYSTEM "DTD\JavaXML.dtd">

W tym przykładzie definicją DTD dla dokumentu jest plik JavaXML.dtd, znajdujący się w lo­kal­nym systemie plików. Parsery XML zazwyczaj dopuszczają stosowanie zwykłego lub lewego ukoś­nika (odpowiednio, dla systemów Unix i Windows), co pozwala uzyskać przenośność ścieżek dostępu pomiędzy różnymi platformami. Pierwszym parametrem deklaracji DOCTYPE jest ele­ment główny dokumentu, o którym powiemy za chwilę — tymczasem wystarczy informacja, że określa on bieżący dokument XML. Następnym argumentem jest albo słowo SYSTEM, albo PU­BLIC. Ponieważ wpisaliśmy SYSTEM, parser XML będzie oczekiwał, że w następnym argu­men­cie znajdzie się położenie pliku DTD, określone za pomocą jednolitego identyfikatora zasobów (URI). Słowo SYSTEM nie oznacza jednak, że plik DTD musi się koniecznie znajdować w sys­te­mie lokalnym. Można też użyć następującego zapisu:

<!DOCTYPE JavaXML:Ksiazka SYSTEM "http://www.oreilly.com/catalog/javaxml/DTD/JavaXML.dtd">

Specyfikacja XML pozwala umieścić w tym miejscu dowolny poprawny identyfikator URI, a więc adres URL jest do przyjęcia. Użycie słowa PUBLIC oznacza, że definicja DTD, do której się od­wo­łujemy, jest upubliczniona i mogą z niej korzystać wszyscy. W tym przypadku przed podaniem URI konieczne jest określenie nazwy publicznej. Poniższą deklarację można zna­leźć na początku niektórych plików HTML, takich jak strona główna konsorcjum W3C, dostępna pod adresem http://www.w3c.org/:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

Po słowie kluczowym PUBLIC następuje nazwa określająca publiczną definicję DTD wyko­rzy­s­ty­waną w danym dokumencie. Parser XML najpierw stara się zlokalizować definicję DTD za pomocą jej nazwy, a dopiero kiedy to się nie uda — za pomocą dodatkowo podanego identy­fi­ka­to­ra URI. Składnia nazwy publicznej definicji DTD jest szczegółowo opisana w specyfikacji XML, ale to na razie nie będzie nas interesować. Definicjom DTD i ich formatowi przyjrzymy się w rozdziale 4., Zawężanie --> XML[Author:ts] .

Zawartość dokumentu

Skoro nagłówek mamy już za sobą, możemy przejść do zawartości dokumentu XML. Składają się na nią elementy, atrybuty i opisywane przez nie dane tekstowe.

Element główny

Element główny (ang. root element) to najwyższy w hierarchii element dokumentu XML. Je­go de­fi­nicję stanowią zawsze pierwszy znacznik otwierający i ostatni znacznik zamykający w do­ku­men­cie. Element ten stanowi punkt wyjścia dla parsera lub aplikacji XML, umożliwiając im roz­po­znanie początku i końca dokumentu. W naszym przykładzie elementem głównym jest <Ja­vaXML:Ksiazka>:

<JavaXML:Ksiazka xmlns:JavaXML="http://www.oreilly.com/catalog/javaxml/">

<!-- tutaj zawartość dokumentu XML -->

</JavaXML:Ksiazka>

Znacznik ten, w połączeniu z odpowiadającym mu znacznikiem zamykającym, otacza całą po­zo­sta­łą zawartość dokumentu XML. Specyfikacja XML zezwala na obecność tylko jednego ele­mentu głównego w dokumencie. Innymi słowy, element taki musi „obejmować” wszystkie inne elementy. Poza tym jednym wymogiem element główny nie różni się od innych elementów XML. Warto o tym pamiętać, ponieważ dokumenty XML mogą zawierać inne dokumenty XML lub odwoływać się do nich. W takich przypadkach element główny dokumentu, do którego się od­wo­łu­jemy, staje się elementem wewnętrznym dokumentu, z którego nastąpiło odwołanie i musi zostać normalnie obsłużony przez parser XML. Dzięki temu, że elementy główne zdefiniowano jako stan­dardowe elementy XML (nie posiadające specjalnych właściwości czy zachowań), dołączanie in­nych dokumentów XML przebiega bezproblemowo.

Identyfikacja elementów za pomocą przestrzeni nazw

Nie będziemy tutaj zbytnio zagłębiać się w temat przestrzeni nazw, ale wypada zdawać sobie spra­wę ze sposobu ich użycia w elemencie głównym. Jak można było zauważyć, wszystkie nazwy elementów XML mają przedrostek JavaXML. Być może później zajdzie potrzeba dołączenia do przykładowego dokumentu fragmentów innych książek wydawnictwa O'Reilly. Ponieważ każda z nich może także posiadać znaczniki <Rozdzial>, <Naglowek> lub <Temat>, dokument musi zostać skonstruowany tak, aby wyeliminować możliwość kolizji przestrzeni nazw z innymi dokumentami. Specyfikacja przestrzeni nazw w języku XML rozwiązuje ten problem w bardzo prosty sposób. Ponieważ nasz dokument odpowiada konkretnej książce, której nie będzie od­po­wiadał żaden inny dokument XML, można użyć przedrostka w rodzaju JavaXML, powodującego przypisanie elementu do danej przestrzeni nazw. Specyfikacja przestrzeni nazw wymaga przy­pi­sa­nia danemu przedrostkowi niepowtarzalnego identyfikatora URI, tak aby możliwe było odróż­nie­nie elementów w danej przestrzeni nazw od elementów w innych przestrzeniach. Zaleca się użycie do tego celu adresu URL i tak właśnie robimy w naszym przykładzie (http://www.oreilly.com/ catalog/javaxml — strona WWW tej książki):

<JavaXML:Ksiazka xmlns:JavaXML="http://www.oreilly.com/catalog/javaxml/">

Do zdefiniowanej w ten sposób przestrzeni nazw można odwoływać się z dowolnego elementu w danym dokumencie XML. W naszym przypadku przestrzeń wykorzystujemy we wszystkich ele­mentach, wszystkie bowiem do niej należą. Poprawnym sposobem związania elementu z prze­strze­nią nazw jest podanie jej identyfikatora jako przedrostka oddzielonego dwukropkiem od właściwej nazwy elementu:

<JavaXML:Rozdzial tematyka=" --> XML[Author:ts] ">

<JavaXML:Naglowek>Wprowadzenie</JavaXML:Naglowek>

<JavaXML:Temat podrozdzialy="7">Co to jest?</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="3">Jak z tego korzystać?</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="4">Dlaczego z tego korzystać?</JavaXML:Temat>

<JavaXML:Temat podrozdzialy="0">Co dalej?</JavaXML:Temat>

</JavaXML:Rozdzial>

Każdy z tych elementów jest traktowany przez parser XML jako część przestrzeni nazw http:// www.oreilly.com/catalog/javaxml/, dzięki czemu nie wystąpią kolizje z innymi elementami o na­zwach Rozdzial, Naglowek czy Temat, zawartymi w innych przestrzeniach nazw. W tym samym dokumencie można umieszczać wiele deklaracji przestrzeni nazw — wszystkie za pomocą jednego elementu:

<JavaXML:Ksiazka xmlns:JavaXML="http://www.oreilly.com/catalog/javaxml/"

xmlns:Cocoon="http://xml.apache.org/cocoon/">

Powyższa deklaracja jest poprawna, jednak przy wykorzystywaniu wielu przestrzeni nazw w jed­nym dokumencie trzeba zachować dużą ostrożność. Często korzyści z takiego rozwiązania mogą zostać zniwelowane przez komplikację i konieczność umieszczania dodatkowego tekstu w do­ku­mencie. Zazwyczaj pojedyncza przestrzeń nazw umożliwia stworzenie jednego, „czystego” doku­mentu XML z jednoczesnym uniknięciem kolizji; jedynym istotnym wyjątkiem jest przypadek, gdy wykorzystywana jest inna specyfikacja XML (np. XML Schema) i gdy trzeba dla niej użyć osobnej przestrzeni nazw.

Na koniec jeszcze jedno interesujące (i może nieco skomplikowane) zagadnienie. Specyfikacja XML Schema, dokładniej omówiona w rozdziale 4., wymaga określenia schematu dokumentu XML w sposób bardzo przypominający zestaw deklaracji przestrzeni nazw (przykład 2.2).

Przykład 2.2. Dokument XML wykorzystujący specyfikację XML Schema

<?xml version="1.0"?>

<ksiazkaAdresowa xmlns:xsi="http://www.w3.org/1999/XMLSchema/instance"

xmlns="http://www.oreilly.com/catalog/javaxml/"

xsi:schemaLocation="http://www.oreilly.com/catalog/javaxml/

mySchema.xsd"

>

<osoba>

<nazwa>

<imie>Brett</imie>

<nazwisko>McLaughlin</nazwisko>

</nazwa>

<email>brettmclaughlin@earthlink.net</email>

</osoba>

<osoba>

<nazwa>

<imie>Maciej</imie>

<nazwisko>Abacki</nazwisko>

</nazwa>

<email>mabacki@poczta.xyz.pl</email>

</osoba>

</ksiazkaAdresowa>

Wystąpiło tutaj kilka zjawisk, które należy dobrze zrozumieć. Po pierwsze, dla danego egzem­pla­rza (ang. instance) schematu XML (XML Schema) definiowana jest — i kojarzona z określonym identyfikatorem URI — przestrzeń nazw. Przestrzeń ta, o skrótowej nazwie xsi, służy do po­da­wania w dokumencie XML informacji o danym schemacie — dokładnie tak, jak robimy to tutaj. Dlatego w pierwszym wierszu udostępniamy elementy naszego egzemplarza schematu XML do wy­korzystania w całym dokumencie. W następnym wierszu definiujemy przestrzeń nazw samego dokumentu XML. Ponieważ nie są w nim wykorzystywane żadne jawne przestrzenie nazw (ina­czej niż w poprzednim przykładzie), deklarujemy domyślną przestrzeń nazw. Specyfikacja przestrzeni nazw XML mówi, że każdy element dokumentu XML musi należeć do jakiejś prze­strzeni nazw; domyślna przestrzeń nazw to ta, z którą skojarzony jest element w przypadku, gdy nie podano żadnej innej przestrzeni. Oznacza to, że wszystkie elementy bez przedrostka prze­strzeni nazw (czyli w tym przykładzie wszystkie) kojarzone są z tą właśnie przestrzenią domyślną.

Przy takim zdefiniowaniu przestrzeni nazw dokumentu oraz schematu XML możemy już zrobić to, co chcieliśmy, czyli skojarzyć schemat z dokumentem. Służy do tego atrybut sche­ma­Lo­ca­tion, należący do przestrzeni nazw XML Schema. Przed tym atrybutem stawiamy jego prze­strzeń nazw (xsi), którą przed chwilą zdefiniowaliśmy. Argument atrybutu składa się właściwie z dwóch identyfikatorów URI: pierwszy określa przestrzeń nazw skojarzoną ze schematem, a drugi jest identyfikatorem schematu, do którego się odwołujemy. W naszym przykładzie pierwszy iden­tyfikator to domyślna przestrzeń nazw, którą właśnie zadeklarowaliśmy, a drugi to plik mySche­ma.xsd w lokalnym systemie plików. Jak każdy inny atrybut XML, para ta umieszczana jest we­wnątrz cudzysłowów. I oto mamy w dokumencie odwołanie do schematu!

Mówiąc poważniej, zagadnienie to nie jest takie proste i wciąż stanowi jeden z najtrudniejszych dla użytkowników aspektów używania przestrzeni nazw i schematu XML. Do całego opisanego wyżej mechanizmu wrócimy wkrótce, na razie zaś wystarczy zrozumieć, że przestrzenie nazw umożliwiają wykorzystanie elementów z różnych grup, przy czym elementy te cały czas pozostają nieodłącznym fragmentem grup, z których pochodzą.

Elementy danych

Do tej pory unikaliśmy definiowania pojęcia „element”. Teraz nadeszła pora, aby wyjaśnić je do­kładnie. Element opatrzony jest dowolną nazwą i musi zawierać się w nawiasach kątowych. W na­szym przykładowym dokumencie obecne są elementy różnego rodzaju:

<!-- Element standardowy: znacznik otwierający -->

<JavaXML:Spis>

<!-- Element standardowy z atrybutem -->

<JavaXML:Rozdzial tematyka="XML">

<!-- Element z danymi tekstowymi -->

<JavaXML:Naglowek>Struktury publikacji WWW</JavaXML:Naglowek>

<!-- Element pusty -->

<JavaXML:PodzialSekcji/>

<!-- Element standardowy: znacznik zamykający -->

</JavaXML:Spis>

Pierwsza zasada tworzenia elementów mówi, że nazwa elementu musi rozpoczynać się literą lub podkreśleniem, po którym może wystąpić dowolna liczba liter, cyfr, podkreśleń, łączników lub kro­pek. Nazwy nie mogą zawierać spacji — poniższy przykład nie jest poprawnym elementem XML:

<!-- Zagnieżdżone spacje nie są dozwolone -->

<niepoprawna nazwa elementu>

W nazwach elementów XML rozróżniana jest wielkość liter. Mówiąc ogólnie, zastosowanie tych samych zasad, których używa się przy tworzeniu nazw zmiennych Javy, pozwala uzyskać po­prawne nazwy elementów XML. Nie powinno się skracać nazw typu „Obiekt telekomunikacyjny” do postaci <otk> (bo staną się niezrozumiałe), z drugiej strony nie powinno się też stosować elementów typu <poczatekNowegoRozdzialu>, bo niepotrzebnie zaśmiecają dokument. War­to pamiętać, że dokumenty XML będą najprawdopodobniej oglądane przez innych pro­gra­mi­stów, a więc dobrze jest używać znaczących, „samodokumentujących się” nazw.

Każdy otwarty element musi zostać zamknięty. I nie ma tutaj wyjątków, tak jak to jest w innych językach znaczników, np. w HTML-u. Znacznik końcowy składa się z ukośnika i nazwy elementu, np. </JavaXML:Spis>. Pomiędzy znacznikiem otwierającym a zamykającym może znajdować się dowolna ilość danych tekstowych lub innych elementów. Nie można jednak zmieniać ko­lej­ności zagnieżdżania — pierwszy otwarty element musi zostać zamknięty jako ostatni. Jeśli któraś z tych zasad nie zostanie spełniona, dokument XML będzie niepoprawnie skonstruowany. Po­pra­wnie skonstruowany (ang. well-formed) dokument to taki, w którym przestrzega się zasad składni języka XML, a wszystkie elementy i atrybuty znajdują się we właściwych miejscach. Jednakże po­prawnie skonstruowany dokument niekoniecznie musi być poprawny (ang. --> valid[Author:ts] ), tzn. nie musi być zgodny z ograniczeniami narzuconymi przez DTD lub schemat. Pomiędzy dokumentem po­praw­nie skonstruowanym a poprawnym jest duża różnica; w tym rozdziale zajmujemy się tylko poprawnością konstrukcji, natomiast reguły określające poprawność dokumentu przedstawimy w rozdziale 4.

Oto przykład dokumentu niepoprawnie skonstruowanego:

<znacznik1>

<znacznik2>

</znacznik1>

</znacznik2>

Kolejność zagnieżdżania nie jest prawidłowa, ponieważ po znaczniku otwierającym <zna­cznik2> nie znajduje się znacznik zamykający </znacznik2>. Ale po poprawieniu tego błę­du składniowego nie możemy jeszcze być pewni, że cały dokument jest poprawny. To istotna różnica, do której wrócimy w rozdziale 4.

Powyższy przykład niepoprawnie sformatowanego dokumentu może się wydawać banalny, ale z drugiej strony warto zauważyć, że w HTML-u byłby to zapis poprawny — i często pojawia się w du­żych tabelach wewnątrz dokumentów zapisanych w tym języku. Innymi słowy, HTML i wiele innych języków znaczników nie wymaga tworzenia poprawnie sformatowanych doku­men­tów w takim sensie, w jakim jest to rozumiane w definicji XML. Ścisłe przestrzeganie zasad za­gnieżdżania obowiązujących w XML-u umożliwia dużo szybsze przetwarzanie i sprawniejszą obsługę zapisanych w nim dokumentów.

Ostatnia zasada, jaką omówimy, dotyczy dość oryginalnych elementów pustych. Powiedzieliśmy już, że znaczniki XML muszą występować parami; na kompletny element XML składają się zna­czniki otwierający i zamykający. Są jednak przypadki, w których element występuje w doku­men­cie samodzielnie, informując np. o tym, że rozdział nie jest ukończony; są też elementy posiadające atrybuty, ale nie zawierające danych tekstowych — np. obrazek w HTML-u. Elementy takie na­leżałoby zapisywać w następujący sposób:

<rozdzialNiedokonczony></rozdzialNiedokonczony>

<img src="/images/xml.gif"></img>

Zapis ten jest niezbyt rozsądny i powoduje zwiększenie bałaganu w dokumencie. Specyfikacja XML dopuszcza jego uproszczenie poprzez zawarcie znacznika otwierającego i zamykającego w je­dnym elemencie:

<rozdzialNiedokonczony/>

<img src="/images/xml.gif"/>

Rozwiązuje to problem elegancji --> zapisu[Author:PG] , a jednocześnie nie narusza zasady, że każdy element XML musi mieć odpowiednik zamykający — tutaj jeden element jest jednocześnie otwierającym i zamykającym.

Atrybuty elementów

Oprócz tekstu zawartego pomiędzy znacznikami, element może także posiadać atrybuty. Atrybuty, wraz z odpowiadającymi im wartościami, zawarte są w deklaracji otwierającej elementu (która może być także deklaracją zamykającą!). Np. częścią znacznika JavaXML:Rozdzial był atry­but określający tematykę rozdziału:

<JavaXML:Rozdzial tematyka="Java">

<!-- Dane rozdzialu -->

</JavaXML:Rozdzial>

<JavaXML:Rozdzial tematyka="XML">

<!-- Dane rozdzialu -->

</JavaXML:Rozdzial>

W powyższym przykładzie tematyka to nazwa atrybutu, a jego wartościami są, odpowiednio, XML i Java. Nazwy atrybutów podlegają takim samym zasadom jak nazwy elementów XML, a ich wartości muszą znajdować się w cudzysłowach. Dopuszczalne są tu również apostrofy, ale stan­dardowo używa się cudzysłowów — odpowiada to zresztą konwencji przyjętej w Javie. Apostrofy i cudzysłowy można także wykorzystywać wewnątrz wartości atrybutu — jeśli znajduje się ona w cudzysłowach, to wewnątrz można użyć apostrofów, i odwrotnie. Nie jest to jednak metoda zalecana, jako że parsery i procesory XML często automatycznie przekształcają wszystkie cu­dzy­słowy otaczające wartości atrybutów na apostrofy (lub odwrotnie), co może spowodować nie­prze­wi­dywalne skutki.

Ważne jest nie tylko to, jak należy używać atrybutów, ale także gdzie ich używać. XML umoż­liwia tak rozmaite formatowanie danych, że rzadko kiedy nie jest możliwe wyrażenie atrybutu przez element, lub odwrotnie — elementu przez atrybut. Nie istnieje żadna specyfikacja ani ogól­nie przyjęty standard mówiący o tym, kiedy używać atrybutu, a kiedy elementu, ale można tutaj podać pewną radę praktyczną: elementów używa się do opisywania danych przeznaczonych do prezentacji, a atrybutów — do opisywania danych systemowych. Dane, które mają zostać przed­sta­wione klientowi albo aplikacji, najprawdopodobniej zostaną opisane za pomocą elementu. Mo­gą one być później traktowane jako dane aplikacji, które można w prosty sposób przeszukiwać i wykorzystywać. Jako przykład może tu posłużyć tytuł rozdziału książki, cena mebla czy adres URL firmowej witryny WWW. Jeśli jednak dane służą do grupowania lub za ich pomocą prze­kazujemy aplikacji informację o sposobie obsłużenia innej porcji danych, czy też wreszcie nie są bezpośrednio widziane przez klienta lub aplikację XML-ową, najprawdopodobniej będą miały postać atrybutu. Przykładami „dobrych kandydatów” na atrybuty mogą być części książki — sama część może być elementem posiadającym własny tytuł, ale grupowanie znajdujących się w niej rozdziałów da się w prosty sposób opisać atrybutem czesc w elemencie JavaXML:Rozdzial. Atrybut taki umożliwia proste indeksowanie części, ale nie będzie prezentowany bezpośrednio użytkownikowi. Innym dobrym przykładem jest sytuacja, w której klient zapłacił zadatek za dany towar (np. krzesło czy stół), „rezerwując” go w ten sposób dla siebie. Poinformowana o tym apli­kacja XML mogłaby wygenerować broszurę lub ulotkę, w której taki towar nie byłby już zawarty. I znów — klient nie widziałby bezpośrednio tej informacji, ale dane zostałyby wykorzystane przy obsłudze i przetwarzaniu dokumentu XML. Jeśli po tym wszystkim nadal jeszcze nie wiadomo, cze­go użyć, zawsze można postąpić asekuracyjnie i zastosować element.

Można też wyobrazić sobie inne sposoby reprezentacji przedstawionych przykładów. Zamiast np. korzystać z atrybutu opisującego część, można zagnieździć elementy JavaXML:Rozdzial w ele­mencie JavaXML:czesc; w drugim przykładzie użycie pustego znacznika <sprze­dane/> pozwoliłoby na sprawniejsze oznakowanie „zarezerwowanych” mebli. W języku XML rzadko mamy do czynienia z jednym tylko sposobem reprezentowania danych. Najczęściej to aplikacja i sposób wykorzystania danych determinują sposób postępowania. Nie będziemy więc pisać o tworzeniu zapisów w XML-u (byłoby to trudne), ale o ich używaniu — i właśnie przez praktyczne używanie Czytelnik będzie mógł poznać sposoby obsługi i użycia różnych re­pre­zen­ta­cji danych. Ta wiedza umożliwia Czytelnikowi samodzielne podejmowanie decyzji o spo­sobie formatowania dokumentów XML.

„Stałe” języka XML

Nie wspomnieliśmy jeszcze o sekwencjach unikowych i odwoływaniu się do innych, stałych war­tości. Dla przykładu, typową reprezentacją ścieżki do katalogu instalacyjnego jest zapis <sciezka-do-Cocoon> lub <katalog-Cocoon>. W obu przypadkach tekst taki zostałby zamieniony przez użytkownika na nazwę wybranego katalogu instalacyjnego. W rozdziale opisu­jącym aplikacje WWW jest przedstawiony przykład, w którym konieczne jest podanie szczegóło­wych informacji o instalacji i sposobie korzystania z aplikacji Apache Cocoon. Może zatem zajść po­trzeba użycia takiej reprezentacji danych w elemencie:

<JavaXML:Tematat> <JavaXML:Naglowek>Instalacja Cocoon</JavaXML:Naglowek> <JavaXML:Zawartosc> Plik Cocoon.properties znajduje się w katalogu <sciezka-do-Cocoon>/bin.

</JavaXML:Zawartosc>

</JavaXML:Temat>

Kłopot polega na tym, iż parser XML spróbuje obsłużyć takie dane jako znacznik XML i za­ko­mu­ni­kuje o błędzie, ponieważ nie znajdzie znacznika zamykającego. Jest to typowy problem związany z każ­­dą sytuacją, w której konieczne jest zastosowanie nawiasów kątowych. Można go rozwiązać za pomocą encji (ang. entity reference). Encja to specjalny typ danych XML służący do odwo­ły­wa­nia się do innych rodzajów danych. Składa się ona z niepowtarzalnej nazwy poprzedzonej zna­kiem ampersand (&) i zakończonej średnikiem, tj. &[nazwa-encji];. Po napotkaniu encji par­ser XML podstawia pod nią odpowiednią wartość i nie przetwarza jej dalej. W języku XML zde­finiowano pięć encji, które pomogą rozwiązać powyższy problem: &lt; to otwierający nawias ką­towy (lub symbol „mniejsze niż”), &gt; to zamykający nawias kątowy (lub symbol „większe niż”), &amp; to sam znak ampersand, &quot; to cudzysłów, a &apos; — apostrof. Za pomocą te­go rodzaju encji możemy przedstawić odwołanie do katalogu instalacyjnego w następujący sposób:

<JavaXML:Temat>

<JavaXML:Naglowek>Instalacja Cocoon</JavaXML:Naglowek>

<JavaXML:Zawartosc>

Plik Cocoon.properties znajduje się w katalogu &lt;sciezka-do-Cocoon&gt;/bin.

</JavaXML:Zawartosc>

</JavaXML:Temat>

Po przetworzeniu tego dokumentu pogrubiony zapis zostanie zinterpretowany jako <sciezka-do-Cocoon> i dokument zostanie zaakceptowany jako poprawnie sformatowany.

Należy także pamiętać, że encje mogą być definiowane przez użytkownika, co pozwala tworzyć swoiste zapisy skrótowe. W przedstawionym na początku rozdziału dokumencie XML znajduje się odwołanie do zewnętrznego, współużytkowanego tekstu noty o prawach autorskich. Ponieważ ten sam dokument wykorzystywany jest w wielu książkach wydawnictwa, nie chcemy zamieszczać go w całości w dokumencie XML. Jeśli jednak prawa autorskie ulegną zmianie, nasz dokument po­wi­nien te zmiany odzwierciedlić. Być może Czytelnik zauważył, że składnia wykorzystana w przy­kła­dowym dokumencie XML wygląda jak predefiniowana encja:

<JavaXML:Copyright>&HelionCopyright;</JavaXML:Copyright>

Co prawda dopiero w części omawiającej definicje DTD wyjaśnimy, w jaki sposób XML ustala, do czego ma się odwołać po napotkaniu encji &HelionCopyright;, ale już teraz należy zau­wa­żyć, że encje służą do wielu innych zadań, nie tylko do reprezentowania nietypowych znaków w danych.

Dane nieprzetwarzane

Ostatnia konstrukcja XML, jaką omówimy, to sekcja CDATA. Stosowana jest ona wtedy, gdy do aplikacji wywołującej trzeba przekazać dużą ilość danych nieprzetworzonych przez parser XML. Z tego sposobu można skorzystać wtedy, gdy dane zawierają wiele nietypowych znaków, których znaczenie należałoby znosić za pomocą encji, albo też gdy zależy nam na utrzymaniu układu te­kstu. W dokumencie XML sekcja CDATA wygląda następująco:

<nieprzetwarzane-dane>

<![CDATA[Diagram:

<Krok 1>Zainstaluj Cocoon do "/usr/lib/cocoon"

<Krok 2>Znajdź odpowiedni plik properties.

<Krok 3>Pobierz program Ant z adresu "http://jakarta.apache.org"

-----> skorzystaj z CVS <-----

]]>

</nieprzetwarzane-dane>

W tym przykładzie zawartość sekcji CDATA nie musi być kodowana za pomocą encji lub innych mechanizmów nakazujących parserowi specjalne postępowanie z nietypowymi znakami — prze­ka­że on je w niezmienionej postaci do aplikacji.

Poznaliśmy już najważniejsze składniki dokumentów XML. Każdy z nich został omówiony nie­ja­ko „przy okazji”, ale już teraz Czytelnik powinien potrafić rozpoznać znaczniki XML i ich prze­zna­czenie. W następnych rozdziałach książki poznamy kolejne właściwości tych konstrukcji, wykonując ćwiczenia praktyczne — ta metoda nauki jest najlepsza.

Co dalej?

Po tym wstępie do tworzenia dokumentów XML możemy rozpocząć pisanie pierwszego programu w Javie. W następnym rozdziale przyjrzymy się prostemu interfejsowi Simple API for XML (SAX). Zaczniemy od przetworzenia naszego dokumentu za pomocą prostego programu, a następnie po­znamy sposoby obsługi instrukcji przetwarzania, elementów, atrybutów i innych konstrukcji ję­zyka XML w procesie przetwarzania dokumentu. Autor zaprezentuje kod napisany w Javie wy­konujący poszczególne czynności, zaczynając od prostego programu drukującego dokument XML. W kolejnym rozdziale rozpocznie się intensywny proces nauki manipulowania składnikami do­ku­men­tu XML oraz ich stosowania w aplikacjach Javy.

52 Rozdział 2. Tworzenie dokumentów XML

Co dalej? 51

C:\Helion\Java i XML\jAVA I xml\02-08.doc — strona 52

C:\Helion\Java i XML\jAVA I xml\02-08.doc — strona 51

C:\Helion\Java i XML\jAVA I xml\02-08.doc — strona 41

[Author ID1: at Thu Feb 22 01:28:00 2001 ][Author ID1: at Thu Feb 22 01:28:00 2001 ][Author ID1: at Thu Feb 22 01:28:00 2001 ][Author ID1: at Thu Feb 22 01:28:00 2001 ][Author ID1: at Thu Feb 22 01:28:00 2001 ][Author ID1: at Thu Feb 22 01:28:00 2001 ]„how Java provides callbacks to the parsing process": "callback" [Author ID1: at Thu Feb 22 01:28:00 2001 ]and[Author ID1: at Thu Feb 22 01:29:00 2001 ] "parsing" [Author ID1: at Thu Feb 22 01:28:00 2001 ]are terms of the art of programming. They have been summarily dismissed. It doesn't matter here, but it may well in a more technical context.[Author ID1: at Thu Feb 22 01:29:00 2001 ] [ts] I agree that it doesn't matter here, thus they have been summarily dismissed

z „parserem” jest pewien problem — teoretycznie powinno się powiedzieć „analizator [składniowy]”, bo słówka „parser” oficjalnie nie ma w słowniku. Ale, zgodnie z informacjami uzyskanymi od tłumacza, „parser” nie tylko analizuje, ale również modyfikuje dokument, więc słowo „analizator” może być nieprecyzyjne. Użycie słów „procesor” i „translator” odpada (pierwsze znaczy w tym kontekście co innego, drugie jest zbyt ogólne). Czy Recenzent odda swój głos w tej sprawie? — See Comment 2 above. "Parser" sounds great. It comes from the Latin "pars"[Author ID1: at Thu Feb 22 01:53:00 2001 ]part. [Author ID1: at Thu Feb 22 01:53:00 2001 ]S[Author ID1: at Thu Feb 22 02:16:00 2001 ]lapping Polish endings on Latin words[Author ID1: at Thu Feb 22 02:16:00 2001 ] [Author ID1: at Thu Feb 22 01:57:00 2001 ]is[Author ID1: at Thu Feb 22 02:17:00 2001 ] an even older tradition in Polish than sla[Author ID1: at Thu Feb 22 01:57:00 2001 ]pping Polish endings on English words. [Author ID1: at Thu Feb 22 01:58:00 2001 ]- pg.[Author ID1: at Thu Feb 22 01:59:00 2001 ] [ts] OK, to zostaje parser, ale ja się pod tym nie podpisuję.

[PG]The yellow highlighted text, in which the Translator explains why he added the above string, should better be moved to a footnote. [ts] Zgadzam się i proszę Tłumacza o stosowanie się do zasady, że uzupełnienia od tłumacza muszą być opatrzone dopiskiem „przyp. tłum.” (mogą być umieszczane bezpośrednio w tekście lub w przypisach). (tłumacz: ok., od tej pory będzie wszędzie jednolicie „przyp. tłum”)

Zawężanie dokumentów XML? specyfikacji XML? Akceptuję możliwość odmiany akronimu XML, ale w tytule brzmi to trochę nieciekawie. Mam też pewne wątpliwości do samego słowa „zawężanie” (ograniczanie?)

albo Helion — to zależy, na czym w końcu stanie w kwestii adresu WWW; zob. uwaga 2.

tu też konieczna będzie aktualizacja po ustaleniu ostatecznego spisu treści

?

[Author ID1: at Thu Feb 22 03:19:00 2001 ][Author ID1: at Thu Feb 22 03:19:00 2001 ][Author ID1: at Thu Feb 22 03:19:00 2001 ][Author ID1: at Thu Feb 22 03:19:00 2001 ][Author ID1: at Thu Feb 22 03:19:00 2001 ][Author ID1: at Thu Feb 22 03:19:00 2001 ]It doesn't seem to make sense to give English equivalents of terms other than [Author ID1: at Thu Feb 22 03:19:00 2001 ]those used in [Author ID1: at Thu Feb 22 03:21:00 2001 ]software strings. If we [Author ID1: at Thu Feb 22 03:19:00 2001 ]offer "valid", why not "document" and "book" etc[Author ID1: at Thu Feb 22 03:21:00 2001 ].[Author ID1: at Thu Feb 22 03:19:00 2001 ] [ts] It does make sense here. The distinction between Polish equivalents of „valid” and ”well-formed” is somewhat less obvious than between „document” and „book”.

[Author ID1: at Thu Feb 22 03:22:00 2001 ][Author ID1: at Thu Feb 22 03:22:00 2001 ][Author ID1: at Thu Feb 22 03:22:00 2001 ][Author ID1: at Thu Feb 22 03:22:00 2001 ][Author ID1: at Thu Feb 22 03:22:00 2001 ][Author ID1: at Thu Feb 22 03:22:00 2001 ]"nie musi być" can mean "is not necessarily", but also can be misunderstood as "doesn't need to be".[Author ID1: at Thu Feb 22 03:22:00 2001 ] [ts] splitting hairs

thanks, this is much more elegant



Wyszukiwarka

Podobne podstrony:
05-08, Programowanie, ! Java, Java i XML
12-08, Programowanie, ! Java, Java i XML
01-08, Programowanie, ! Java, Java i XML
14-08, Programowanie, ! Java, Java i XML
00-08-orig, Programowanie, ! Java, Java i XML
Java i XML, programowanie, Java
Java i XML, programowanie, Java
Java i XML, programowanie, Java
r12-05, Programowanie, ! Java, Java Server Programming
r20-05, Programowanie, ! Java, Java Server Programming
O Autorach-05, Programowanie, ! Java, Java Server Programming
programowanie C java
r05-05, Programowanie, ! Java, Java Server Programming
r07-05, Programowanie, ! Java, Java Server Programming
r03-05, Programowanie, ! Java, Java Server Programming
rE-05, Programowanie, ! Java, Java Server Programming
r19-05, Programowanie, ! Java, Java Server Programming
r17-05, Programowanie, ! Java, Java Server Programming

więcej podobnych podstron