04-08.doc

(209 KB) Pobierz
Wstęp

XML Schema              115

 

4

 

Zawężanie danych XML

 

 

 

 

Nauka XML-a, zarówno jako reprezentacji danych, jak i materiału wykorzystywanego przez apli­ka­cję w Javie, to proces wieloetapowy. Kolejne poznawane cechy XML-a lub technologii sio­strza­nych przyczyniają się do odkrywania całych pokładów wiedzy o tym języku. Istnieje wiele projektów i specyfikacji związanych z XML-em; pojawia się pokusa „poznania wszystkiego”. A kiedy w koń­cu wydaje nam się, że poznaliśmy wszystkie strony zagadnienia, pojawiają się nowe wersje... Im le­piej jednak rozumiemy zasadę działania poszczególnych komponentów składających się na kraj­obraz XML-a, tym lepiej przygotowani jesteśmy na wszelkie nowinki w naszym programistycznym warsztacie. Pamiętając o tym, na jakiś czas porzucimy teraz język Java i wrócimy do specyfikacji związanych z samym XML-em.

W rozdziałach 2. i 3. uzyskaliśmy wiedzę, która powinna wystarczyć do stworzenia poprawnie sfor­matowanego dokumentu oraz do późniejszej manipulacji (w ograniczonym zakresie) tym do­ku­mentem z poziomu Javy. Powinniśmy także rozumieć, jak przetwarzane są dokumenty XML i jak w tym procesie można wykorzystać klasy SAX. W tym rozdziale zostanie omówione zawężanie do­kumentów XML, a w następnym — wpływ zawężania na przetwarzanie takiego dokumentu w Javie.

Po co zawężać dane XML?

Wypada najpierw wytłumaczyć, do czego potrzebne są Czytelnikowi wiadomości dotyczące defi­ni­cji DTD i schematów. Niektórzy użytkownicy XML-a twierdzą, że w ogóle nie ma potrzeby za­wężania dokumentów XML i sprawdzania ich poprawności. Jak już powiedzieliśmy, poprawny dokument XML spełnia wymogi zawężeń na niego narzuconych przez odpowiednią definicję DTD lub schemat. Napisaliśmy również, że choć dokument jest poprawnie sformatowany, to nie musi jeszcze być poprawny. Po cóż więc zadawać sobie trud tworzenia definicji DTD lub schematu, któ­ry narzuca dodatkowe reguły na dane XML?

Komentarze w programach

Jako programujący w Javie, Czytelnik zapewne potrafi już dokumentować swój kod za pomocą na­rzędzia Javadoc lub komentarzy w samym kodzie. Prawdopodobnie wie także, jak ważne jest dokumentowanie własnej pracy — być może na kogoś spadnie obowiązek czytania naszego kodu, poprawiania, czy po prostu zrozumienia. Komentowanie kodu jest jeszcze ważniejsze w pro­je­ktach open source. Być może zdarzyło nam się kiedyś, że poganiani terminami nie byliśmy zbyt rozlewni w komentowaniu programu. A trzy miesiące później programista, któremu powierzono zadanie kontynuowania projektu, zasypywał nas telefonami o przeznaczenie danego fragmentu kodu. Dobrze, jeśli jeszcze pamiętaliśmy; gorzej, jeśli dawno już zapomnieliśmy, jak udało nam się zrobić „tę sztuczkę”. Właśnie w takich chwilach poznajemy wartość dokumentacji.

Dane XML to z pewnością nie kod. W wyniku zagnieżdżania i innych reguł składniowych niemal zawsze łatwiej jest zrozumieć dokument XML niż fragment kodu w Javie. Jednakże nie należy zakładać, że to, jak my widzimy naszą reprezentację danych, będzie identycznie postrzegane przez innych. Świetnie obrazuje to plik XML z przykładu 4.1.

Przykład 4.1. Dwuznaczny plik XML

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

 

<strona>

  <ekran>

    <nazwa>Sprzedaż</nazwa>

    <kolor>#CC9900</kolor>

    <font>Arial</font>

  </ekran>

  <zawartosc>

    <p>Tu idzie cała zawartość.</p>

  </zawartosc>

</strona>

Przeznaczenie powyższego pliku wydaje się zupełnie oczywiste. Za jego pomocą aplikacja otrzy­muje informacje o sposobie wyświetlenia konkretnego ekranu u klienta. Podany jest kolor, rodzaj czcionki oraz zawartość ekranu. Gdzież tutaj dwuznaczność? Cóż, staje się ona ewidentna dopiero po obejrzeniu innego dokumentu wykorzystywanego w tej samej aplikacji (przykład 4.2).

Przykład 4.2. Mniej dwuznaczny plik XML

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

 

<strona>

  <ekran>

    <nazwa>Sprzedaż</nazwa>

    <kolor>#CC9900</kolor>

    <font>Arial</font>

  </ekran>

  <ekran>

    <nazwa>Komunikaty</nazwa>

    <kolor>#9900FF</kolor>

    <font>Arial</font>

  </ekran>

  <ekran>

    <nazwa>Nowości</nazwa>

    <kolor>#EECCEE</kolor>

    <font>Helvetica</font>

  </ekran>

  <zawartosc>

    <p>Tu idzie cała zawartość.</p>

  </zawartosc>

</strona>

I nagle nasza interpretacja pierwszego pliku nie wydaje się już poprawna. Element ekran nie mo­że reprezentować bieżącego ekranu, bo w drugim przykładzie widzimy aż trzy takie elementy. W rzeczywistości aplikacja tworzy na górze strony odsyłacze do dostępnych ekranów i właśnie element ekran opisuje, jak odsyłacze te mają wyglądać — podana jest nazwa odsyłacza, kolor fra­gmentu ekranu i czcionka. W pierwszym przypadku tak się złożyło, że był tylko jeden ekran, do którego tworzono odsyłacz, i stąd to zamieszanie. Tylko autor dokumentu XML lub programista apli­kacji od razu zrozumieliby, o co tutaj chodzi.

Zawężanie dokumentów XML umożliwia udokumentowanie takich dwuznacznych sytuacji. Gdy­byśmy wiedzieli, że w danej stronie XML dozwolony jest tylko jeden element ekran, mogli­byś­my bezpiecznie poczynić takie założenie, jakie zrobiliśmy odnośnie pierwszego przykładu. Gdy­byśmy jednak wiedzieli, że dozwolonych jest wiele elementów ekran, to nawet patrząc tylko na pierwszy przykład moglibyśmy trafniej odgadnąć przeznaczenie dokumentu. Innymi słowy, po­praw­nie sformatowany dokument XML zawiera słowa występujące w słowniku. Słowa te mają pewne znaczenia, ale mogą być wykorzystywane w różny sposób. Jako przykład weźmy słowa: „Lis kot bieg chleb ser”. Poprawność (ang. validity) dokumentu daje nam gwarancje, że „słowa” te (elementy i atrybuty dokumentu XML) zostaną złożone w sensowny sposób: „Lisy i koty biegną w kierunku chleba z serem”.

Udokumentowanie „poprawnych” czy „właściwych” połączeń elementów i atrybutów to właśnie za­danie definicji DTD lub schematu. Umożliwiają one samodokumentowanie się danych XML — te­raz już nie tylko my będziemy wiedzieli, co właściwie chcieliśmy przekazać za pomocą danych XML.

Przenośność

Zawężanie XML-a pomaga nie tylko zrozumieć sposób reprezentacji danych innym osobom; po­maga także zrozumieć dane innym aplikacjom. Wspomnieliśmy o tym już wcześniej — jeśli weź­mie­my dwie dowolne aplikacje, to nie możemy zakładać, że korzystają one ze wspólnych zasobów. Mówiąc inaczej, program, który utworzył dokument XML w jednej aplikacji, może nie być do­stępny w drugiej; ta druga aplikacja „nie rozumie” logiki, według której powstał dokument XML. Druga aplikacja musi więc określić sama, jaki typ danych jest przekazywany za pośrednictwem dokumentu XML. Nie mając żadnych wskazówek, druga aplikacja mogłaby tylko zakładać, co „autor miał na myśli” — i często byłyby to założenia błędne.

Przypomina to nieco problemy z językiem C, których starali się uniknąć twórcy Javy. Java, nie­za­leżna od platformy i nie polegająca na kodzie własnym, jest obecnie najbardziej przenośnym ję­zykiem programowania. Wynika to stąd, że nałożono szereg zawężeń na to, co Java może robić i zawężenia te działają na wszystkich platformach. Takie szczegóły implementacyjne jak za­rzą­dza­nie pamięcią czy wątkami pozostawiono do rozwiązania poszczególnym platformom, ale interfejs do obsługi tych zadań przez programistę jest zawsze taki sam.

Zawężanie dokumentów za pomocą definicji DTD lub schematów gwarantuje podobną prze­noś­ność w języku XML. Przypomnijmy sobie pierwszy z dwóch powyższych przykładów — gdyby inna aplikacja mogła uzyskać dostęp do zasobu opisującego dozwolone formaty przetwarzanych da­nych, mogłaby przetworzyć te dane za pomocą narzędzi XML-a. Ponieważ zawężenia doku­mentu nie zostały zakodowane bezpośrednio w aplikacji (pierwszej czy drugiej), logika aplikacji nie zmieni się po zmianie formatu dokumentu. Definicja DTD lub schemat mógłby ulec zmianie, ale ponieważ pracujemy na tekstowym opisie zawężeń, aplikacja mogłaby natychmiast wyko­rzystać dokument o zmienionej strukturze, bez konieczności modyfikacji samej aplikacji. W ten sposób uzyskuje się przenośność danych XML bez konieczności ingerencji w kod aplikacji — tak jak próbuje się unikać kodu własnego w programach w Javie.

Czy to na potrzeby dokumentacji, przenośności pomiędzy aplikacjami i systemami, czy po prostu ze względu na bardziej restrykcyjne sprawdzanie poprawności danych XML, zawężanie przydaje się w niemal wszystkich przypadkach. Przeciwnicy zawężania mają rację właściwie tylko w jed­nym — sprawdzanie poprawności danych ma duży wpływ na wydajność całego procesu. Jednakże w wielu strukturach publikacji, np. takich jak Apache Cocoon, można określić, czy dany dokument ma być sprawdzany pod kątem poprawności, czy nie. Oznacza to, że tworzenie dokumentu można przeprowadzać przy włączonym sprawdzaniu poprawności i wyłączyć je dopiero wtedy, gdy stru­ktura dokumentu została już solidnie przetestowana. Aplikacje otrzymujące dane również mogą sprawdzać lub nie sprawdzać poprawności dokumentu. W razie potrzeby zawsze jest to możliwe, bo dokument ten zawierać będzie odwołanie do definicji DTD lub schematu. A więc możliwe jest korzystanie ze sprawdzania składni bez jednoczesnego zmniejszania wydajności aplikacji. Wcześ­niej należy jednak sprawdzić, czy funkcja włączania-wyłączania sprawdzania jest dostępna w wy­korzystywanej strukturze publikacji.

W systemach produkcyjnych sprawdzanie poprawności oznacza wyższą jakość aplikacji typu fir­ma-firma (ang. business-to-business). Sprawdzanie poprawności daje gwarancję, że dane otrzy­ma­ne z innych aplikacji — często takich, na które nie mamy wpływu — są poprawnie sformatowane. Dzięki temu unikamy błędów wynikających z niepoprawnego formatu danych wejściowych. Tutaj definicje DTD i schematy są wprost nieocenione.

Definicje typu dokumentu

Jak już to zostało powiedziane, dokument XML ma niewielką wartość bez towarzyszącej mu de­fi­nicji DTD. XML w wydajny sposób opisuje dane, a DTD przygotowuje te dane do użycia w wielu różnych programach poprzez zdefiniowanie ich struktury. W tej części książki zajmiemy się kon­stru­kcjami DTD. W funkcji przykładowego pliku XML znów zostanie wykorzystany fragment spi­su treści niniejszej książki, dla którego zbudujemy definicję DTD.

Zadaniem definicji DTD jest określenie sposobu formatowania danych. Zdefiniowany musi zostać każdy element dozwolony w danym dokumencie XML, sposoby występowania i zagnieżdżania ele­mentów, a także zewnętrzne encje. Tak naprawdę w definicji DTD można określić jeszcze wie­le innych aspektów dokumentu, ale tutaj skoncentrujemy się na tych podstawowych. Poznamy konstrukcje oferowane przez DTD — za ich pomocą zawęzimy nasz przykładowy plik z rozdziału 2. Ponieważ do pliku tego będziemy się często odwoływali w tym rozdziale, warto przytoczyć go tutaj jeszcze raz (przykład 4.3).

Przykład 4.3. Plik XML zawierający spis treści

<?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:Title>Java i XML</JavaXML:Title>

<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>&OReillyCopyright;</JavaXML:Copyright>

 

</JavaXML:Ksiazka>

Określanie elementów

Najpierw zajmiemy się określaniem, które elementy są w naszym dokumencie dozwolone. Chce­my, aby definicja DTD umożliwiała autorom umieszczanie w naszym dokumencie takich elemen­tów jak JavaXML:Ksiazka i JavaXML:Spis, ale nie JavaXML:jas czy JavaXML:malgo­sia. Określenie zestawu dozwolonych elementów oznacza nadanie takiemu dokumentowi zna­cze­nia semantycznego; innymi słowy określamy dopuszczalny (sensowny) kontekst. Najpierw należy więc stworzyć listę dopuszczalnych elementów. Najprostszym sposobem jest przejrzenie dokumentu i odnotowanie każdego wykorzystanego elementu. Dobrze jest także zdefiniować przeznaczenie poszczególnych znaczników. Co prawda na określenie przeznaczenia elementów

nie pozwala bezpośrednio DTD (chyba że za pomocą komentarzy — to całkiem niezłe roz­wią­za­nie), ale coś takiego uprościłoby pracę autora DTD. W tabeli 4.1 przedstawiono pełne zestawienie ele­mentów dokumentu contents.xml.

Tabela 4.1. Elementy dozwolone w naszym dokumencie XML

Nazwa elementu

Znaczenie

JavaXML:Ksiazka

element główny

...

Zgłoś jeśli naruszono regulamin