oraz jako element przetwarzania, które powinno się odbyć w sposób opisany w punkcie 4. procedury omówionej na początku tego podrozdziału.
Rysunek 2.15. Każda instrukcja xsl:for-each z rysunku 2.14 tworzy nowy wiersz dla każdego cudu. (Uwaga! Na tym rysunku ze względu na ograniczoną ilość miejsca nie zostały pokazane wszystkie wiersze). Po przetworzeniu wszystkich tych węzłów w wybranym zbiorze kontynuowane jest przetwarzanie reszty szablonu
Ponieważ arkusz stylów jest sam w sobie również dokumentem XML, to jeśli kod HTML jest częścią pliku XSLT, musi być zgodny z regułami pisania dokumentów XML. Przykładowo każdy znacznik otwierający musi posiadać odpowiadający mu znacznik zamykający, a elementy nie mogą na siebie zachodzić. Więcej szczegółów na ten temat znajdziesz w rozdziale 1.
Rysunek 2.16. Zwróć uwagę, że nazwa każdego cudu jest napisana w języku polskim, a następnie w języku oryginalnym, jeśli taki istnieje
47
Zapętlanie węzłów
W warunku select elementu xsl:for-each możesz zażądać dopasowania konkretnego atrybutu, stosując instrukcję @[atrybut='wyrażenie']. Jest to ta sama składnia, którą stosowaliśmy w atrybucie select dla obydwu elementów xsl:value-of z rysunku 2.14.
Rozdział 2.
Warunkowe przetwarzanie węzłów Nierzadko zdarza się, że chcemy przetworzyć określony węzeł lub grupę węzłów tylko w wypadku spełnienia określonego warunku. Taki warunek jest zapisywany jako wyrażenie. Mógłbyś na przykład wykonać określone działanie, jeśli konkretny zbiór węzłów nie jest pusty lub jeśli wartość ciągu tego węzła stanowi konkretne słowo.
Aby przetwarzać węzły warunkowo: 1. W obrębie reguły szablonu wpisz
Rysunek 2.17. Tutaj warunek xsl:if test sprawdza, czy bieżącym węzłem jest węzeł nazwa z atrybutem jezyk innym niż polski. Jeśli tak jest, wyświetlana jest wartość danego węzła nazwa. Jeśli warunek nie jest spełniony, nie jest podejmowane żadne działanie. Zapobiega to wyświetlaniu pustych par nawiasów w przypadku, gdy nie ma nazwy w języku alternatywnym
3. Wpisz >, aby zamknąć znacznik.
Warunkowe przetwarzanie węzłów
4. Określ, co powinno się zdarzyć, jeśli zbiór węzłów, ciąg lub liczba określona w punkcie 2. nie są puste (lub w przypadku liczby nie jest ona równa zero). 5. Wreszcie wpisz , aby zakończyć instrukcję (rysunek 2.17).
Wskazówki Gdy odnosimy się do zbioru węzłów w wyrażeniu, instrukcja test zwraca wartość „prawda”, jeśli dany zbiór węzłów nie jest pusty, czyli zawiera przynajmniej jeden węzeł. Jeśli chcesz mieć możliwość określenia alternatywnego rezultatu, kiedy wyrażenie jest fałszywe (np. w postaci warunku typu „w przeciwnym razie”), zastosuj element xsl:choose (patrz podrozdział „Dodawanie wyborów warunkowych”).
Rysunek 2.18. W tym pliku wyjściowym z dokumentu XSLT przedstawionego na rysunku 2.17 pogrubiony tekst pokazuje wersję elementu nazwa zapisanego w języku alternatywnym. Zwróć uwagę, że w przypadku wielkiej piramidy w Gizie nie ma żadnych dodatkowych elementów wyjściowych, ponieważ nie ma alternatywnego języka w tym węźle nazwa
Możesz testować wszelkiego rodzaju warunki. Szczegółowe informacje dotyczące konstruowania bardziej skomplikowanych wyrażeń testujących znajdziesz w rozdziale 3., „Wzorce i wyrażenia XPath”.
Rysunek 2.19. Jeśli istnieje nazwa w innym języku niż polski, jest ona wyświetlana. W przeciwnym razie nie ma żadnego elementu wyjściowego
48
XSLT
Dodawanie wyborów warunkowych Opisana w poprzednim podrozdziale instrukcja xsl:if pozwala na utworzenie tylko jednego warunku i podjęcie na tej podstawie tylko jednego działania. Jeśli chcesz przetestować kilka różnych warunków i zareagować odpowiednio w przypadku spełnienia któregokolwiek z nich, możesz zastosować instrukcję xsl:choose. Najprostszym przykładem jest sytuacja, w której chcesz wykonać jedno działanie w przypadku, gdy warunek jest prawdziwy, a inne, gdy okaże się fałszywy. Rysunek 2.20. W dokumencie XML ustawiłem zero jako wysokość wiszących ogrodów Semiramidy. Zrobiłem to, ponieważ potrzebowałem numerycznej wartości dla tego węzła. Skoro jednak nie przetrwały żadne dokumenty dotyczące tych ogrodów, nikt nie wie, jakie mogły być ich rozmiary. (W rzeczywistości kwestionowane jest w ogóle ich istnienie, ale to już inna historia)
Aby dodać wybory warunkowe: 1. W obrębie reguły szablonu wpisz . 2. Wpisz , aby zamknąć znacznik.
6. Wpisz , aby zakończyć warunek. 7. Powtórz etapy 2. – 6. dla każdego warunku. Rysunek 2.21. Dzięki zastosowaniu instrukcji xsl:choose na rysunku 2.20 zamiast zera dla wiszących ogrodów Semiramidy (tak jak na rysunku 2.19) wyświetlana jest wartość nieznana
8. W razie potrzeby wpisz . Określ, co powinno się zdarzyć, jeśli żaden z warunków określonych elementami xsl:when nie okaże się prawdziwy. Następnie wpisz jeszcze raz . 9. Na koniec wpisz , aby zakończyć instrukcję.
Wskazówka W przypadku zdefiniowania wielu warunków, gdy jeden z nich zostanie spełniony, pozostałe są ignorowane (nawet jeśli któryś kolejny warunek również jest spełniony). Podejmowane jest jedynie działanie opisane dla pierwszego spełnionego warunku. Rysunek 2.22. Teraz ta informacja ma większy sens
49
Dodawanie wyborów warunkowych
5. Określ, co powinno się zdarzyć, jeśli zbiór węzłów, ciąg lub liczba określona w punkcie 3. nie są puste (lub w przypadku liczby nie jest ona równa zero).
Rozdział 2.
Sortowanie węzłów przed przetworzeniem Domyślnie węzły są przetwarzane w takiej kolejności, w jakiej pojawiają się w dokumencie źródłowym XML. Jeśli chciałbyś zmienić kolejność ich przetwarzania, możesz dodać element xsl:sort, kiedy stosujesz element xsl:for-each.
Aby posortować węzły przed przetworzeniem: 1. Bezpośrednio po elemencie xsl:for-each wpisz
Rysunek 2.23. Zaraz po elemencie xsl:for-each dodałem instrukcję xsl:sort, aby posortować węzły do przetwarzania według wysokości w porządku malejącym
2. Następnie wpisz select="kryteria", gdzie kryteria to wyrażenie określające węzeł (klucz), według którego mają zostać posortowane węzły źródłowe.
Sortowanie węzłów przed przetworzeniem
3. W razie potrzeby wpisz order="descending" (sortowanie w porządku malejącym). Dla węzłów domyślnym ustawieniem jest sortowanie w porządku rosnącym (ang. ascending). 4. W razie potrzeby wpisz data-type="text" (sortowanie tekstu) lub data-type="number" (sortowanie liczb), w zależności od tego, co sortujesz. Domyślnym typem danych jest text. 5. Na koniec wpisz />, aby zamknąć instrukcję (rysunek 2.23). 6. Powtórz etapy 1. – 5., aby zdefiniować tyle parametrów sortowania, ile potrzebujesz,
Rysunek 2.24. Według dokumentu XSLT z rysunku 2.23 piramida Cheopsa (najwyższy ze starożytnych cudów) będzie przetwarzana jako pierwsza i dlatego pojawi się na pierwszym miejscu w tabeli
Wskazówki Upewnij się, że zdefiniowałeś właściwy typ danych (data-type) w punkcie 4. Sortowanie liczb jako tekstu może skutkować błędnymi wynikami, np. 100, 7, 89. Podobnie nieskuteczne jest sortowanie tekstu jako liczb. Sortowanie malejące (ang. descending) oznacza porządkowanie liczb od największej do najmniejszej oraz liter od Z do A. Sortowanie rosnące (ang. ascending) oznacza porządkowanie liczb od najmniejszej do największej oraz liter od A do Z. Elementy xsl:sort możesz zagnieżdżać w innych elementach xsl:sort. Umożliwia to zdefiniowanie sortowania według wielu węzłów (kluczy).
50
Rysunek 2.25. Teraz cuda starożytności są wylistowane według wysokości w porządku malejącym. Najwyższy z nich mierzy ponad 45 pięter
XSLT
Generowanie atrybutów wyjściowych W trakcie przekształcania dokumentu źródłowego XML w dokument HTML (lub w inny dokument XML) często przydaje się możliwość dodania atrybutów i wartości dla danego elementu wyjściowego. Przykładowo jeśli tworzysz element lub element , możesz mieć potrzebę dodania atrybutów, odpowiednio: src, width i height lub href i target. Rysunek 2.26. Tutaj wykorzystałem instrukcję xsl:attribute, aby dodać atrybut href do elementu kotwicy . Wartość href będzie ustawiona na £ (znak funta), a nazwa cudu będzie przetwarzana. W ten sposób każdy cud będzie powiązany na stronie z odwołaniem o nazwie danego cudu
Aby wygenerować atrybuty wyjściowe: 1. Bezpośrednio po znaczniku otwierającym element, w którym powinien pojawić się ten nowy atrybut, wpisz , aby zamknąć znacznik.
5. Na koniec wpisz , aby zakończyć generowanie atrybutu (rysunek 2.26). Rysunek 2.27. Teraz piramida Cheopsa jest powiązana z odwołaniem href o tej samej nazwie co nazwa cudu
6. Powtórz etapy 1. – 5., aby zdefiniować tyle atrybutów, ile potrzebujesz.
Wskazówka W punkcie 4. często będziesz korzystał z elementu xsl:value-of, aby wygenerować wartość atrybutu z zawartości, która pochodzi z Twojego dokumentu XML.
Rysunek 2.28. Teraz każda z nazw cudu posiada własne hiperłącze
51
Generowanie atrybutów wyjściowych
4. Określ wartość nowego atrybutu, korzystając z instrukcji XSLT lub elementów literalnych.
Rozdział 2.
Tworzenie i stosowanie szablonów Jak omówiono w podrozdziale „Przekształcanie dokumentów XML za pomocą XSLT”, szablon główny jest pierwszą rzeczą przekształcaną w arkuszu stylów XSLT. Szablon ten stanowi zbiór reguł zastosowanych do węzła głównego źródłowego dokumentu XML. Jak się okazuje, XSLT pozwala tworzyć więcej szablonów niż tylko szablon główny. Umożliwia to tworzenie różnych zestawów reguł przetwarzania, które będą stosowane do różnych części Twojego dokumentu XML. Chociaż większa część przetwarzania XSLT może odbywać się bez wykorzystywania szablonów, to jedną z głównych zalet ich stosowania jest możliwość ponownego wykorzystania szablonu dla pozostałych węzłów dokumentu. W ten sam sposób, w jaki korzysta się z funkcji w większości języków programowania, możesz stworzyć szablon i po prostu stosować go, kiedy jest to konieczne. Eliminuje to konieczność pisania za każdym razem od nowa tych samych instrukcji przetwarzania.
Rysunek 2.29. W tym fragmencie kodu dodałem nowy szablon dla tych węzłów nazwa, których atrybut jezyk jest inny niż polski. Szablon ten będzie wyświetlał wartość bieżącego węzła nazwa ujętą w nawiasy i zapisaną kursywą. Można to zrobić dzięki wykorzystaniu instrukcji xsl:value-of select=".", która zwraca wartość bieżącego węzła
Aby utworzyć szablon:
Tworzenie i stosowanie szablonów
1. Wpisz , aby zamknąć znacznik. 4. Określ wszystkie transformacje, które mają być wykonane, gdy zostanie znaleziony węzeł pasujący do wzorca z punktu 2. 5. Na koniec wpisz , aby zakończyć szablon.
Wskazówki Szablon główny to po prostu szablon z wzorcem, który odpowiada węzłowi głównemu. Tylko szablon główny jest wywoływany automatycznie. Wszystkie pozostałe szablony muszą być zastosowane ręcznie (patrz kolejny punkt), w przeciwnym razie są po prostu ignorowane.
52
Rysunek 2.30. W tym fragmencie tego samego arkusza stylów XSLT zastosowałem element xsl:apply-templates w miejsce elementu xsl:if widocznego na rysunku 2.17. Ten element xsl:if testował węzeł nazwa pod kątem atrybutu jezyk innego niż polski. Nowy plik wyjściowy będzie taki sam jak poprzednio, co będziesz mógł zobaczyć na kolejnych rysunkach
XSLT Teraz, gdy nauczyłeś się już tworzyć szablony, następnym krokiem jest poznanie sposobu ich używania. Innymi słowy, chodzi o sposób, w jaki szablon stosuje się do określonego węzła w dokumencie XML. Określa się to za pomocą elementu xsl:apply-templates. W ten sposób kontrolujesz, gdzie i kiedy w finalnym dokumencie dokonywana jest transformacja opisana w danym szablonie.
Aby zastosować szablon: 1. W obrębie wybranego szablonu wpisz
Rysunek 2.31. W tym fragmencie tego samego arkusza stylów XSLT dodałem nową sekcję Historia, aby zaprezentować historyczne informacje o cudach starożytności. Wykorzystałem ponownie nowy szablon z rysunku 2.29 z zaznaczonym pogrubieniem elementem xsl:apply-templates wyświetlającym niepolską nazwę
2. Następnie wpisz select="wyrażenie", gdzie wyrażenie identyfikuje węzeł (lub węzły) dokumentu XML, których szablony powinny być zastosowane. Więcej szczegółów na temat pisania szablonów znajdziesz w rozdziale 3., „Wzorce i wyrażenia XPath”. 3. Na koniec wpisz />, aby zakończyć instrukcję (rysunki 2.30 i 2.31).
Wskazówki
Jeśli nie określisz atrybutu select w punkcie 2. powyższej procedury, procesor będzie szukał szablonu dla każdego z bieżących elementów potomnych węzła i będzie te szablony stosował.
Rysunek 2.32. Dzięki przeniesieniu instrukcji przetwarzania niepolskich nazw do osobnego szablonu jestem w stanie korzystać z tej samej logiki i wyświetlać te same informacje dwukrotnie, bez konieczności pisania ponownie tych samych instrukcji
Kiedy stosujesz element xsl:apply-templates, a nie ma żadnego szablonu odpowiadającego bieżącemu węzłowi, automatycznie stosowany jest szablon wbudowany w procesor XSLT. W przypadku węzła głównego lub węzła elementu wyszukiwany jest odpowiadający szablon dla każdego węzła potomnego. W przypadku węzła atrybutu lub węzła tekstowego wyświetlana jest wartość węzła w postaci tekstu. Element xsl:apply-templates może zawierać element xsl:sort (patrz podrozdział „Sortowanie węzłów przed przetworzeniem”). Jeśli jeszcze tego nie zrobiłeś, polecam pobranie i przeglądanie przykładowych plików. Informacje o tym, skąd można pobrać przykłady, zostały zamieszczone we wstępie do książki.
53
Tworzenie i stosowanie szablonów
Jeśli w swoim arkuszu stylów posiadasz wiele szablonów, kolejność elementów xsl:apply-templates determinuje kolejność przetwarzania szablonów.
Rozdział 2.
54
Wzorce i wyrażenia XPath
3
Rozdział 3. Wzorce i wyrażenia XPath W poprzednim rozdziale, „XSLT”, nauczyłeś się tworzyć i stosować szablony do przekształcania dokumentów XML. Tworząc szablon, używasz wzorca do określenia węzłów, do których dany szablon może być zastosowany. Gdy stosujesz szablon, korzystasz z wyrażenia w celu wskazania zbioru węzłów, które powinny zostać przetworzone. Do pisania wzorców oraz wyrażeń stosuje się składnię języka ścieżek XML (ang. XML Path Language), czyli XPath. XPath jest językiem służącym do wybierania węzłów i zbioru węzłów poprzez określanie ścieżek ich lokalizacji w dokumencie XML. W tym rozdziale szczegółowo opisano sposób definiowania ścieżek lokalizacji XPath.
Podobnie jak XSLT, XQuery wykorzystuje wyrażenia XPath. Język XQuery został omówiony w rozdziale 16. Uwaga! Najbardziej aktualna wersja języka ścieżek XML to XPath 2.0. Ponieważ jednak wersja 1.0 jest wciąż szerzej stosowana, te dwa rozdziały omawiają właśnie XPath 1.0. Wersja XPath 2.0 została szczegółowo opisana w rozdziale 15.
55
Wzorce i wyrażenia XPath
XPath możesz również stosować w innych instrukcjach XSLT w celu dalszego przetworzenia danego zbioru węzłów, aby zwracane były wartości zamiast węzłów. Język XPath posiada wbudowane funkcje umożliwiające wykonywanie obliczeń matematycznych, przetwarzanie ciągów znaków oraz testowanie warunków w dokumencie XML. Funkcje te zostały opisane szczegółowo w kolejnym rozdziale, „Funkcje XPath”.
Rozdział 3.
Lokalizowanie węzłów U podstaw języka XPath leży możliwość stosowania ścieżek lokalizacji (ang. location paths) w celu odwoływania się do węzła lub zbioru węzłów. Pamiętaj, że węzeł (ang. node) to indywidualny fragment dokumentu XML (taki jak element, atrybut lub pewna zawartość tekstowa). Ścieżka lokalizacji wykorzystuje relacje do opisania lokalizacji węzła lub zbioru węzłów w stosunku do danego węzła. Podczas tłumaczenia ścieżek lokalizacji XPath postrzega wszystkie dokumenty XML jako struktury drzewa. Konkretnie dokumenty te traktowane są jako drzewa węzłów, które są hierarchiczną strukturą węzłów (rysunki 3.1 i 3.2).
Lokalizowanie węzłów
Drzewo węzłów XML W drzewie węzłów XML wszystko jest węzłem, a każdy węzeł jest w pewien sposób spokrewniony z innymi. Na szczycie drzewa węzłów znajduje się węzeł główny (ang. root node). Węzeł główny, czyli inaczej węzeł dokumentu (ang. document node), może posiadać dowolną liczbę węzłów-dzieci (ang. child nodes). Dla tych węzłów-dzieci węzeł główny jest węzłem-rodzicem (ang. parent node). Węzły-dzieci same mogą posiadać dowolną liczbę swoich węzłów-dzieci itd. Węzły-dzieci mające tego samego rodzica zwane są rodzeństwem (ang. sibling nodes). Węzły potomne (ang. descendant nodes) to węzły-dzieci danego węzła, dzieci jego dzieci itd. Węzły-przodkowie (ang. ancestor nodes) to węzłyrodzice danego węzła, węzły dziadkowie itd. Za pomocą ścieżek lokalizacji XPath możesz uzyskać dostęp do dowolnego z tych węzłów z poziomu innego węzła, znając po prostu relacje pomiędzy nimi.
Ścieżki lokalizacji Są dwa rodzaje ścieżek lokalizacji: względne i bezwzględne. Względna ścieżka lokalizacji (ang. relative location path) składa się z sekwencji kroków lokalizacji rozdzielonych znakiem / (prawym ukośnikiem). Każdy krok określa węzeł lub zbiór węzłów względem węzła bieżącego. Następnie każdy węzeł w tym zbiorze jest używany jako węzeł bieżący dla kolejnego kroku itd.
56
Rysunek 3.1. Oto reprezentacja drzewa węzłów XML dla pojedynczego cudu starożytności i jego elementów-dzieci. Element cuda_starozytnosci jest korzeniem lub węzłem dokumentu. W tym przykładzie element cuda_starozytnosci ma jeden węzeł-dziecko, którym jest element cud. Z kolei element cuda_starozytnosci jest dla elementu cud węzłem-rodzicem. Element cud posiada siedem węzłów-dzieci (nazwa, nazwa, lokalizacja, wysokosc, historia, obrazek_glowny oraz zrodlo), z których każdy jest dla drugiego rodzeństwem. Ponadto każdy z nich jest węzłem potomnym węzła cud oraz węzła cuda_starozytnosci. W konsekwencji węzeł cud oraz węzeł cuda_starozytnosci są węzłami-przodkami dla tych siedmiu dzieci
Wzorce i wyrażenia XPath Bezwzględna ścieżka lokalizacji (ang. absolute location path) składa się ze znaku / (prawego ukośnika), po którym opcjonalnie może następować względna ścieżka lokalizacji. Znak / sam w sobie oznacza węzeł główny dokumentu XML. Jeśli po nim następuje względna ścieżka lokalizacji, wtedy jest to ścieżka lokalizacji rozpoczynająca się w węźle głównym. Wybór pomiędzy zastosowaniem względnej i bezwzględnej ścieżki lokalizacji zależy od okoliczności. Względne ścieżki lokalizacji są najbardziej powszechnie stosowane, ponieważ generują wynikowy zbiór węzłów w relacji do bieżącego węzła, a jest to zazwyczaj kontekst, w którym pracujesz. Rysunek 3.2. To jest faktyczny dokument źródłowy XML, którego reprezentacja w postaci drzewa węzłów XML została przedstawiona na rysunku 3.1. Jak już wspomniano, element cuda_starozytnosci jest korzeniem lub węzłem dokumentu, a także rodzicem elementu cud. Idąc dalej w dół dokumentu XML, element cud jest rodzicem siedmiu dzieci (nazwa, nazwa, lokalizacja, wysokosc, historia, obrazek_glowny oraz zrodlo). Wszystkie siedem węzłów-dzieci elementu cud stanowi rodzeństwo. Węzły te oraz sam element cud są potomkami węzła cuda_starozytnosci. To z kolei czyni węzeł cuda_starozytnosci przodkiem elementu cud i wszystkich jego dzieci
Korzystanie z węzłów zlokalizowanych Stosując ścieżki lokalizacji, często będziesz wykorzystywał węzły lub zbiory węzłów zlokalizowanych jako kontenery dla innych elementów do przetworzenia. Innym razem będziesz potrzebował znać wartość danego węzła. W języku XPath istnieje siedem różnych typów węzłów: węzeł główny (który zawsze jest tylko jeden), węzły elementów, węzły tekstowe, węzły atrybutów, węzły komentarzy, węzły instrukcji przetwarzania oraz węzły przestrzeni nazw. Dla każdego typu węzła istnieje określony sposób pozyskiwania jego wartości. W niektórych przypadkach wartość jest częścią samego węzła, w innych wartość ta jest oparta na wartości węzłów potomnych.
Składnia języka XPath została zainspirowana po części przez popularny system plików „ścieżka/plik”. Węzłem bieżącym (ang. current node) jest element lub węzeł, który jest w danym momencie przetwarzany. Węzeł kontekstowy (ang. context node) znajduje się tam, gdzie rozpoczyna się adres ścieżki lokalizacji XPath. W większości przypadków terminy te są zamienne, więc w całej książce będę posługiwał się terminem węzeł bieżący.
57
Lokalizowanie węzłów
Wskazówki
Rozdział 3.
Ustalanie bieżącego węzła Gdy procesor XSLT przetwarza arkusz stylów, działa na jednym węźle naraz. Dzięki zastosowaniu elementów xsl:template, xsl:apply-templates oraz xsl:for-each procesor wie, które (i kiedy) części dokumentu XML przetwarzać. Przygotowując arkusz stylów XSLT, często będziesz określał, co ma być przetwarzane w następnej kolejności w stosunku do tego, co jest przetwarzane aktualnie. Węzeł, który jest przetwarzany w danym momencie, zwany jest węzłem bieżącym. Oczywiście zanim będziesz mógł odwołać się do węzła bieżącego, musisz wiedzieć, jak go zidentyfikować (rysunek 3.3).
Aby zidentyfikować węzeł bieżący: 1. Domyślnie węzeł bieżący to ten, który jest określony bieżącym szablonem. Innymi słowy, węzeł bieżący jest identyfikowany atrybutem match tego szablonu.
Ustalanie bieżącego węzła
2. Jeśli występuje jakaś instrukcja xsl:apply-templates, węzłem bieżącym staje się węzeł, który pasuje do danego szablonu (czyli węzeł określony atrybutem match instrukcji xsl:template). Kiedy procesor „wraca” z tej instrukcji xsl:template, bieżącym węzłem staje się na powrót ten odpowiadający atrybutowi match pierwotnego szablonu. 3. Jeśli występuje jakaś instrukcja xsl:for-each, bieżący węzeł zmienia się na ten, który jest określony atrybutem select. Po wykonaniu instrukcji xsl:for-each bieżącym węzłem staje się na powrót ten, który był węzłem bieżącym przed przetworzeniem danej instrukcji.
Wskazówka Instrukcja xsl:apply-templates może przetwarzać więcej niż jeden węzeł w przypadku, gdy wyrażenie select zwraca zbiór węzłów. W takiej sytuacji każdy z węzłów tego zbioru staje się kolejno węzłem bieżącym.
58
Rysunek 3.3. W punkcie 1 bieżącym węzłem jest / (węzeł główny), tak jak to zostało określone za pomocą instrukcji xsl:template match="/". Kiedy procesor dociera do punktu 1a, bieżącym węzłem staje się pierwszy element cud w elemencie cuda_starozytnosci, a przetwarzanie przeskakuje do punktu 2, gdzie dany element cud jest przetwarzany zgodnie z instrukcją xsl:template match="cud". Następnie, gdy procesor dociera do punktu 2a, element nazwa z atrybutem jezyk różnym niż polski staje się węzłem bieżącym, a przetwarzanie przeskakuje do punktu 3, gdzie ten element nazwa staje się węzłem bieżącym i jest przetwarzany zgodnie z instrukcją xsl:template match="nazwa[@jezyk!='polski']". Kiedy ta instrukcja zostanie zakończona, procesor „wraca” z szablonu nazwa zastosowanego w punkcie 2a. Bieżącym węzłem staje się ponownie element cud do czasu, gdy procesor zakończy szablon cud i powróci do szablonu głównego. Po przetworzeniu pierwszego elementu cud drugi element cud staje się węzłem bieżącym i tak kolejno, aż zostaną przetworzone wszystkie elementy cud (i każdy z nich po kolei będzie węzłem bieżącym)
Wzorce i wyrażenia XPath
Odwoływanie się do węzła bieżącego Jeśli aktualnie przetwarzasz węzeł, który chcesz wykorzystać w atrybucie select, możesz zastosować pewien skrót. Zamiast odwoływać się do węzła bieżącego za pomocą ścieżki lokalizacji od węzła głównego, dużo łatwiej jest zastosować skrót bieżącego węzła (rysunek 3.4).
Aby odwołać się do bieżącego węzła: W ścieżce lokalizacji wpisz . (pojedynczą kropkę). Rysunek 3.4. Bieżącym węzłem będzie zawartość pewnego elementu nazwa, którego argument jezyk to polski. Wybór konkretnego elementu nazwa zależy do tego, w którym momencie procedury przetwarzania znajduje się procesor
Wskazówki Nie zawsze będziesz chciał wybrać cały zbiór węzłów. Aby uzyskać podzbiór bieżącego węzła, możesz zastosować test zwany predykatem (ang. predicate). Więcej szczegółów na ten temat znajdziesz w podrozdziale „Warunkowe wybieranie węzłów”. W predykacie możesz również zastosować . (skrót bieżącego węzła), aby odwołać się do węzła kontekstowego. Węzeł kontekstowy to węzeł, który jest testowany przez predykat.
Odwoływanie się do węzła bieżącego
Rysunek 3.5. Pogrubiony tekst jest wyświetlany, kiedy procesor wykonuje instrukcję w szablonie cud. W obrębie samego szablonu () instrukcja zwraca wartość bieżącego węzła za każdym razem, kiedy jest wywoływana
59
Rozdział 3.
Wybieranie dzieci danego węzła Jeśli bieżący węzeł zawiera element (lub elementy), który chcesz wykorzystać, możesz zastosować skrót w celu odwołania się do danych węzłów-dzieci (rysunek 3.6). Zamiast podawać ścieżkę lokalizacji od węzła głównego, możesz odwołać się do wymaganych węzłów-dzieci, po prostu podając ich nazwy (rysunek 3.7).
Aby wybrać dziecko węzła: 1. Upewnij się, że wiesz, który węzeł jest bieżący (patrz podrozdział „Ustalanie bieżącego węzła”) oraz że interesujący Cię węzeł lub zbiór węzłów jest dzieckiem tego bieżącego węzła. (Właściwie możesz odwołać się do dowolnego potomka. Patrz punkt 3. poniżej). 2. Następnie w żądanej ścieżce lokalizacji wpisz nazwa_dziecka, aby odwołać się do elementu-dziecka (lub elementów) w obrębie bieżącego węzła.
Rysunek 3.6. Oto fragment dokumentu XML. Zawarty w nim element historia posiada cztery elementy-dzieci: rok_wybudowania, rok_zniszczenia, sposob_zniszczenia oraz dzieje
Wybieranie dzieci danego węzła
3. W razie potrzeby możesz jeszcze dodać krok /nazwa_wnuka, aby odwołać się do węzła lub zbioru węzłów zawartych w zbiorze dziecka wybranego w punkcie 2. Umożliwi Ci to dalsze zagłębienie się w drzewo XML i odwoływanie się do bardziej zagnieżdżonych zbiorów węzłów. 4. Powtarzaj punkt 3. do momentu, aż dojdziesz do węzła (lub węzłów) na wymaganym poziomie.
Wskazówki Oczywiście zanim będziesz mógł wskazać węzły-dzieci, musisz wiedzieć, który element jest bieżący. Więcej szczegółów na ten temat znajdziesz w podrozdziale „Ustalanie bieżącego węzła”. Wpisz * (gwiazdkę), aby wybrać wszystkie dzieci bieżącego węzła. Element xsl:text jest wykorzystywany w celu dodania bezpośredniego tekstu do pliku wyjściowego. Element ten nie może zawierać żadnych innych elementów. Jest on często stosowany do obsługi znaków specjalnych, takich jak & lub >, lub do kontrolowania białych znaków. Zwróć uwagę, że element ten został użyty do wstawienia spacji pomiędzy elementami rok_wybudowania/rok_zniszczenia a ich elementami potomnymi era na rysunku 3.7. Bez tego nie byłoby odstępu pomiędzy rokiem i erą w wyświetlonym pliku wyjściowym.
60
Rysunek 3.7. Kiedy procesor dociera do szablonu historia, element historia staje się węzłem bieżącym. Dzięki temu procesor może teraz bezpośrednio adresować jego węzły-dzieci w ścieżkach lokalizacji XPath. Zwróć uwagę na użycie znaku @ odwołującego się do atrybutu era. Zostało to omówione bardziej szczegółowo w podrozdziale „Wybieranie atrybutów węzła”
Wzorce i wyrażenia XPath
Wybieranie rodzica lub rodzeństwa danego węzła Ponownie, jeśli relacja pomiędzy bieżącym węzłem (patrz podrozdział „Ustalanie bieżącego węzła”) a węzłem wymaganym jest wystarczająco oczywista (rysunek 3.8), dużo łatwiej jest zastosować skrót, niż napisać kompletną ścieżkę bezwzględną rozpoczynającą się w węźle głównym.
Aby wybrać rodzica węzła:
Rysunek 3.8. Zwróć uwagę, że elementy historia i nazwa są elementami-dziećmi elementu cud (są zawarte bezpośrednio w tym elemencie) i dlatego są dla siebie rodzeństwem
1. Upewnij się, że wiesz, który węzeł jest bieżący oraz że interesujący Cię zbiór węzłów jest rodzicem tego bieżącego węzła. 2. Wpisz .. (dwie kropki), aby wybrać rodzica bieżącego węzła.
Aby wybrać rodzeństwo węzła:
Rysunek 3.9. Kiedy procesor przechodzi do szablonu historia, węzeł historia staje się węzłem bieżącym. Jeśli teraz chcę się odnieść do elementu nazwa (który jest rodzeństwem), muszę zastosować ścieżkę .., aby przejść poziom wyżej (do elementu cud, który jest rodzicem obu tych elementów). Następnie muszę zastosować znak /, aby przejść do innego dziecka i wpisać nazwa w celu określenia tego elementu-dziecka
2. W razie potrzeby wpisz /nazwa_siostrzenicy, gdzie nazwa_siostrzenicy odnosi się do węzła, który jest dzieckiem rodzeństwa bieżącego węzła. 3. Jeśli to konieczne, powtarzaj czynność z punktu 2. aby wybrać prasiostrzenicę itd.
Wskazówki Instrukcja .. jest często łączona z atrybutem węzła w celu odnalezienia atrybutu węzła-rodzica (../@atrybut). Więcej informacji na ten temat znajdziesz w kolejnym podrozdziale, „Wybieranie atrybutów węzła”. W ścieżce lokalizacji możesz również zastosować gwiazdkę, jako znak wieloznaczny. Przykładowo ścieżka ../* spowodowałaby wybranie wszystkich elementów-dzieci rodzica danego węzła bieżącego, wraz z samym węzłem bieżącym.
Rysunek 3.10. Chociaż procesor znajduje się teraz w szablonie historia (a nie w szablonie cud), dopóki wskazuję tę nową relację, dopóty dokument jest wyświetlany poprawnie
61
Wybieranie rodzica lub rodzeństwa węzła
1. Po dotarciu do rodzica węzła w punkcie 2. powyższej procedury wpisz /nazwa_rodzeństwa, gdzie nazwa_rodzeństwa odnosi się do nazwy pożądanego węzła. To rodzeństwo jest więc dzieckiem rodzica bieżącego węzła, ale samo nie jest bieżącym węzłem (rysunek 3.9).
Rozdział 3.
Wybieranie atrybutów węzła Jeśli chcesz, aby ścieżka lokalizacji zwróciła atrybut węzła zamiast samego węzła, możesz w tym celu zastosować znak @ (rysunek 3.11).
Aby wybrać atrybut (lub atrybuty) węzła: 1. Wpisz ścieżkę lokalizacji danego węzła, wykorzystując techniki opisane w tym rozdziale. 2. Następnie wpisz /@, aby wskazać, że interesują Cię atrybuty bieżącego węzła. 3. Na koniec wpisz atrybut, aby określić nazwę interesującego Cię atrybutu. Możesz też wpisać * (gwiazdkę) jako znak wieloznaczny, w celu wybrania wszystkich atrybutów danego węzła.
Rysunek 3.11. Aby pozyskać atrybut (lub atrybuty) określonego elementu, zastosuj nazwę tego elementu, po której wpisz znak @ oraz nazwę wymaganego atrybutu. W tym przykładzie żądany jest atrybut era elementu rok_wybudowania
Wybieranie atrybutów węzła
Wskazówka Znak @ jest czasem określany mianem osi atrybutu (ang. attribute axis). W języku XPath oś to zbiór węzłów powiązanych z węzłem bieżącym. Oprócz węzła atrybutu w specyfikacji XPath zostało zdefiniowanych jeszcze 12 innych osi. Są to: przodek (ang. ancestor), przodek lub bieżący (ang. ancestor-or-self), dziecko (ang. child), potomek (ang. descendant), potomek lub bieżący (ang. descendant-or-self), następujący (ang. following), następujący siostrzany (ang. following-sibling), przestrzeń nazw (ang. namespace), rodzić (ang. parent), poprzedzający (ang. preceding), poprzedzający siostrzany (ang. preceding-sibling) oraz bieżący (ang. self). Każda z tych dodatkowych osi określa „kierunek” względem bieżącego węzła i reprezentuje odpowiadający mu zbiór węzłów. Ponieważ wszystkie osie mogą być reprezentowane skrótami (szczególnie tymi omówionymi w tym rozdziale), same osie są rzadko używane w praktyce.
Rysunek 3.12. Wyświetlana jest zawartość atrybutu era (z elementu rok_wybudowania)
Rysunek 3.13. W powyższym fragmencie dokumentu HTML wyświetlane są informacje z atrybutu era wraz z elementem rok_wybudowania
62
Wzorce i wyrażenia XPath
Warunkowe wybieranie węzłów Wybranie całego zbioru węzłów z dokumentu XML nie zawsze jest wystarczająco precyzyjne (rysunek 3.14). W XPath możesz tworzyć wyrażenia logiczne (ang. boolean expressions), zwane predykatami (ang. predicates), które umożliwiają testowanie warunków i na podstawie otrzymanych wyników pozwalają wybrać określony podzbiór danego zbioru węzłów (rysunek 3.15).
Rysunek 3.14. Zwróć uwagę, że w tym dokumencie XML element cud może posiadać więcej niż jeden element-dziecko nazwa, a każdy z nich posiada własny atrybut jezyk
Predykaty mogą porównywać wartości, sprawdzać występowanie elementów, wykonywać obliczenia matematyczne i wiele więcej. Do napisania takich (i bardziej skomplikowanych) warunków możesz wykorzystać funkcje. Więcej szczegółów na ten temat znajdziesz w rozdziale 4., „Funkcje XPath”.
Aby wybrać węzły warunkowo: 1. Stosując się do instrukcji zawartych w tym rozdziale, utwórz ścieżkę lokalizacji do węzła, który zawiera wymagany podzbiór. 2. Wpisz [ (lewy nawias kwadratowy znajdujący się na prawo od litery P na klawiaturze). Rysunek 3.15. Ten szablon zostanie zastosowany tylko do tych elementów nazwa, dla których atrybut jezyk nie równa się polski
3. Wpisz wyrażenie identyfikujące dany podzbiór. 4. Następnie wpisz ] (prawy nawias kwadratowy), aby zakończyć predykat.
Jak wspomniano powyżej, predykaty nie służą jedynie do porównywania. Wystarczy napisać [@jezyk], aby wybrać wszystkie elementy bieżącego węzła posiadające atrybut jezyk (bez względu na wartość tego atrybutu). Możesz użyć kilku predykatów, aby bardziej zawęzić swoje wyszukiwanie. Instrukcja
nazwa[@jezyk='polski'][position() = last()] spowoduje wybranie tych elementów nazwa, których atrybut jezyk równa się polski i są
ostatnimi węzłami w zbiorze. Rysunek 3.16. Elementy nazwa napisane w innym języku niż polski są wyświetlane kursywą i ujęte w nawiasy, według instrukcji z szablonu XSLT
W razie potrzeby możesz również po predykacie dodać selektor atrybutu. Aby uzyskać na przykład wszystkie atrybuty ostatniego elementu bieżącego węzła, wpisz [last ()]/@*. Pamiętaj, żeby stosować nawiasy kwadratowe, a nie klamrowe czy okrągłe.
63
Warunkowe wybieranie węzłów
Wskazówki
Rozdział 3.
Tworzenie bezwzględnych ścieżek lokalizacji Wszystkie utworzone przeze mnie dotychczas ścieżki lokalizacji były ścieżkami względnymi, czyli zależącymi od bieżącego węzła. Możesz jednak tworzyć również bezwzględne ścieżki lokalizacji, które nie opierają się na węźle bieżącym (rysunek 3.17). W tym celu pisanie ścieżki do wymaganego węzła należy rozpocząć w węźle głównym.
Aby utworzyć bezwzględną ścieżkę lokalizacji: Wpisz /, aby wskazać, że rozpoczynasz w węźle głównym dokumentu XML. Następnie wpisz korzeń, gdzie korzeń odnosi się do elementu głównego Twojego dokumentu XML. Dalej wpisz /, aby zejść poziom niżej w hierarchii drzewa tego dokumentu XML.
Rysunek 3.17. Zmieniłem zaznaczoną pogrubionym drukiem ścieżkę lokalizacji (wyświetlającą polską nazwę cudu) ze względnej na bezwzględną. Zrobiłem to, dodając /cuda_starozytnosci/cud na początku ścieżki względnej zastosowanej w oryginalnej wersji (select="nazwa[@jezyk='polski']")
Tworzenie bezwzględnych ścieżek lokalizacji
Wpisz kontener, gdzie kontener określa nazwę tego elementu na następnym poziomie, który zawiera element wymagany. Powtarzaj kroki z punktów 3. – 4., aż dojdziesz do rodzica interesującego Cię węzła. Na koniec wpisz /element, gdzie element jest nazwą wymaganego węzła. Teraz możesz zastosować predykat, wybrać atrybut danego węzła lub zrobić obydwie te rzeczy.
Wskazówki
Rysunek 3.18. Zamiast pobrać polską nazwę bieżącego węzła, bezwzględna ścieżka lokalizacji zwraca za każdym razem pierwszy element polskiej nazwy z węzła głównego
Wszystkie opisane wyżej w tym rozdziale koncepcje i skróty związane ze ścieżkami lokalizacji mogą być również zastosowane przy tworzeniu ścieżek bezwzględnych. W dowolnym miejscu ścieżki lokalizacji możesz zastosować * (gwiazdkę), aby wskazać wszystkie elementy na danym poziomie. Możesz pominąć punkty 3. – 5. powyższej procedury, jeśli wymagany element jest elementem-dzieckiem elementu głównego. Niektóre korzyści wynikające ze stosowania ścieżek bezwzględnych zostały opisane w podrozdziale „Lokalizowanie węzłów”. Bądź jednak ostrożny, stosując takie ścieżki, ponieważ zignorowanie węzła bieżącego może powodować nieprzewidziane konsekwencje (rysunek 3.19).
64
Rysunek 3.19. I tu właśnie leży problem. Korzystając z bezwzględnych ścieżek lokalizacji i ignorując bieżący węzeł, upewnij się, że wiesz, co robisz. Możesz nie otrzymać tego, co chciałeś, i wszystko może skończyć się bałaganem
Wzorce i wyrażenia XPath
Wybieranie wszystkich potomków Kiedy musisz wybrać wszystkie potomki konkretnego węzła, przydatny może okazać się podwójny ukośnik // (rysunek 3.21). Podobnie jak większość opisanych w tym rozdziale skrótów, skrót ten możesz zastosować zarówno we względnej, jak i w bezwzględnej ścieżce lokalizacji.
Rysunek 3.20. Wiem, że w tym dokumencie znajdują się elementy zawierające nazwy plików graficznych. Jeśli jednak nie jestem pewien, gdzie się znajdują, i chcę utworzyć listę ich wszystkich, mogę zastosować skrót //, tak jak pokazano na rysunku 3.21
Aby wybrać wszystkie potomki węzła głównego: Wpisz // (podwójny prawy ukośnik).
Aby wybrać wszystkie potomki bieżącego węzła: Wpisz .// (kropka i dwa prawe ukośniki).
Aby wybrać wszystkie potomki dowolnego węzła: 1. Zastosuj opisane w poprzednich rozdziałach techniki, aby uzyskać węzeł, którego potomki Cię interesują. 2. Następnie wpisz // (podwójny prawy ukośnik).
Rysunek 3.21. Zaznaczone pogrubieniem atrybuty select i match zwracają wszystkie węzły, dla których atrybutem jest plik, bez względu na ich położenie w źródłowym dokumencie XML. (Uwaga! Jest to całkowicie inny plik XSLT, który nie został oparty na poprzednich plikach)
1. Stosując opisane w poprzednich podrozdziałach techniki, utwórz ścieżkę do węzła, którego potomki Cię interesują. 2. Wpisz //. 3. Następnie wpisz nazwy elementów potomnych, które Cię interesują.
Wskazówka
Rysunek 3.22. Zwróć uwagę, że wyświetlone zostały tutaj wszystkie nazwy plików z obrazkami zawartych w źródłowym dokumencie XML, bez względu na ich faktyczną lokalizację
Aby dostać się do węzła, którego położenia w danym dokumencie nie znasz (lub nie interesuje Cię to), możesz zastosować następującą technikę. Wyrażenie takie jak //nazwa_elementu wyświetli wszystkie odpowiadające mu w danym dokumencie elementy o nazwie nazwa_elementu, bez względu na ich umiejscowienie.
65
Wybieranie wszystkich potomków
Aby wybrać niektóre potomki dowolnego węzła:
Rozdział 3.
66
Funkcje XPath
4
Rozdział 4. Funkcje XPath W poprzednich dwóch rozdziałach nauczyłeś się korzystać ze ścieżek lokalizacji XPath do wskazywania węzłów i zbiorów węzłów w dokumencie źródłowym XML. W niektórych przypadkach używałem ścieżek lokalizacji do dalszego przetwarzania za pomocą szablonów (xsl:template oraz xsl:apply-templates) lub przy testowaniu warunków (xsl:if oraz xsl:when). W obu tych sytuacjach może się zdarzyć, że nie będziesz potrzebował (lub chciał) korzystać ze wszystkich danych zwracanych ze zbioru węzłów. Za pomocą funkcji XPath możesz stosować dodatkową logikę dla tych zbiorów węzłów, aby zwracały tylko potrzebne Ci dane.
W tym rozdziale zostanie omówionych szczegółowo wiele popularnych funkcji XPath. Oficjalne specyfikacje dla funkcji XPath w wersji 1.0 znajdziesz na stronie organizacji W3C (ang. World Wide Web Consortium): www.w3.org/TR/xpath#corelib. Jak już wcześniej wspomniano, choć najnowszą wersją języka XPath jest specyfikacja 2.0, w tym i poprzednim rozdziale omawiamy szczegółowo XPath w wersji 1.0. Jest to spowodowane tym, że wersja 1.0 jest nadal najpowszechniej stosowaną i wspieraną wersją. Język XPath 2.0 został omówiony szczegółowo w rozdziale 15., a specyfikację najnowszej wersji możesz znaleźć na stronie http://www.w3.org/TR/xpath20/.
67
Funkcje XPath
W innych przypadkach używałem ścieżek lokalizacji do wyodrębnienia zawartości węzła za pomocą instrukcji xsl:value-of. Pamiętaj, że instrukcja xsl:value-of powoduje wyświetlenie wartości ciągu pierwszego węzła ze zbioru węzłów. Dzięki funkcjom XPath możesz w celu modyfikacji końcowego rezultatu przeprowadzić na tym ciągu nawet kilka operacji, zanim ciąg ten zostanie wyświetlony.
Rozdział 4.
Porównywanie dwóch wartości Prawdopodobnie najbardziej typowym testem, który możesz wykonać na ścieżce lokalizacji, jest sprawdzenie, czy jedna wartość jest większa od drugiej (rysunek 4.1). Wynik testu może być następnie użyty do określenia działań, które mają być podjęte. Możesz też po prostu wykorzystać wynikowy zbiór węzłów w swojej transformacji.
Aby porównać dwie wartości:
Porównywanie dwóch wartości
1. Utwórz ścieżkę do pierwszego zbioru węzłów, który chcesz porównać. 2. Następnie wpisz = (równa się), != (nie równa się), > (jest większe niż), >= (jest większe lub równe), < (jest mniejsze niż) lub <= (jest mniejsze lub równe), w zależności od sposobu w jaki chcesz porównać dane wartości.
Rysunek 4.1. W tym przykładzie użyłem warunku w celu bardziej precyzyjnego określenia zbioru węzłów wykorzystywanych w instrukcji xsl:apply-templates. Warunek ten mówi konkretnie, że zastosowane mają być tylko te węzły cud, dla których wysokość jest większa niż 30 m
3. Na koniec wpisz wartość lub ścieżkę do drugiego zbioru węzłów, który chcesz porównać z pierwszym zbiorem węzłów określonym w punkcie 1.
Wskazówki Ten test może być wykorzystany w przetwarzaniu xsl:template oraz xsl:apply-templates, jak również przy testowaniu warunkowym za pomocą xsl:if oraz xsl:when. Jeśli chcesz po prostu sprawdzić, czy dany zbiór węzłów istnieje (bez względu na jego zawartość), pomiń punkty 2. – 3. powyższej procedury. Wartości ciągu i wartości tekstowe w punkcie 3. powinny być ujęte w pojedyncze znaki cudzysłowu. Użyj operatora and (i), aby sprawdzić, czy wszystkie podane warunki są prawdziwe. Użyj operatora or (lub), aby sprawdzić, czy co najmniej jeden z kilku podanych warunków jest prawdziwy. Pozostałe operatory logiczne nie są poprawne. Istnieje również wyrażenie logiczne not (nie), ale jest to funkcja, a nie operator. Więcej szczegółowych informacji na ten temat znajdziesz w podrozdziale „Więcej funkcji języka XPath”.
68
Rysunek 4.2. Zgodnie z arkuszem stylów XSLT przedstawionym na rysunku 4.1, cztery z siedmiu cudów mają wysokość większą niż 30 m, co widać powyżej. Zwróć uwagę, że ten sam warunek wysokości został zastosowany zarówno w sekcji Przegląd, jak i w sekcji Historia
Funkcje XPath
Testowanie pozycji Poza stosowaniem warunków dla ścieżek lokalizacji, możesz również wybierać określony węzeł w danym zbiorze węzłów: pierwszy, drugi lub nawet ostatni.
Aby sprawdzić pozycję węzła: Wpisz position() = n, gdzie n jest liczbą identyfikującą dany węzeł w bieżącym zbiorze węzłów (rysunek 4.3).
Aby znaleźć ostatni węzeł w zbiorze węzłów: Wpisz last(), aby uzyskać ostatni węzeł.
Wskazówki Przy stosowaniu funkcji position() oraz last() nie umieszcza się żadnych elementów w nawiasach. W predykacie (czyli w umieszczonym w nawiasach kwadratowych wyrażeniu logicznym mającym na celu przetestowanie warunku) możesz stosować po prostu parametr n, jako skrót dla funkcji position()=n. Przykładowo instrukcja cud[1] zwróci pierwszy węzeł cud. (Uwaga! Możesz stosować ten skrót w przetwarzaniu szablonów, ale nie w wyrażeniach testujących xsl:if lub xsl:when. Nie można go stosować także w instrukcji xsl:value-of.
Rysunek 4.4. Wynikiem transformacji opartej na szablonie z rysunku 4.3 jest wyświetlenie listy siedmiu cudów świata. Lista ta jest odpowiednio sformatowana: nazwy rozdzielone są przecinkami, a przed ostatnią nazwą pojawił się wyraz „oraz”
69
Testowanie pozycji
Rysunek 4.3. Zastosowałem tutaj funkcje position, aby sformatować zdanie, które wymienia wszystkie cuda. Nazwa cudu wyświetlana jest bez względu na wszystko. Jeśli nazwa znajduje się na ostatniej pozycji, zaraz po niej wyświetlana jest kropka. Jeśli nazwa znajduje się na przedostatniej pozycji (position() = last()–1), po nazwie wyświetlana jest spacja, słowo „oraz” i kolejna spacja. Dla pozostałych pozycji wyświetlane są tylko nazwa i spacja
Rozdział 4.
Mnożenie, dzielenie, dodawanie i odejmowanie W swoich wyrażeniach możesz zawierać proste operacje arytmetyczne. Umożliwi Ci to testowanie bardziej skomplikowanych warunków lub wyświetlanie obliczonych wartości (rysunek 4.5).
Aby pomnożyć, podzielić, dodać lub odjąć:
Mnożenie, dzielenie, dodawanie i odejmowanie
1. Wpisz pierwszy argument. Może być to stała liczbowa, np. 12. Może być to również zbiór węzłów (w takim przypadku stosowana jest wartość ciągu pierwszego węzła). 2. Następnie wpisz jeden z dostępnych operatorów matematycznych: * (dla mnożenia), div (dla dzielenia, ponieważ znak / ma już przypisane inne znaczenie), + (dla dodawania) lub – (dla odejmowania). 3. Na koniec wpisz drugi argument.
Wskazówki Zgodnie z matematyczną zasadą kolejności wykonywania działań, mnożenie i dzielenie jest wykonywane przed dodawaniem i odejmowaniem. Innymi słowy 4+5*3 wynosi 19, a nie 27. Domyślną kolejność działań możesz zmienić, stosując nawiasy. W ten sposób (4+5)*3 faktycznie daje 27.
Rysunek 4.5. Do sekcji Przegląd dodałem nową kolumnę o nazwie Lata przetrwane. Obliczenia matematyczne są dość proste, a skomplikowany element logiki jest objaśniony tutaj: ponieważ wszystkie cuda zostały wybudowane p.n.e., to jeśli zostały zniszczone w n.e. lub nadal stoją, muszę dodać (a nie odjąć) rok_wybudowania i rok_zniszczenia
Do kontrolowania sposobu wyświetlania operacji matematycznych (oraz wszelkich wartości liczbowych) możesz użyć funkcji formatowania liczb (patrz podrozdziały „Formatowanie liczb” i „Zaokrąglanie liczb”). Istnieje jeszcze piąty operator, mod, który służy uzyskiwaniu reszty z dzielenia. Tak więc 20 mod 4 wynosi 0 (ponieważ 20 dzieli się równo przez 4), ale 20 mod 3 wynosi 2, ponieważ 20/3 równa się 6 i reszty 2.
Rysunek 4.6. Jeśli na podstawie tego dokumentu HTML, będącego wynikiem transformacji wykonanej za pomocą arkusza stylów XSLT z rysunku 4.5, przeprowadzisz proste obliczenia matematyczne, zobaczysz, że po upływie kolejnych 260 lat piramida Cheopsa będzie stała dłużej niż wszystkie pozostałe cuda razem wzięte
70
Funkcje XPath
Liczenie węzłów Często zamiast wykonywać na zbiorze węzłów operacje arytmetyczne, będziesz chciał po prostu wiedzieć, ile węzłów znajduje się w danym zbiorze (rysunek 4.7).
Aby policzyć węzły: 1. Wpisz count(. 2. Następnie podaj ścieżkę do zbioru węzłów, który ma być przeliczony. 3. Wpisz ), aby zakończyć funkcję. Rysunek 4.7. W pierwszej funkcji count() użyłem bezwzględnej ścieżki lokalizacji, aby zwrócić liczbę cudów, które zostały zniszczone w wyniku trzęsienia ziemi. W ostatnich dwóch funkcjach count() zastosowałem skrót //, aby zwrócić wszystkie węzły z całego dokumentu odpowiadające danemu wyrażeniu
Wskazówka Ścieżka lokalizacji wskazana w punkcie 2. powyższej procedury może opcjonalnie zawierać predykaty. Zostało to pokazane w dwóch pierwszych wystąpieniach funkcji count() na rysunku 4.7.
Liczenie węzłów
Rysunek 4.8. Zgodnie z arkuszem stylów XSLT z rysunku 4.7, ponad połowa cudów została zniszczona w wyniku trzęsienia ziemi
71
Rozdział 4.
Formatowanie liczb W Xpath działania arytmetyczne są wykonywane z uwzględnieniem obliczeń zmiennoprzecinkowych, co może powodować otrzymywanie dość długich wyników (rysunki 4.9 i 4.10). Na szczęście za pomocą funkcji format-number możesz łatwo kontrolować format wyświetlania liczb.
Aby sformatować liczby:
Rysunek 4.9. Ten fragment kodu powoduje wyświetlenie wysokości w metrach, a następnie przeliczenie wartości na stopy i również jej wyświetlenie
1. Wpisz format-number(. 2. Następnie wpisz wyrażenie zawierające liczbę, która ma być sformatowana.
Formatowanie liczb
3. Dalej wpisz , ' (przecinek, spację i pojedynczy cudzysłów). 4. Następnie wpisz 0 dla każdej cyfry, która powinna pojawiać się zawsze, oraz # dla każdej cyfry, która powinna pojawiać się tylko wtedy, kiedy nie jest równa zero. W razie potrzeby wpisz . (kropkę), aby oddzielić część całkowitą liczby od części ułamkowej.1 5. Na koniec wpisz ') (pojedynczy cudzysłów oraz prawy nawias okrągły), aby zakończyć wzorzec liczby oraz funkcję (rysunek 4.11).
Rysunek 4.10. Pamiętaj, że w działaniach arytmetycznych uwzględniane są obliczenia zmiennoprzecinkowe, co — jak już wspomniano — może powodować wyświetlanie dość długich liczb
Wskazówki Zastosuj wzorzec ###0.00, aby wyświetlić co najmniej jedną liczbę danej cyfry oraz dokładnie dwie cyfry w części ułamkowej tej cyfry (podobnie jak przy podawaniu kwoty w złotych i groszach: 269,40). W przypadku wzorca #000.0# liczby z dziesiętnymi częściami po przecinku (ale nie z setnymi) nie będą posiadały ostatniego zera, np. 269.4.
Rysunek 4.11. Formatowana liczba to ta widoczna na rysunku 4.10. Teraz zostanie ona sformatowana w taki sposób, aby zawierała co najmniej jedną cyfrę przed przecinkiem (chociaż liczby nigdy nie są przycinane od lewej) i dokładnie jedną cyfrę po przecinku
Liczby ujemne są domyślnie poprzedzane znakiem minus (–). Jeśli chcesz, żeby były raczej ujmowane w nawiasy, dodaj ;(0) po kroku 4. powyższej procedury.
Rysunek 4.12. Teraz liczby wyglądają znacznie lepiej bez tylu cyfr po przecinku
1
Liczby formatowane są zgodnie z notacją stosowaną w krajach anglosaskich — przyp. red.
72
Funkcje XPath
Zaokrąglanie liczb Rysunek 4.13. Z tego fragmentu kodu XML wynika, że obrazek ma 528 pikseli szerokości i 349 pikseli wysokości
W języku XPath dostępne są trzy funkcje służące zaokrąglaniu liczb w danych źródłowych (rysunek 4.13). Możesz zaokrąglać do najbliższej liczby całkowitej (round), zawsze zaokrąglać w górę (ceiling) lub zawsze zaokrąglać w dół (floor).
Aby zaokrąglić liczby: 1. Wpisz ceiling(, floor( lub round( w zależności od tego, czy chcesz zaokrąglić w górę, w dół lub do najbliższej liczby całkowitej. 2. Następnie wpisz wyrażenie zawierające liczbę, która ma być sformatowana. 3. Wreszcie wpisz ), aby zakończyć funkcję.
Wskazówka Jeśli przy stosowaniu funkcji format-number() (patrz podrozdział „Formatowanie liczb”) zostały usunięte jakieś miejsca po przecinku, procesor XSLT automatycznie zaokrągli wyświetlaną liczbę wynikową.
Rysunek 4.15. Po zastosowaniu funkcji ceiling() języka XPath wartości atrybutów szerokosc i wysokosc stanowią teraz połowę ich oryginalnych wartości
Rysunek 4.16. Obrazki ilustrujące cuda są teraz wyświetlane w rozmiarze stanowiącym połowę rozmiaru pierwotnego: 264×175 pikseli
73
Zaokrąglanie liczb
Rysunek 4.14. Chciałbym, żeby obrazek był wyświetlany w rozmiarze o połowę mniejszym niż rozmiar pierwotny. Ponieważ atrybuty szerokosc i wysokosc akceptują tylko liczby całkowite, zastosowałem funkcję ceiling() w celu zaokrąglenia wyniku dzielenia do najbliższej wartości całkowitej
Rozdział 4.
Wyodrębnianie podciągów Przy przetwarzaniu dokumentu XML w celu uzyskania pliku do wyświetlenia często użyteczne jest zagłębienie się nieco w określony ciąg i wyodrębnienie tylko tego fragmentu, który jest potrzebny. W tym przykładzie (rysunek 4.17) podzieliłem element lokalizacja na miasto i kraj, stosując w tym celu przecinek.
Aby wyodrębnić podciąg umieszczony pomiędzy określonymi znakami: 1. Wpisz substring-after( lub substring-before( w zależności od tego, czy chcesz wyodrębnić część ciągu występującą przed (ang. before) lub po (ang. after) określonym znaku.
Wyodrębnianie podciągów
2. Następnie wpisz wyrażenie zawierające ciąg źródłowy. Rysunek 4.17. W dokumencie XML element lokalizacja 3. Dalej wpisz , c, gdzie c jest znakiem występującym po podciągu lub przed podciągiem, który ma być wyodrębniony. 4. Wreszcie wpisz ), aby zakończyć funkcję.
zawiera zarówno nazwę miasta, jak i kraju. W tym przykładzie rozdzieliłem element lokalizacja na dwie wyświetlane osobno informacje o mieście i kraju. Dla miasta wykorzystałem ciąg znaków przed przecinkiem, a dla kraju ciąg po przecinku
Wskazówka Możesz również wyodrębnić podciąg ze środka danego ciągu, jeśli znasz pozycję pierwszego znaku tego podciągu oraz całkowitą liczbę znaków następujących po pierwszym znaku. W tym celu możesz użyć funkcji substring(s,f,n), gdzie s jest wyrażeniem zawierającym ciąg źródłowy, f jest pozycją pierwszego znaku wyodrębnianego podciągu, a n jest całkowitą liczbą wymaganych znaków.
Rysunek 4.18. Po zastosowaniu arkusza stylów XSLT z rysunku 4.17 każde miasto i każdy kraj danego cudu są wyświetlane w sekcji Przegląd w osobnych kolumnach
74
Funkcje XPath
Zmienianie wielkości znaków w ciągu Podczas obróbki tekstu często istotne jest, aby mieć możliwość zmiany wielkości liter z małych na wielkie i z powrotem.
Aby zamienić w ciągu małe litery na wielkie: 1. Wpisz translate(. Rysunek 4.19. Zamierzam w sekcji Historia wyświetlać nazwę nad obrazkiem. Ponadto nazwa ta ma w całości być zapisana wielkimi literami
2. Dalej wpisz wyrażenie zawierające ciąg źródłowy. 3. Następnie wpisz , 'aąbcćdeęfghijklłmnoópqrsśtuvwxyzżź'
4. Teraz wpisz , 'AĄBCĆDEĘFGHIJKLŁMNOÓPQRSŚTUVWXYZŻŹ'
(czyli przecinek, spacja oraz ciąg zawierający litery, które mają zastąpić znaki z punktu 3.). 5. Wreszcie wpisz ), aby zakończyć funkcję (rysunek 4.19).
Wskazówki Jeśli chcesz zmienić wielkie litery na małe, zamień punkt 3. z 4. w powyższej procedurze. Rysunek 4.20. Dzięki arkuszowi stylów XSLT z rysunku 4.19 nazwa każdego cudu jest teraz zapisana wielkimi literami jako nagłówek w sekcji Historia
Możesz użyć funkcji translate() w celu przekształcenia dowolnego w znaku w jakikolwiek inny dowolny znak. W punkcie 3. powyższej procedury wpisz litery, które mają być zmienione, a litery mające je zastąpić podaj w punkcie 4. W wersji 2.0 języka XPath dostępnych jest znacznie więcej funkcji do modyfikacji ciągów znaków, w tym funkcja przeznaczona do zamiany małych liter na wielkie i odwrotnie.
75
Zmienianie wielkości znaków w ciągu
(czyli przecinek, spacja oraz ciąg zawierający litery do zmiany).
Rozdział 4.
Sumowanie wartości W celu podsumowania wszystkich wartości węzłów z danego zbioru węzłów możesz wykorzystać funkcję sum() języka XPath (rysunek 4.21). Funkcja ta świetnie sprawdza się przy wyświetlaniu danych w tabelach i kolumnach (rysunek 4.22).
Aby podsumować wartości: 1. Wpisz sum(. 2. Następnie podaj ścieżkę do zbioru węzłów, którego węzły mają być podsumowane. 3. Wreszcie wpisz ), aby zakończyć funkcję.
Sumowanie wartości
Wskazówka Jak pokazano w przykładzie na rysunku 4.21, możesz łączyć wiele różnych funkcji XPath w tym samym pliku wynikowym. Umożliwia to tworzenie ściśle określonych przekształceń danych źródłowych XML.
Rysunek 4.21. Utworzyłem dodatkowy wiersz, w którym wyświetlana ma być średnia wysokość wszystkich cudów. W celu znalezienia tej średniej zastosowałem funkcję sum(), żeby zsumować wszystkie wartości węzłów wysokosc. Następnie podzieliłem uzyskaną wartość przez liczbę cudów, dla których wysokość nie jest równa zero. Na koniec sformatowałem plik wynikowy tak, aby wyświetlana była jedna cyfra po przecinku
Rysunek 4.22. Średnia wysokość wszystkich cudów to prawie 20 pięter
76
Funkcje XPath
Więcej funkcji języka XPath
Rysunek 4.23. Aby zakończyć przygotowywanie pliku wyjściowego dla dokumentu wonders-master.xml, dodałem element dzieje do sekcji Historia
Poza funkcjami XPath omówionymi do tej pory w tym rozdziale, istnieje jeszcze kilka dodatkowych funkcji, które możesz uznać za przydatne. Pełną listę funkcji języka XPath 1.0 znajdziesz na stronie www.w3.org/TR/xpath#corelib.
Funkcje węzłów: Funkcja name(zbiór_węzłów) zwraca pierwszy węzeł w określonym zbiorze węzłów, a funkcja name() zwraca nazwę bieżącego węzła. Funkcja id(id_ciągu) zwraca wszystkie elementy, których identyfikator jest równy id_ciągu.
Funkcje ciągów:
Funkcja string-length(ciąg1) zwraca liczbę znaków w ciąg1, a funkcja string-length() zwraca liczbę znaków w bieżącym węźle.
Rysunek 4.24. Oto zrzut ekranu z finalnego pliku wyjściowego HTML po wykonaniu wszystkich prac w XSLT i XPath!
Funkcja normalize-space(ciąg1) zwraca ciąg1 z usuniętymi wszystkimi początkowymi i końcowymi białymi znakami oraz z sekwencjami białych znaków zastąpionymi pojedynczą spacją. Funkcja normalize-space() wykonuje to samo działanie na bieżącym węźle.
Funkcje logiczne: Funkcja not(wyrażenie) zwraca wartość „prawda”, jeśli wyrażenie jest fałszywe, lub wartość „fałsz”, jeśli wyrażenie jest prawdziwe. Funkcja | (pionowa kreska, często zlokalizowana na klawiaturze nad znakiem \). Chociaż technicznie nie jest to funkcja, instrukcja ta jest stosowana do łączenia dwóch zestawów węzłów w jeden.
Wskazówka Chociaż język XPath 1.0 pozostaje najbardziej powszechnie stosowaną wersją, zapewnia dość ograniczony zestaw funkcji. Jeśli naprawdę potrzebujesz jakiejś określonej funkcjonalności, możesz zapoznać się ze specyfikacją XPath 2.0, która oferuje obszerniejszy zestaw funkcji i operatorów, Specyfikację tę znajdziesz na stronie http://www.w3.org/TR/xpath20/.
77
Więcej funkcji języka XPath
Funkcja contains(ciąg1, ciąg2) zwraca wartość „prawda” (ang. true), jeśli ciąg1 zawiera ciąg2. W przeciwnym razie zwraca wartość „fałsz” (ang. false).
Rozdział 4.
78
XSL-FO
5
Rozdział 5. XSL-FO [RS1] Jak wspomniano w rozdziale 2., XSL (ang. eXtensible Stylesheet Language — rozszerzalny język arkuszy stylów) stanowił pierwotnie pojedynczą specyfikację dla formatowania dokumentów XML. Jednak przed zakończeniem prac nad tą specyfikacją W3C podzieliło XSL na dwie części: XSLT (dla transformacji; ang. for Transformations) oraz XSL-FO (dla formatowania obiektów; ang. for Formatting Objects). XSLT zostało omówione w trzech poprzednich rozdziałach. W tym rozdziale zajmiemy się specyfikacją XSL-FO. XSL-FO jest zasadniczo językiem składu. Umożliwia łatwe definiowanie układów stron, w tym ustawianie marginesów i odstępów między wierszami, tworzenie nagłówków, stopek i marginaliów, a także przypisów, przypisów końcowych, zawartości kolumnowej, okładek oraz spisów treści.
Aby przetestować działanie przykładów lub napisać własne dokumenty XSL-FO, będziesz potrzebował procesora XSL-FO. Jeśli jeszcze takiego nie masz, możesz zapoznać się z listą dostępnych opcji, którą znajdziesz w dodatku A. W roku 2001 XSL-FO 1.0 stało się oficjalną rekomendacją W3C, która została zaktualizowana w roku 2006 do wersji 1.1. W marcu 2008 r. opublikowany został projekt roboczy wersji 2.0. Więcej informacji na ten temat znajdziesz na stronie grupy roboczej XSL organizacji W3C: http://www.w3.org/Style/XSL.
79
XSL-FO
XSL-FO jest językiem znaczników opartym na XML-u i został zaprojektowany do formatowania danych XML. Zobaczyłeś już, w jaki sposób XSLT może formatować dane XML i przekształcać je w dokumenty HTML. XSL-FO został jednak specjalnie przystosowany do formatowania danych XML w celu uzyskania plików wyjściowych do wydruku. Wykorzystane w tym rozdziale przykłady XSL-FO będą generować możliwy do wydrukowania plik wyjściowy w formacie Adobe PDF.
Rozdział 5.
Dwie części dokumentu XSL-FO Dokument XSL-FO jest plikiem wyłącznie tekstowym zawierającym znaczniki i zawartość literalną XSL-FO. Za pomocą tego dokumentu procesor XSL-FO może wygenerować jeden z wielu różnych nadających się do wydruku plików wyjściowych, takich jak: PDF (ang. Portable Document Format), MIF (ang. Maker Interchange Format), PS (ang. PostScript) itd.
Dwie części dokumentu XSL-FO
Każdy dokument XSL-FO (rysunek 5.1) można podzielić na dwie części. Obie z nich zawierają się w elemencie najwyższego poziomu fo:root. Pierwsza część opisuje ogólną strukturę (ang. overall structure) finalnego pliku wyjściowego. Odbywa się to poprzez wykorzystanie elementów i atrybutów XSL-FO w celu ustawienia szerokości/wysokości strony, marginesów oraz fiszek, a także w celu identyfikowania różnych szablonów stron (takich jak szablony dla okładki, spisu treści, stron parzystych i nieparzystych oraz samej zawartości). Dotycząca ogólnej struktury część dokumentu XSL-FO zawiera element fo:layout-master-set, który jest kontenerem dla jednego lub kilku elementów-dzieci fo:simple-page-master. Te elementy-dzieci opisują szablony stron, które są podzielone na pięć elementów regionu, takich jak fo:region-body wykorzystywany dla regionu głównej zawartości szablonu strony. Druga część dokumentu XSL-FO zawiera i formatuje zawartość strony (ang. page content) finalnego pliku wyjściowego. W tej części znajdują się dwa elementy fo:page-sequence, z których każdy odpowiada określonemu elementowi fo:simple-page-master zdefiniowanemu w dotyczącej ogólnej struktury części danego dokumentu. Każda sekwencja strony (ang. page sequence) zawiera jeden element-dziecko fo:flow dla każdego z regionów zdefiniowanych w elemencie fo:simple-page-master. Wreszcie każdy element flow posiada co najmniej jeden element-dziecko fo:block, a każdy element block zawiera faktyczną zawartość strony.
80
Rysunek 5.1. W tym fragmencie pliku XSL-FO część dotycząca ogólnej struktury definiuje zawartość strony za pomocą elementów page-width, page-height oraz margin. Część dotycząca zawartości strony zawiera bezpośredni tekst „Siedem cudów starożytnego świata” (sformatowany czcionką o wielkości 28 punktów) oraz dodatkowy tekst o Herodocie (wyjustowany i zapisany czcionką o wielkości 14 punktów)
Rysunek 5.2. Dokument XSL-FO z rysunku 5.1 po przetworzeniu generuje finalny dokument wyjściowy. W tym przypadku utworzyłem plik PDF (którego górny fragment widać powyżej) z dokumentu XSL-FO
XSL-FO
Tworzenie dokumentu XSL-FO XSL-FO to język znaczników XML, więc dokumenty XSL-FO są pisane z wykorzystaniem składni XML. Pierwszy wiersz dokumentu XSL-FO to standardowa deklaracja XML, a dokument musi zawierać pojedynczy element główny (rysunek 5.3). Dokumenty XSL-FO to pliki wyłącznie tekstowe, zapisywane z rozszerzeniem .fo.
Aby utworzyć dokument XSL-FO: 1. Wpisz .
3. Następnie wpisz xmlns:fo="http://www.w3.org/ 1999/XSL/Format", aby zadeklarować przestrzeń nazw z prefiksem fo:. 4. Wreszcie wpisz >, aby zamknąć znacznik. 5. Wpisz , aby rozpocząć część dokumentu dotyczącą ogólnej struktury. 6. Wpisz , gdzie nazwa_strony jest nazwą szablonu strony użytą w punkcie 10. 7. Wpisz , aby zadeklarować, że ta strona nadrzędna (ang. page master) będzie posiadać zawartość w regionie zawartości głównej (ang. body region). 8. Wpisz .
Rysunek 5.4. Oto górny fragment pliku PDF, który został wygenerowany w wyniku przetworzenia dokumentu XSL-FO z rysunku 5.3
9. Wpisz . 10. Wpisz , gdzie nazwa_strony jest tą samą nazwą, która została zdefiniowana w punkcie 6. Rozpoczyna to część dokumentu dotyczącą zawartości strony. 11. Wpisz . Tutaj xsl-region-body odnosi się do regionu zawartości głównej zadeklarowanego w punkcie 7. 12. Za pomocą elementów fo:block wprowadź zawartość strony dla finalnego dokumentu wyjściowego. 13. Wpisz . 14. Wpisz . 15. Wpisz , aby zakończyć dokument XSL-FO.
81
Tworzenie dokumentu XSL-FO
Rysunek 5.3. To jest kompletny dokument XSL-FO. Szablon strony został nazwany „cuda” i posiada region zawartości głównej mieszczący tekst „Kolos Rodyjski”. Zwróć uwagę, że dokument XSL-FO może mieć bardzo niewielką zawartość, ale i tak będzie wymagał części dotyczącej ogólnej struktury oraz części poświęconej zawartości strony
2. Wpisz
Rozdział 5.
Tworzenie i stylizowanie bloków zawartości strony W dokumentach XSL-FO zawartość, taka jak akapity i nagłówki, mieści się w blokach (ang. blocks). Procesor XSL-FO pobiera zawartość każdego bloku, aplikuje jego właściwości stylu, a następnie układa w stos jeden blok po drugim, aby wygenerować finalny plik wyjściowy.
Aby utworzyć blok zawartości strony: 1. Jako element-dziecko elementu fo:flow wpisz , aby zamknąć znacznik.
Tworzenie i stylizowanie bloków
4. Wpisz literalną zawartość strony, którą jest wartość tekstowa tego elementu fo:block. 5. Na koniec wpisz .
Aby nadać styl blokowi zawartości strony: Jako atrybut elementu fo:block wpisz nazwę właściwości stylu i jego wartość. Na przykład:
Rysunek 5.5. W tym fragmencie do dokumentu XSL-FO pokazanego na rysunku 5.3 dodałem więcej zawartości strony, wykorzystując kolejne elementy fo:block. Do każdego z bloków zastosowałem również kilka właściwości stylu
font-size="rozmiar_czcionki", gdzie rozmiar_czcionki może być określony w calach (in), punktach (pt) lub innych jednostkach. Może to być rozmiar bezwzględny (np. small [mały], x-large [duży] itd.) lub względny (np. larger [większy] lub smaller [mniejszy]). Dopuszczalne są
także procenty podane za pomocą wartości liczbowej lub jednostki em. Użycie parametru inherit (dziedzicz) powoduje zastosowanie wartości font-size elementu-rodzica.
space-after="odstęp_po", gdzie odstęp_po może być długością wyrażoną w calach (in), punktach (pt) lub innych jednostkach. Użycie parametru inherit powoduje
zastosowanie wartości atrybutu elementu-rodzica.
Wskazówka Element fo:block może posiadać elementy-dzieci fo:block, a wszelkie dziedziczone właściwości stylu elementu-rodzica zostaną zastosowane do każdego dziecka. Jeśli dziedziczenie nie odbędzie się automatycznie, zastosowanie wartości elementu-rodzica jest możliwe po ustawieniu parametru inherit dla wartości stylu elementu-dziecka.
82
Rysunek 5.6. Po przetworzeniu dokumentu XSL-FO każdy element fo:block ma odpowiedni styl dzięki swoim właściwościom stylu, a w finalnym pliku wyjściowym został ułożony w stos wraz z pozostałymi elementami
Wygląda znajomo? Wiele właściwości stylu elementu fo:block jest tożsamych z właściwościami w języku CSS (ang. Cascading Style Sheets). Jeśli znasz już język CSS, wiedza ta będzie miała również zastosowanie przy stylizacji plików wyjściowych XSL-FO.
XSL-FO
Dodawanie obrazków Element fo:block może, poza zawartością tekstową, zawierać również obrazki. Identyfikujący obrazek element fo:external-graphic może także posiadać zdefiniowane własne właściwości stylu (rysunek 5.7).
Aby dodać obrazek:
Rysunek 5.7. Dodałem do dokumentu XSL-FO obrazek colossus.jpg. W finalnym pliku wyjściowym obrazek ten będzie wyśrodkowany, będzie miał grubą ramkę z grzbietem i wysokość 3,5 cala. Postanowiłem również wyśrodkować nazwę cudu
Do typowych właściwości stylu elementu fo:external-graphic należą: content-height="wysokość_zawartości", gdzie wysokość_zawartości może być ustawiona na auto, co oznacza zastosowanie rzeczywistej wysokości obrazka. Atrybut ten może również przyjmować wartość scale-to-fit, co oznacza skalowanie obrazka w celu dopasowania go do przestrzeni bloku dostarczonego przez dokument XSL-FO. Możliwe jest także określenie długości w calach (in), punktach (pt) lub innych jednostkach. Dopuszczalne są także procenty podane za pomocą wartości liczbowej lub jednostki em. Użycie parametru inherit powoduje zastosowanie wartości content-height elementu-rodzica. Zwróć uwagę, że kiedy ustawiona jest właściwość content-height, ale nie jest zdefiniowana właściwość content-width (szerokość zawartości), obrazek jest skalowany proporcjonalnie. border-style="styl_ramki", gdzie styl_ramki może mieć wartość none (brak) lub hidden (ukryta), co powoduje, że ramka nie jest wyświetlana. Inne dopuszczalne wartości to dotted (przerywana z kropek), dashed (przerywana z kresek), solid (ciągła), double (podwójna), groove (żłobiona), ridge (dekoracyjna), inset (wklęsła) oraz outset (wypukła). Każda z tych wartości odnosi się do określonego wizualnego stylu ramki. Użycie parametru inherit powoduje zastosowanie właściwości border-style elementu-rodzica. border-width="grubość_ramki", gdzie grubość_ramki może przyjmować wartość thin (cienka), medium (średnia) lub thick (gruba). Każda kolejna z tych wartości powoduje ustawienie coraz większej grubości ramki. Dopuszczalne jest też podawanie długości w calach (in), punktach (pt) oraz innych jednostkach. Użycie parametru inherit powoduje zastosowanie właściwości border-width elementu-rodzica.
83
Dodawanie obrazków
Rysunek 5.8. Obrazek colossus.jpg jest traktowany jak każda inna zawartość umieszczona w bloku. Jest więc układany w stos w odpowiedniej kolejności, a jego style są stosowane do finalnego pliku wyjściowego. (W tym przypadku obrazek jest wyśrodkowany, a po nim następuje odstęp o wysokości 0,2 cala)
1. Jako element-dziecko elementu fo:block wpisz , aby zamknąć element.
Rozdział 5.
Definiowanie szablonu strony Głównym elementem dokumentu XSL-FO jest fo:root. Jak już wcześniej wspomniano, składa się on z dwóch części: pierwsza definiuje ogólną strukturę finalnego pliku wyjściowego, a druga definiuje zawartość strony tego pliku. W poprzednich dwóch podrozdziałach skoncentrowałem się na tej części dokumentu XSL-FO, która dotyczy zawartości strony. Teraz zajmiemy się ogólną strukturą. Część dotycząca ogólnej struktury zawarta jest w pojedynczym elemencie fo:layout-master-set, który posiada co najmniej jeden element-dziecko fo:simple-page-master. Elementy te definiują szablony stron, w których wyświetlana jest zawartość strony.
Rysunek 5.9. Element fo:simple-page-master wykorzystuje atrybut do zdefiniowania szablonu strony o nazwie „cuda”. Poprzez ustawienie właściwości stylu atrybutów elementu fo:simple-page-master zdefiniowałem, że szablon strony „cuda” jest szeroki Aby zdefiniować zawartość strony: na 8,5 cala, wysoki na 11 cali i posiada jednocalowy Jako atrybut elementu fo:simple-page-master wpisz margines u góry, po prawej, u dołu i po lewej
nazwę właściwości stylu oraz jego wartość, która ma być zastosowana (rysunek 5.9). Na przykład:
Definiowanie szablonu strony
page-width="szerokość_strony", gdzie szerokość_strony może być długością podawaną w calach (in), punktach (pt) lub innych jednostkach. Wartość auto (wartość domyślna) oznacza, że szerokość
strony jest ustalana przez procesor XSL-FO. Z kolei wartość indefinite (nieokreślona) oznacza, że szerokość strony jest determinowana przez rozmiar zawartości strony. page-height="wysokość_strony", gdzie wysokość_ strony posiada te same opcje co atrybut page-width. margin="szerokość_marginesu", gdzie szerokość_marginesu jest długością podawaną w calach (in), punktach (pt) lub innych jednostkach.
Wskazówka Właściwości skrócone (ang. shorthand properties) to właściwości stylu, które definiują więcej niż jedną podwłaściwość za pomocą pojedynczego atrybutu i jego wartości. Przykładowo określenie właściwości margin w rzeczywistości definiuje podwłaściwości margin-top (margines górny), margin-right (margines prawy), margin-bottom (margines dolny) oraz margin-left (margines lewy). Wymienione w poprzednim podrozdziale atrybuty border-style oraz border-width są również właściwościami skróconymi, które definiują podwłaściwości -top, -right, -bottom oraz -left.
84
Rysunek 5.10. W przeciwieństwie do przykładu PDF pokazanego na rysunku 5.8, tutaj zawartość strony nie zbliża się do górnej i lewej krawędzi strony. Zamiast tego mamy z każdego brzegu jednocalowy margines
XSL-FO
Tworzenie nagłówka szablonu strony Jak dotąd używałem jedynie regionu zawartości głównej szablonu strony definiowanego elementem fo:regionbody. Definiować można jednak jeszcze cztery inne regiony szablonu strony, które odpowiadają nagłówkowi, stopce oraz lewym i prawym fiszkom.
Aby utworzyć strukturę dla nagłówka: Rysunek 5.11. Nagłówek (fo:region-before) ma zdefiniowaną wysokość o wartości 1 cala. Aby uniknąć nachodzenia na siebie zawartości (patrz punkt „Wskazówka” w tym podrozdziale), część główna (fo:region-body) musi posiadać jednocalowy margines. Ponadto, z uwagi na ustawienie tego marginesu, usunięte zostały ustawienia marginesów z szablonu strony (fo:simple-page-master)
1. Po elemencie fo:region-body wpisz
4. Na koniec wpisz />, aby zamknąć element.
Aby zdefiniować zawartość strony dla nagłówka: 1. Zlokalizuj element fo:page-sequence, którego atrybut master-reference równy jest atrybutowi master-name z punktu 1. poprzedniej procedury. Jako element-dziecko tego elementu wpisz
Rysunek 5.12. Zawartość strony dla nagłówka jest zdefiniowana w elemencie . Jest to element-dziecko elementu fo:page-sequence, którego atrybut master-reference jest równy „cuda”
2. Następnie wpisz flow-name="xsl-region-before">. (xsl-region-before odnosi się do regionu nagłówka zdefiniowanego przez element fo:region-before). 3. Napisz elementy fo:block, aby zdefiniować zawartość strony dla swojego nagłówka. 4. Na koniec wpisz .
Wskazówka Chociaż definiowany osobno, region nagłówka (a także region stopki i regiony prawych i lewych fiszek) jest częścią regionu zawartości głównej. W konsekwencji wartość atrybutu margin regionu zawartości głównej musi być równa (lub większa) wartości atrybutu extent regionu nagłówka. Jeśli będzie inaczej, zawartość główna będzie zachodzić na nagłówek. Rysunek 5.13. Zawartość nagłówka („Siedem cudów starożytnego świata”) jest wyświetlana czcionką o wielkości 18 punktów. Tekst został wyśrodkowany, a linia obramowania jest ciągła, o średniej grubości, i umieszczona pod tekstem (obramowanie dolne)
85
Tworzenie nagłówka szablonu strony
3. Zdefiniuj dla tego regionu odpowiednie atrybuty właściwości stylu, takie jak background (tło) oraz border (ramka).
Rozdział 5.
Tworzenie dokumentów XSL-FO za pomocą XSLT Pamiętaj, że język XSL-FO został zaprojektowany do formatowania dokumentów XML, a nie bezpośredniego tekstu, co pokazywałem do tej pory. Pamiętaj również, że XSL było pierwotnie jedną specyfikacją, która została podzielona na dwie części: XSLT oraz XSL-FO. Przez ponowne połączenie tych dwóch języków będziesz najpierw przekształcał dane źródłowe XML (za pomocą XSLT), a następnie będziesz formatował przekształconą zawartość (za pomocą XSL-FO) w celu uzyskania finalnego dokumentu wyjściowego do publikacji.
Jak połączyć XSLT z XSL-FO: 1. Zamiast zaczynać od dokumentu XSL-FO, rozpocznij od dokumentu XSLT (rysunek 5.14). Szczegółowe informacje na ten temat znajdziesz w części II, „XSLT”.
Rysunek 5.14. Tutaj korzystam z pliku XSLT, aby wygenerować dokument XSL-FO pokazany na rysunkach 5.11 i 5.12. Wygenerowany dokument XSL-FO będzie zawierał wszystkie cuda, nie tylko Kolosa Rodyjskiego. Plik XSLT z tego przykładu pojawia się również w dwóch kolejnych przykładach
Tworzenie dokumentów XSL-FO
2. W obrębie elementu xsl:stylesheet wpisz xmlns:fo="http://www.w3.org/1999/XSL/Format",
aby zadeklarować przestrzeń nazw XSL-FO. 3. Wpisz , aby zdefiniować format XML dla atrybutu method pliku wyjściowego (i — dla lepszej czytelności — zastosować wcięcie w tekście [indent="yes"] dla tego pliku wyjściowegoXML). 4. Utwórz szablon główny (), który będzie zawierał całe drzewo dokumentu XSL-FO rozpoczynające się od jego elementu głównego . 5. Na koniec wykorzystaj elementy XSLT, takie jak xsl:apply-templates (rysunek 5.15), aby wygenerować zawartość strony XSL-FO. Te elementy XSLT będą następnie wywoływać elementy xsl:template za pomocą elementów xsl:value-of (rysunek 5.16).
Rysunek 5.15. W szablonach stron dokumentu XSL-FO (tam, gdzie wprowadzana jest zawartość strony), zamiast wpisywać bezpośredni tekst, korzystam z elementu xsl:apply-templates XSLT. Wywołuje on w kolejności alfabetycznej szablon nazwa dla każdego cudu z nazwą pisaną w języku polskim
Wskazówka W wyniku przetwarzania tego dokumentu XSLT generowany jest plik wyjściowy w postaci dokumentu XSL-FO. Możesz następnie przetworzyć uzyskany dokument XSL-FO i wygenerować finalny plik wyjściowy do publikacji. Niektóre procesory XSLT/XSL-FO umożliwiają nawet za pomocą pojedynczego polecenia przechodzenie bezpośrednio od dokumentu XSLT, przez XSL-FO, aż do finalnego pliku wyjściowego.
86
Rysunek 5.16. W tym fragmencie szablonu nazwa arkusza XSLT utworzony został blok XSL-FO zawierający nazwę cudu. Rozmiar czcionki to 24 punkty, tekst jest wyśrodkowany, a odstęp po tekście wynosi 0,2 cala. To samo formatowanie zastosowałem wobec Kolosa Rodyjskiego w poprzednich rozdziałach
XSL-FO
Wstawianie podziałów stron
Rysunek 5.17. Ten fragment arkusza stylów XSLT pokazuje, że podział strony będzie wstawiany przed każdym blokiem wyświetlającym nazwy cudów. Dalsza część tego kodu zamieszczona została w następnym przykładzie.
Przykład XSLT z poprzedniego podrozdziału generuje dokument XSL-FO, który z kolei generuje finalny plik wyjściowy. Jak możesz sobie wyobrazić (lub jak udało Ci się podejrzeć w plikach z przykładami), finalny plik wyjściowy liczy kilka stron długości i nie ma żadnych logicznych podziałów stron.
Aby wstawić podział strony Wpisz break-before="page" jako atrybut elementu fo:block. Powoduje to wstawienie w finalnym pliku wyjściowym podziału strony przed zawartością danego bloku (rysunek 5.17). Jeśli Twój finalny plik wyjściowy posiada wiele stron, możesz dodać elementy XSL-FO, aby w stopce ponumerować strony (rysunek 5.18).
Aby ponumerować każdą stronę w stopce:
2. Aby skonfigurować zawartość strony dla stopki, wartością atrybutu w punkcie 2. drugiej z procedur opisanych w podrozdziale „Tworzenie nagłówka szablonu strony” powinna być wartość "xsl-region-after". (xsl-region-after odnosi się do regionu stopki zdefiniowanego przez element fo:region-after w punkcie 1.). 3. Na koniec w bloku zawartości strony dla stopki wpisz , co spowoduje wyświetlenie numeru bieżącej strony.
Wskazówki
Rysunek 5.19. W wyniku przetworzenia XSLT na XSL-FO i dalej na format PDF otrzymaliśmy siedmiostronicowy dokument z każdym cudem opisanym na osobnej stronie oraz numeracją stron w stopce
Właściwość stylu break-before (podział strony przed) może również przyjmować inne wartości, takie jak: auto (ustawienie domyślne), gdzie nie jest wymuszany żaden podział, even-page lub odd-page, gdzie podział strony generowany jest, odpowiednio: tylko dla stron parzystych lub nieparzystych, inherit, gdzie wykorzystywana jest wartość break-before elementu-rodzica, oraz column. Ta ostatnia wartość została omówiona w kolejnym podrozdziale, „Wyświetlanie zawartości strony w kolumnach”. Istnieje również właściwość stylu break-after (podział strony po), która działa tak samo jak break-before z tą różnicą, że podział strony jest wstawiany po danym elemencie.
87
Wstawianie podziałów stron
Rysunek 5.18. Ten fragment kodu XSL-FO w szablonie XSLT odpowiada za wyświetlanie w stopce bezpośrednio wpisanego tekstu „Strona”, po którym następuje numer bieżącej strony
1. Aby stworzyć strukturę dla stopki, elementem-dzieckiem w punkcie 1. pierwszej z procedur opisanych w podrozdziale „Tworzenie nagłówka szablonu strony” powinien być element
Rozdział 5.
Wyświetlanie zawartości strony w kolumnach Jedną z wbudowanych funkcji typograficznych XSL-FO jest możliwość definiowania kolumn, w których wyświetlana ma być zawartość strony.
Aby wyświetlić zawartość strony w kolumnach:
Wyświetlanie zawartości strony w kolumnach
1. Jako atrybut elementu regionu wpisz column-count= "liczba_kolumn", gdzie liczba_kolumn to liczba kolumn, które mają być zastosowane w finalnym pliku wyjściowym dla danego regionu (rysunek 5.20).
Rysunek 5.20. Region zawartości głównej szablonu strony o nazwie „cuda” będzie wyświetlany w dwóch kolumnach. Plik XSLT z tego przykładu pojawia się również w dwóch kolejnych przykładach
2. W obrębie regionu określonego w punkcie 1. wpisz span="all" jako atrybut wybranego bloku, którego nie chcesz wyświetlać w układzie kolumnowym (rysunek 5.21). 3. W obrębie regionu określonego w punkcie 1. wpisz, według potrzeb: break-before="column" lub Rysunek 5.21. Ten element bloku będzie zawierał break-after="column" jako atrybut wybranego nazwę cudu i obrazek. Wyświetlany będzie na bloku, dla którego ma być wygenerowany podział szerokości wszystkich kolumn kolumnowy (rysunek 5.22).
Wskazówki Kolejnym atrybutem właściwości stylu dla kolumn jest column-gap, który definiuje szerokość odstępu pomiędzy kolumnami. Wartością tego atrybutu może być długość podana w calach (in), punktach (pt) lub innych jednostkach. Dopuszczalne są także procenty podawane za pomocą wartości liczbowej lub jednostki em. Umieszczenie podziału kolumnowego w ostatnim bloku na ostatniej stronie finalnego pliku wyjściowego może generować niezamierzoną pustą stronę (po stronie, która powinna być ostatnia). Możesz uniknąć tego problemu, nie umieszczając tego atrybutu w ostatnim bloku. Jednym ze sposobów na to jest zastosowanie elementu xsl:if z elementem xsl:attribute, aby dodać atrybut break-after="column" tylko w przedostatnim bloku. (Dodałem tę poprawkę w następnej grupie przykładowych plików XSLT).
88
Rysunek 5.22. Dodałem atrybut break-after="column" do bloku wyświetlającego dzieje cudu
Rysunek 5.23. Teraz dokument PDF wyświetla tekst opisu w dwóch kolumnach, a obrazek (oraz nazwa cudu niewidoczna na przykładzie) rozciąga się na obie kolumny
XSL-FO
Dodawanie szablonu nowej strony W podrozdziale „Definiowanie szablonu strony” zdefiniowałem szablon strony, którego używałem dla moich finalnych plików wyjściowych we wszystkich dotychczasowych przykładach. Teraz chcę utworzyć dla pliku wyjściowego okładkę o innym układzie ogólnym oraz innej zawartości. Rysunek 5.24. Ten nowy szablon strony będzie okładką naszego dokumentu PDF. Nazwałem go „cuda_okładka”
Aby dodać nowy szablon strony: 1. Wpisz , aby zamknąć znacznik. 5. Wpisz , aby zadeklarować, że dana strona nadrzędna (ang. page master) będzie posiadać zawartość w regionie zawartości głównej, oraz żeby dodać wszelkie niezbędne właściwości stylu dla tego regionu. 6. Dodaj elementy deklaracji pozostałych regionów (patrz podrozdział „Tworzenie nagłówka szablonu strony”). 7. Na koniec wpisz .
Aby zdefiniować zawartość strony dla nowego szablonu strony: 1. W dokumencie XSL-FO, w części dotyczącej zawartości strony, wpisz , gdzie nazwa_strony jest nazwą szablonu strony z punktu 2. powyższej procedury (rysunek 5.25). 2. Wpisz , aby utworzyć kontener dla bloków zawartości regionu zawartości głównej. 3. Wpisz bloki zawartości strony dla tego regionu. 4. Wpisz , aby zakończyć ten element. Rysunek 5.26. Okładka wykorzystuje inny szablon strony, który nie zawiera nagłówka oraz stopki
5. Powtórz czynności z punktów 3. i 4. dla pozostałych regionów zdefiniowanych w punkcie 6. powyższej procedury. 6. Na koniec wpisz .
89
Dodawanie szablonu nowej strony
Rysunek 5.25. Początkowa wersja okładki pokazana została na rysunkach 5.1 i 5.2
Rozdział 5.
90
DTD
III
Część III DTD
Rozdział 6.
Tworzenie dokumentów DTD
Rozdział 7.
Encje i notacje w dokumentach DTD
Rozdział 8.
Walidacja i używanie DTD
93 109 121
91
Rozdział x.
92
Tworzenie dokumentów DTD
6
Rozdział 6. Tworzenie dokumentów DTD [RS1] W części I tej książki zapoznałeś się z bazową gramatyką XML-a, która określa reguły pisania dokumentów XML. W części II nauczyłeś się przekształcać dokumenty XML do innej postaci, którą w naszym przypadku były pliki HTML. Z kolei w części III dowiesz się, jak zdefiniować niestandardowy język znaczników w XML-u. Aby zdefiniować taki język, musisz najpierw określić jego elementy oraz ich atrybuty, a także zadeklarować, które są wymagane, a które nie. Takie informacje zwane są schematem (ang. schema). Historyk mógłby na przykład utworzyć język CsśML, (fikcyjny) język znaczników cudów starożytnego świata, będący systemem katalogowania danych dotyczących cudów starożytności. CsśML mógłby zawierać takie elementy jak cud, nazwa, rok_wybudowania oraz dzieje.
Istnieją dwa zasadnicze systemy pisania schematów: DTD oraz XML Schema. DTD, czyli definicja typu dokumentu (ang. Document Type Definition), jest starszym ale szeroko stosowanym systemem ze specyficzną i ograniczoną składnią. Kolejne trzy rozdziały poświęcone są pisaniu schematów w stylu DTD. Drugi podstawowy system, XML Schema, został opisany szczegółowo w części IV tej książki. Z różnych powodów możesz preferować jeden lub drugi system (patrz podrozdział „Wady i zalety DTD” w rozdziale 8.).
93
Tworzenie dokumentów DTD
Schematy, chociaż nie są wymagane, są niezwykle istotne dla zachowania spójności dokumentów XML. W rzeczywistości możesz porównać dowolny dokument XML z odpowiadającym mu schematem, aby zweryfikować, czy jest on zgodny z regułami zdefiniowanymi w tym schemacie (patrz rozdział 8.). Jeśli taki dokument XML zostanie uznany za poprawny, oznacza to, że jego dane mają właściwą formę — taką, jaka została określona w schemacie.
Rozdział 6.
Praca z dokumentami DTD
Praca z dokumentami DTD
DTD, czyli definicja typu dokumentu (ang. Document Type Definition), jest zbiorem reguł, które definiują niestandardowy język znaczników w XML-u. DTD w swej istocie po prostu identyfikuje elementy i ich atrybuty. Jeśli dokument XML nie stosuje się do reguł zdefiniowanych przez DTD, nie jest uznawany za poprawny dla tego konkretnego języka niestandardowego. Za pomocą takiego testu walidacji możesz szybko rozpoznać, czy dany dokument XML przestrzega zasad, które zdefiniowałeś dla swojego języka, czy też nie. Jak już wspomniano, XML wykorzystuje te same bloki składowe co HTML: elementy, atrybuty oraz wartości. Elementy są fundamentalnymi jednostkami dokumentu XML (rysunek 6.1). Mogą one przyjmować wartości, posiadać atrybuty oraz zawierać inne elementy. Schemat DTD dla danego języka znaczników niestandardowych będzie definiował listę elementów oraz wszelkich elementów-dzieci, które każdy element może mieć (rysunek 6.2). Będzie też definiował wszelkie atrybuty, które każdy element może posiadać, oraz będzie definiował, czy te elementy i atrybuty są opcjonalne czy wymagane. W ten sposób DTD definiuje prawidłową strukturę języka znaczników niestandardowych, a zatem również dowolny poprawny dokument XML, który jest częścią tego języka. DTD jest dokumentem wyłącznie tekstowym i zwyczajowo jest zapisywany z rozszerzeniem .dtd. Nie jest on dokumentem XML i dlatego nie rozpoczyna się od standardowej deklaracji XML.
Wskazówki Zastosowanie dokumentów DTD jest doskonałym sposobem zapewnienia spójności danych XML udostępnianych różnym osobom i firmom. Przed użyciem dokumentów XML otrzymywanych od innych osób możesz wykorzystywać DTD do sprawdzania, czy dokumenty te mają właściwy format. Do sprawdzenia zgodności dokumentu XML z danym dokumentem DTD będziesz potrzebował edytora XML lub jakiegoś procesora DTD. Szczegółowe informacje na temat tych dwóch typów narzędzi znajdziesz w dodatku A.
94
Rysunek 6.1. Oto jeden z pierwszych dokumentów XML, które napotkałeś w tej książce. Składa się z czterech elementów: elementu głównego o nazwie cud oraz trzech elementów-dzieci (nazwa, lokalizacja i wysokosc)
Rysunek 6.2. Ten fragment kodu DTD definiuje strukturę dokumentu XML pokazanego na rysunku 6.1. Można go odczytać następująco. Element cud zawiera trzy elementy-dzieci: nazwa, lokalizacja i wysokosc. Wszystkie są elementami typu PCDATA. PCDATA zostało omówione szczegółowo w podrozdziale „Definiowanie elementu zawierającego tekst”. Teraz powiem tylko, że PCDATA to po prostu tekst
Tworzenie dokumentów DTD
Definiowanie elementu zawierającego tekst Aby zdefiniować w DTD strukturę własnego języka znaczników niestandardowych, powinieneś zdefiniować strukturę i zawartość elementów, które posiadałby poprawny dokument XML. Wiele elementów w Twoim dokumencie XML będzie zawierać po prostu tekst (rysunek 6.3). O ile element adres może zawierać elementy potomne, takie jak ulica, miasto, wojewodztwo i kod_pocztowy, to już te elementy prawdopodobnie będą zawierać jedynie tekst.
Aby zdefiniować element, który zawiera wyłącznie tekst: 1. Wpisz , aby zakończyć definicję elementu (rysunek 6.4).
Wskazówka Skrótowiec PCDATA (ang. parsed character data) oznacza parsowane dane znakowe i odnosi się do wartości tekstowej elementu. Te dane znakowe będą parsowane lub analizowane przez procesor XML. Tekst (zwany również ciągiem znaków) może być dowolną serią liter, liczb i symboli, np. „Halo”, „Privet Dr. 4” lub „99811”.
Rysunek 6.4. Prawie każdy dokument DTD będzie zawierał elementy, które zostały zdefiniowane jako PCDATA. W tym fragmencie kodu DTD pokazałem wszystkie elementy z rysunku 6.3, które zostały zdefiniowane jako elementy zawierające tekst
Element, który został zdefiniowany tak, aby zawierać PCDATA, nie może zawierać żadnego innego elementu. W języku XML wielkość liter ma znaczenie. Słowo
95
Definiowanie elementu zawierającego tekst
Rysunek 6.3. Zwróć uwagę, że w tej uproszczonej wersji dokumentu głównego XML większość elementów zawiera tekst. (Niektóre z nich zawierają również atrybuty, które zostały omówione w podrozdziale „Na temat atrybutów”). Elementy-dzieci elementu historia również zawierają tekst, przy czym sam element historia tekstu nie zawiera. Elementy zawierające elementy-dzieci zostały omówione w podrozdziale „Definiowanie elementu, który zawiera element-dziecko”
Rozdział 6.
Definiowanie pustego elementu Poza elementami zawierającymi tekst, dokumenty DTD muszą mieć również możliwość definiowania pustych elementów. Jak wspomniano w rozdziale 1., pusty element nie ma żadnej własnej zawartości. Zamiast tego wykorzystuje on atrybuty służące do przechowywania danych (rysunek 6.5).
Aby zdefiniować pusty element: 1. Wpisz
Rysunek 6.5. W tym fragmencie kodu XML elementy obrazek_glowny i zrodlo są elementami pustymi. Nie ma znaczenia, czy wykorzystują one pojedynczy znacznik otwierający/zamykający, czy osobne znaczniki otwierające i zamykające. I tak oba są elementami pustymi
2. Następnie wpisz EMPTY, aby wskazać, że dany element nie będzie posiadał własnej zawartości tekstowej. 3. Wreszcie wpisz >, aby zakończyć definicję elementu (rysunek 6.6).
Wskazówki
Definiowanie pustego elementu
Zwróć uwagę, że wpisując EMPTY, nie używasz nawiasów, tak jak jest to wymagane przy (#PCDATA). Jak już wspomniano, puste elementy będą posiadały atrybuty, które zostały omówione w podrozdziale „Na temat atrybutów”.
96
Rysunek 6.6. Oto fragment DTD definiujący elementy z rysunku 6.5. Definiowanie ich atrybutów zostało omówione w podrozdziale „Na temat atrybutów”
Tworzenie dokumentów DTD
Definiowanie elementu, który zawiera element-dziecko Teraz, kiedy rozumiesz już, jak definiuje się podstawowe elementy XML w DTD, powinieneś nauczyć się definiowania elementów-rodziców, czyli elementów zawierających inne elementy (rysunek 6.7).
Aby zdefiniować element, który ma zawierać element-dziecko: 1. Wpisz , aby zakończyć definicję elementu (rysunek 6.8).
Wskazówki
Rysunek 6.8. Ta definicja DTD określa, że element cuda_starozytnosci może zawierać pojedynczy element-dziecko o nazwie cud, tak jak pokazano na rysunku 6.7. Uwaga! Zawartość elementu cud zależy tylko od jego definicji (a przynajmniej nie wpływa na nią definicja elementu cuda_starożytności)
Znacznik, który został zdefiniowany tak, aby zawierać jeden inny element, nie może zawierać niczego innego poza tym elementem. Nie może on zawierać innych dodatkowych elementów ani tekstu. Element-dziecko może być opcjonalny lub pojawiać się wielokrotnie. Więcej informacji na ten temat znajdziesz w podrozdziale „Definiowanie liczby wystąpień”. Możesz także kontrolować kolejność, w jakiej elementy powinny pojawiać się w dokumencie XML (patrz podrozdział „Definiowanie elementu, który zawiera kilka elementów-dzieci”). Jeśli zdefiniujesz, że dany element zawiera element-dziecko, to dany element musi zawierać wskazany element-dziecko w każdym wystąpieniu w dokumencie XML. Jeżeli tak nie będzie, dokument XML nie zostanie uznany za poprawny.
97
Definiowanie elementu
Rysunek 6.7. W tej uproszczonej wersji dokumentu głównego XML element cuda_starozytnosci zawiera pojedynczy element-dziecko o nazwie cud
Rozdział 6.
Definiowanie elementu, który zawiera kilka elementów-dzieci Często dokument XML zawiera sekwencję elementów-dzieci (rysunek 6.9). W DTD możesz zdefiniować sekwencję elementów-dzieci, które muszą być zawarte w danym elemencie-rodzicu. Taka sekwencja definiuje również kolejność, w jakiej dane elementy-dzieci mają się pojawić.
Aby zdefiniować element zawierający elementy-dzieci: 1. Wpisz
Definiowanie elementu
2. Następnie wpisz (dziecko1, gdzie dziecko1 jest pierwszym elementem, który powinien pojawić się w danym elemencie-rodzicu. 3. Dalej wpisz dziecko2, gdzie dziecko2 jest kolejnym elementem, który powinien pojawić się w danym elemencie-rodzicu. Elementy-dzieci oddzielaj przecinkiem i spacją.
Rysunek 6.9. Element cud posiada wiele elementów-dzieci. Zwróć uwagę, że spora część z tych elementów posiada atrybuty, które zostały omówione szczegółowo w podrozdziale „Na temat atrybutów”
4. Powtarzaj punkt 3. dla wszystkich elementów, które powinny pojawić się w elemencie-rodzicu. 5. Następnie wpisz ), aby zakończyć sekwencję. 6. Wpisz >, aby zakończyć definicję elementu (rysunek 6.10).
Wskazówki Najbardziej istotną rzeczą w sekwencji jest przecinek. Jest to znak rozdzielający elementy (lub grupy elementów) w sekwencji. Nie możesz używać (#PCDATA) w żadnej części sekwencji. Sekwencja musi zawierać jedynie elementy. Elementy zawarte w sekwencji mogą oczywiście zawierać własne elementy-dzieci. Element historia zdefiniowany na rysunku 6.10 zawiera faktycznie cztery indywidualne elementy-dzieci (co widać na rysunku 6.12).
98
Rysunek 6.10. Ta definicja DTD, wykorzystywana do walidacji dokumentu XML z rysunku 6.9, mówi, że element cud musi zawierać każdy z wymienionych elementów w danej kolejności. Nie może też zawierać niczego innego
Tworzenie dokumentów DTD
Definiowanie liczby wystąpień
Rysunek 6.11. Znaki specjalne (zwane również kwantyfikatorami) sprawiają, że dana definicja jest znacznie bardziej elastyczna. Teraz element cuda_starozytnosci musi zawierać co najmniej jeden (lub dowolnie więcej) element cud. Ponadto element cud musi zawierać co najmniej jeden (lub dowolnie więcej) element nazwa, a elementów zrodlo może być dowolna liczba (może ich też nie być w ogóle). Elementy lokalizacja, wysokosc, historia oraz obrazek_glowny muszą pojawić się dokładnie raz (co jest ustawieniem domyślnym)
Aby zdefiniować liczbę wystąpień: 1. W definicji elementu, w części dotyczącej zawartości, wpisz nazwę elementu-dziecka. 2. Następnie wpisz *, aby wskazać, że dany element-dziecko może pojawiać się w definiowanym elemencie-rodzicu tyle razy, ile to konieczne lub nie pojawiać się w ogóle (zero lub kilka razy). Możesz też wpisać +, aby wskazać, że dany element-dziecko musi pojawić się w definiowanym elemencie-rodzicu dowolną liczbę razy, ale co najmniej raz (jeden lub kilka razy). Możesz również wpisać ?, aby wskazać, że dany element-dziecko może pojawić się w definiowanym elemencie-rodzicu nie więcej niż raz lub w ogóle (zero lub jeden raz).
Wskazówki Powtórzmy: * oznacza zero lub kilka razy; + oznacza jeden lub kilka razy; ? oznacza zero lub tylko raz.
Należy pamiętać, że element bez kwantyfikatora musi pojawić się dokładnie jeden raz. Kwantyfikatorów możesz również używać do zdefiniowania liczby wystąpień dla sekwencji (patrz podrozdział „Definiowanie elementu, który zawiera kilka elementów-dzieci”). Nie istnieje żaden specjalny sposób definiowania konkretnej liczby występowania elementu (np. trzy wystąpienia). Jedyny (i dość obszerny) sposób to napisanie: (element, element, element).
99
Definiowanie liczby wystąpień
Rysunek 6.12. Ta definicja elementu historia mówi, że element ten musi zawierać dokładnie jeden element rok_wybudowania i dokładnie jeden element dzieje. Elementy rok_zniszczenia i sposob_zniszczenia mogą być pominięte (lub mogą pojawić się co najwyżej raz)
Jak dotąd element-rodzic mógł zawierać tylko jedną instancję każdego ze swoich elementów-dzieci. Jednak DTD dopuszcza więcej niż tylko jedną instancję elementu-dziecka w dokumencie XML. W DTD istnieją trzy specjalne symbole, które mogą być wykorzystane do zdefiniowania liczby wystąpień elementu-dziecka w elemencie-rodzicu (rysunki 6.11 i 6.12).
Rozdział 6.
Definiowanie wyborów Czasem chcemy, żeby element XML zawierał jedną rzecz lub drugą — do wyboru (rysunek 6.13).
Aby zdefiniować wybory dla zawartości elementu: 1. Wpisz
Rysunek 6.13. Wyobraź sobie, że informacje o cudach starożytności pochodzą z trzech różnych źródeł, a każde źródło ma inną strukturę elementu cud
4. Dalej wpisz dziecko2, gdzie dziecko2, jest drugim elementem, który może się pojawić. 5. Powtórz czynności z punktów 3. – 4. dla każdego dodatkowego wyboru.
Definiowanie wyborów
6. Wpisz ), aby zakończyć listę wyborów. 7. Wpisz >, aby zakończyć definicję elementu (rysunek 6.14).
Wskazówki Możesz dodać kwantyfikator * po punkcie 6. powyższej procedury, aby element mógł mieć dowolną liczbę dowolnych wyborów (patrz podrozdział „Definiowanie liczby wystąpień”). Kiedy kwantyfikator * zostanie zastosowany do listy wyborów, oznacza to, że dany element może zawierać dowolną liczbę indywidualnych wyborów w dowolnej kolejności. W efekcie powoduje to utworzenie nieuporządkowanej listy wyborów. W niektórych przypadkach możesz chcieć, aby element posiadał zarówno zawartość, jak i elementy-dzieci. Nazywa się to zawartością mieszaną (ang. mixed content) i zostało przedstawione na rysunku 6.13. W takiej sytuacji musisz dodać kwantyfikator * w sposób opisany w powyższych wskazówkach. Uwaga! Takiego rozwiązania nie używa się zbyt często podczas pisania własnego języka niestandardowych znaczników. Korzysta się z tego raczej w trakcie pisania dokumentu DTD, aby mógł on obsługiwać wiele dokumentów XML pochodzących z różnych źródeł.
100
Rysunek 6.14. To DTD wykorzystuje wybory, żeby obsłużyć różne struktury elementu cud pokazane na rysunku 6.13. Definicja ta deklaruje, że element cud może mieć zero lub więcej wystąpień będących typami PCDATA elementów nazwa, lokalizacja, kraj lub miasto
Rysunek 6.15. Oto kolejny sposób na napisanie logiki DTD z rysunku 6.12. Tutaj DTD definiuje element historia w taki sposób, że może on zawierać albo elementy rok_wybudowania, rok_zniszczenia, sposob_zniszczenia i dzieje, albo jedynie elementy rok_wybudowania i dzieje
Tworzenie dokumentów DTD
Definiowanie elementu, który ma dowolną zawartość Chociaż DTD nie jest idealne do tworzenia uporządkowanego zestawu reguł, to w takim dokumencie możesz zdefiniować element, który ma dowolną zawartość. Oznacza to, że element ten może zawierać dowolną kombinację elementów i tekstu. Podobnie jak w przypadku zawartości mieszanej, jest to przydatne przy tworzeniu DTD, które ma obsługiwać dokumenty XML pochodzące z różnych źródeł. Dla niemożliwej do przewidzenia struktury elementów może to być jedyny sposób na zdefiniowanie elementów, które znasz i dopuszczasz (rysunek 6.16).
Aby zdefiniować element, który może mieć dowolną zawartość: 1. Wpisz , aby zakończyć definicję elementu (rysunek 6.17).
Wskazówki
Rysunek 6.17. Zamiast do DTD z rysunku 6.14 dodawać definicję nowej struktury elementu lokalizacja, zdefiniowałem, aby ten element mógł zawierać cokolwiek. Nie jest to tak czytelne jak zdefiniowanie konkretnej zawartości dla elementu lokalizacja, ale działa
Korzystając z instrukcji ANY, powinieneś zachować zdrowy rozsądek. Celem dokumentu DTD jest zdefiniowanie reguł dotyczących tego, co mogą, a czego nie mogą zawierać elementy. Jeśli chcesz dopuścić, aby każdy element miał dowolną zawartość, możesz równie dobrze w ogóle zrezygnować z DTD. Dokumenty DTD nie są wymagane. Pomagają po prostu zachować spójność danych. Instrukcja ANY definiuje, że dany element może zawierać dowolną strukturę. Jeśli jednak element ten zawiera elementy-dzieci, te elementy wciąż muszą być zdefiniowane w DTD. Innymi słowy — ANY nie pozwala, aby element zawierał elementy-dzieci, które nie zostały zdefiniowane w DTD. Wszystkie elementy pojawiające się w poprawnym dokumencie XML muszą być i tak zdefiniowane. Każdy element musi być zdefiniowany dokładnie raz (i tylko raz). Nawet jeśli jakiś element może pojawiać się w wielu różnych miejscach poprawnego dokumentu XML, nadal musi być zdefiniowany tylko raz.
101
Definiowanie elementu
Rysunek 6.16. Tutaj do dokumentu XML z rysunku 6.13 dodałem kolejny element cud (z nowego nieoczekiwanego źródła). Ten nowy element cud ma jeszcze inną strukturę. Zwróć uwagę, że w tym nowym elemencie element lokalizacja nie zawiera żadnych typów PCDATA. Jest on raczej elementemrodzicem dla elementów kraj i miasto
Rozdział 6.
Kilka słów o atrybutach Atrybuty są użyteczne przy dostarczaniu dodatkowych danych na temat elementu. Informacje umieszczone w atrybutach raczej opisują zawartość dokumentu XML, a nie są samą zawartością.
Kilka słów o atrybutach
Przykładowo jeśli w dokumencie głównym XML Cuda starożytnego świata element nazwa zawiera atrybut jezyk opisujący język, w którym podana jest zawartość elementu nazwa, można by łatwo zrestrukturyzować dany dokument XML tak, aby ta sama informacja znajdowała się w dwóch indywidualnych elementach-dzieciach. Element nazwa mógłby zawierać dwa elementy: jezyk oraz nazwa_lokalna. Każdy sposób jest dobry, ale zasadniczo najlepsze praktyki sugerują, że elementy lepiej nadają się do przechowywania informacji, które mają być wyświetlane, a atrybuty lepiej sprawdzają się do przechowywania informacji o informacjach. Istnieje ku temu kilka przesłanek. Atrybuty nie mogą opisywać relacji między danymi, tak jak robią to elementy-dzieci, wartości atrybutów nie mogą być w prosty sposób zweryfikowane przez DTD i wreszcie atrybuty nie mogą zawierać kilku wartości, podczas gdy elementy-dzieci mają taką możliwość. Atrybuty są oczywiście często wykorzystywane w pustych elementach, gdzie opisują informacje na temat danego elementu. Są one na przykład często stosowane do przechowywania identyfikatorów, ponieważ atrybuty nie są danymi, ale informacjami na temat tych danych (patrz podrozdział „Definiowanie atrybutów z wartościami unikatowymi”).
Wskazówka Decyzja co do sposobu, w jaki zdecydujesz się opracować swój język XML, powinna być oparta na jego zastosowaniu. Jeśli nie zamierzasz zbyt wiele „robić” z konkretną porcją informacji, wtedy utworzenie jej w formie atrybutu jest w porządku. Jeśli jednak zamierzasz korzystać z tej informacji w bardziej znaczący sposób, wtedy lepszym rozwiązaniem jest umieszczenie jej w postaci zawartości elementu (rysunek 6.18).
102
Rysunek 6.18. Oba fragmenty kodu XML zawierają tę samą informację: posąg Zeusa w Olimpii został zniszczony w roku 426 w wyniku pożaru. Różnica polega na tym, jak te informacje zostały zorganizowane. W pierwszym kodzie 426 jest wartością atrybutu. W drugim kodzie zarówno 426, jak i pożar stanowią zawartość indywidualnych elementów
Tworzenie dokumentów DTD
Definiowanie atrybutów Rysunek 6.19. Ta definicja atrybutu mówi, że element wysokosc może zawierać opcjonalny atrybut jednostka (z uwagi na status #IMPLIED), który zawiera tekst (z uwagi na typ atrybutu CDATA)
Atrybut nie może pojawić się w poprawnym pliku XML dopóty, dopóki nie zostanie zadeklarowany w DTD. Definicja atrybutu składa się z czterech części: nazwy elementu, nazwy atrybutu, typu atrybutu oraz statusu opcjonalnego.
Aby zdefiniować atrybut: 1. Wpisz
Rysunek 6.20. Zgodnie z definicją DTD z rysunku 6.19, wszystkie widoczne na rysunku fragmenty kodu XML są prawidłowe, ponieważ atrybut jednostka jest opcjonalny (#IMPLIED), a jego zawartością może być dowolna kombinacja znaków
3. Dalej wpisz CDATA, aby wskazać, że typem atrybutu jest tekst. W przeciwieństwie do danych typu (#PCDATA), CDATA, czyli dane znakowe, nie będą parsowane przez procesor. 4. Następnie dla opcjonalnego statusu wpisz #IMPLIED, aby wskazać, że w razie potrzeby dany atrybut może być pominięty (rysunek 6.19).
Rysunek 6.21. Ta wersja definicji mówi, że w elemencie wysokosc atrybut jednostka jest wymagany
5. Wreszcie wpisz >, aby zakończyć definicję atrybutu.
Wskazówki Zwróć uwagę, że we wszystkich częściach definicji atrybutu ważna jest wielkość liter. Musisz je wpisywać w takiej samej formie, w jakiej podałem je w przykładach. Wpisanie na przykład #Required nie ma w DTD żadnego znaczenia.
Rysunek 6.22. Są to te same trzy przykłady, które zostały pokazane na rysunku 6.20. Jednak po przeprowadzeniu walidacji względem DTD z rysunku 6.21 tylko ostatnie dwa okazują się poprawne. Pierwszy fragment kodu nie jest prawidłowy, ponieważ element wysokosc nie zawiera atrybutu jednostka
Możesz zdefiniować wszystkie atrybuty dla danego elementu w pojedynczej definicji atrybutu. Przed zakończeniem definicji atrybutu w punkcie 5. powyższej procedury powtarzaj czynności z punktów 2. – 4. dla każdego atrybutu, który dany element powinien posiadać. Jest to najbardziej typowy sposób definiowania wielu atrybutów dla pojedynczego elementu.
103
Definiowanie atrybutów
Możesz też wpisać #REQUIRED, aby wskazać, że dany atrybut nie może być pominięty i musi zawierać jakąś wartość (rysunek 6.21).
Rozdział 6.
Definiowanie wartości domyślnych Zamiast wpisywania instrukcji #REQUIRED lub #IMPLIED w ramach opcjonalnego statusu atrybutu, możesz zdefiniować, aby atrybut ten posiadał wartości domyślne.
Rysunek 6.23. Tym razem dodaję domyślną wartość metr dla atrybutu wysokosc
Aby zdefiniować atrybut z właściwościami domyślnymi: 1. Według punktów 1., 2. i 3. z procedury opisanej w podrozdziale „Definiowanie atrybutów” zdefiniuj nazwę elementu, nazwę atrybutu oraz typ atrybutu.
Definiowanie wartości domyślnych
2. Następnie wpisz "wartość_domyślna" (cudzysłów otwierający i zamykający jest wymagany), gdzie wartość_domyślna będzie wartością tego atrybutu, jeśli żadna inna wartość nie zostanie zdefiniowana w dokumencie XML (rysunek 6.23). Możesz też wpisać #FIXED "wartość_domyślna", gdzie wartość_domyślna będzie wartością tego atrybutu, jeśli żadna wartość nie zostanie w wyraźny sposób zdefiniowana. Ponadto jeśli wartość tego atrybutu zostanie zdefiniowana, to musi ona być równa wartości domyślnej, aby dany dokument XML był poprawny (rysunek 6.25). 3. Wpisz >, aby zakończyć definicję atrybutu.
Wskazówki Jeśli definiujesz atrybut z wartością domyślną, parser XML automatycznie doda tę wartość domyślną, jeżeli atrybut nie zostanie ustawiony w danym dokumencie XML (rysunek 6.24).
Rysunek 6.25. Wartość ustalona może być użyteczna, jeśli chcesz mieć pewność, że dany atrybut będzie miał określoną wartość, bez względu na to, czy faktycznie pojawi się w danym dokumencie XML
Rysunek 6.24. Wszystkie te fragmenty kodu XML są poprawne. Atrybut jednostka może posiadać dowolną wartość, a nawet może zostać pominięty. Jeśli — tak jak w trzecim kodzie — atrybut jednostka zostanie pominięty, parser zachowa się tak, jakby ten atrybut był w rzeczywistości obecny, a jego wartością była stopa
Jeśli definiujesz atrybut z instrukcją #FIXED "wartość_domyślna", wartość atrybutu w dokumencie XML musi być ustawiona na wartość_domyślną, jeżeli jest w ogóle ustawiona. Jeśli atrybut nie jest ustawiony, parser automatycznie ustawi dla niego wartość domyślną (rysunek 6.26). Nie możesz łączyć wartości domyślnej z instrukcją #REQUIRED lub #IMPLIED. W rzeczywistości, skoro wartość domyślna jest już zdefiniowana, status opcjonalny praktycznie nie ma sensu.
104
Rysunek 6.26. Są to te same trzy przykłady, które zostały pokazane na rysunku 6.24. Jednak po przeprowadzeniu walidacji względem definicji DTD pokazanej na rysunku 6.25, środkowy kod nie jest już poprawny. Jeśli dany atrybut zostanie ustalony, musi posiadać wartość metr (a nie stopa czy inny ciąg znaków). Zwróć uwagę, że w przypadku trzeciego fragmentu kodu parser zachowuje się tak, jakby wartością atrybutu jednostka faktycznie był metr
Tworzenie dokumentów DTD
Definiowanie atrybutów z wyborami Rysunek 6.27. W tym przykładzie chcę dopuścić tylko dwie możliwe wartości dla atrybutu jednostka w elemencie wysokosc: metr lub centymetr. Lista wyborów umieszczona jest w nawiasach, a do rozdzielenia pozycji zastosowałem pionową kreskę. Zwróć uwagę, że dany atrybut musi być ustalony (z powodu wartości #REQUIRED)
Dokumenty DTD obsługują typy atrybutów, które dopuszczają znacznie więcej niż tylko dane znakowe. Jeden z takich typów pozwala definiować atrybut, który obsługuje różne predefiniowane wybory (rysunek 6.27).
Aby zdefiniować atrybut z wyborami: 1. Rozpocznij definicję atrybutu według punktów 1. i 2. procedury opisanej w podrozdziale „Definiowanie atrybutów”. 2. Wpisz (wybór_1 | wybór_2), gdzie wybór_n reprezentuje każdą możliwą wartość atrybutu, a każdy atrybut w dokumencie XML może stosować tylko jeden z wymienionych wyborów. Wybory powinny być rozdzielone pionową kreską, a cała lista powinna być ujęta w nawiasy.
4. Wpisz >, aby zakończyć definicję atrybutu.
Wskazówki Przy definiowaniu każdego wyboru z listy należy przestrzegać reguł pisania poprawnych nazw XML (patrz rozdział 1., podrozdział „Tworzenie elementu głównego”). Istnieje jeszcze kilka innych rodzajów typów atrybutów: ID, IDREF i IDREFS (które zostały omówione w podrozdziałach „Definiowanie atrybutów z wartościami unikatowymi” i „Odwoływanie się do atrybutów z wartościami unikatowymi”), NMTOKEN i NMTOKENS (które zostały omówione w podrozdziale „Ograniczanie atrybutów do poprawnych nazw XML”) oraz ENTITY (opisany w rozdziale 7.).
105
Definiowanie atrybutów z wyborami
Rysunek 6.28. Spośród tych trzech fragmentów kodu XML tylko pierwszy jest poprawny względem definicji DTD z rysunku 6.27. Środkowy kod jest nieprawidłowy, ponieważ metr nie jest dopuszczalnym wyborem dla zawartości tego atrybutu. Trzeci fragment jest nieprawidłowy, ponieważ brakuje atrybutu jednostka, chociaż jest on wymagany (#REQUIRED)
3. Określ opcjonalne statusy atrybutu w sposób opisany w punkcie 4. procedury z podrozdziału „Definiowanie atrybutów” oraz w punkcie 2. procedury z podrozdziału „Definiowanie wartości domyślnych”.
Rozdział 6.
Definiowanie atrybutów z wartościami unikatowymi Istnieje kilka specjalnych rodzajów typów atrybutów. Atrybuty ID są definiowane z wartością, która jest unikatowa (niepowtarzalna) dla całego dokumentu XML. Atrybut ID jest idealny dla kluczy i innych informacji identyfikujących (kody produktów, kody klientów itd.).
Rysunek 6.29. Jeśli zamierzasz utworzyć atrybut ID, najlepiej, żeby był on wymagany. Jeśli nie, musi on być zasugerowany (#IMPLIED), ponieważ atrybuty ID nie mogą mieć wartości domyślnych
Aby zdefiniować atrybuty ID: 1. Rozpocznij definicję atrybutu według punktów 1. i 2. procedury opisanej w podrozdziale „Definiowanie atrybutów”.
Definiowanie atrybutów
2. Wpisz ID, aby zdefiniować, że wartość tego atrybutu będzie unikatowa i niepowtarzalna dla całego dokumentu XML. Innymi słowy, żaden inny element nie może mieć atrybutu o tej samej wartości. 3. Określ opcjonalne statusy atrybutu w sposób opisany w punkcie 4. procedury z podrozdziału „Definiowanie atrybutów” (Uwaga! Dla atrybutów ID można stosować tylko instrukcję #REQUIRED lub #IMPLIED. Nie mogą one posiadać domyślnych wartości z punktu 2. procedury opisanej w podrozdziale „Definiowanie wartości domyślnych”). 4. Wpisz >, aby zakończyć definicję atrybutu (rysunek 6.29).
Wskazówki Dokument XML nie jest uznawany za poprawny, jeśli dwa elementy z atrybutami ID mają tę samą wartość — bez względu na to, czy nazwy elementów lub atrybutów są takie same, czy inne. Jedynym wyjątkiem od tej reguły jest możliwość zdefiniowania nieograniczonej liczby pomijanych atrybutów ID, z których każdy implikuje pustą wartość. Wartość atrybutu ID musi stosować się do tych samych reguł, które określają zasady pisania nazw XML (patrz rozdział 1., podrozdział „Tworzenie elementu głównego”). (Oznacza to, że atrybut ID nie może zawierać jedynie wartości liczbowych, jak to ma miejsce w przypadku wielu pól ID w bazach danych, w numerach ubezpieczenia itd., chyba że poprzedzisz je literą lub znakiem podkreślenia).
106
Rysunek 6.30. Zgodnie z tym, co zostało zdefiniowane w DTD z rysunku 6.29, atrybut kod musi za każdym razem zawierać unikatową wartość w całym dokumencie XML. Przy tym założeniu pierwszy fragment jest poprawny, ale drugi nie
Tworzenie dokumentów DTD
Odwoływanie się do atrybutów z wartościami unikatowymi Rysunek 6.31. Element specjalna_strona będzie dokumentował strony WWW poświęcone każdemu z cudów. Jego atrybut identyfikator_cudu został zdefiniowany jako typ IDREF, więc może zawierać identyfikator cudu, którego dotyczy
Rysunek 6.33. Element ogolna_strona posiada atrybut IDREFS o nazwie zawartosc. Atrybut ten może zawierać listę identyfikatorów cudów, na których koncentruje się element ogolna_strona
Atrybut, którego wartość jest identyczna z wartością dowolnego istniejącego atrybutu ID (omówionego w podrozdziale „Definiowanie atrybutów z wartościami unikatowymi”) w dokumencie XML, jest zwany atrybutem IDREF (rysunek 6.31). Atrybut, którego wartość stanowi rozdzielona białymi znakami lista wartości istniejących atrybutów ID, jest zwany atrybutem IDREFS (litera „S” to oczywiście konsekwencja utworzenia w języku angielskim liczby mnogiej — rysunek 6.33).
Aby odwołać się do atrybutów z unikatowymi wartościami: 1. Rozpocznij definicję atrybutu według punktów 1. i 2. procedury opisanej w podrozdziale „Definiowanie atrybutów”.
Rysunek 6.34. Ten fragment kodu XML jest prawidłowy, jeśli zastosujemy do niego definicję DTD z rysunku 6.33
Możesz też wpisać IDREFS (z „s” na końcu) dla zdefiniowania atrybutu, który zawiera kilka rozdzielonych białymi znakami wartości odpowiadających wartościom istniejących atrybutów ID. 3. Określ opcjonalne statusy atrybutu w sposób opisany w punkcie 4. procedury z podrozdziału „Definiowanie atrybutów” oraz w punkcie 2. procedury z podrozdziału „Definiowanie wartości domyślnych”. 4. Wpisz >, aby zakończyć definicję atrybutu.
Wskazówki Zwróć uwagę, że może być kilka atrybutów IDREF, które odnoszą się do tego samego ID (rysunek 6.32). Jest to zupełnie poprawne. Tylko samo ID musi być unikatowe dla jednego elementu.
Rysunek 6.32. Zgodnie z DTD z rysunku 6.31, atrybut identyfikator_cudu musi zawierać wartość pochodzącą z istniejącego atrybutu ID z danego dokumentu. (Uwaga! Ten fragment kodu XML pochodzi z pliku XML, który zawiera również pierwszy z fragmentów kodu z rysunku 6.30)
Żaden czynnik nie wyklucza powtarzających się pozycji z atrybutu IDREFS. Konstrukcja taka jak zawartość="w_143 w_143 w_143" jest zupełnie poprawna dla parsera, bez względu na to, czy właśnie o to Ci chodziło. Jeśli chcesz mieć większą kontrolę nad zawartością elementów i atrybutów, musisz zrezygnować z DTD na rzecz XML Schema (patrz część IV).
107
Odwoływanie się do atrybutów
2. Wpisz IDREF, aby zdefiniować atrybut, który posiada wartość odpowiadającą wartości dowolnego istniejącego atrybutu ID (takiego jak ten, który został zdefiniowany według instrukcji opisanych w podrozdziale „Definiowanie atrybutów z wartościami unikatowymi”).
Rozdział 6.
Ograniczanie atrybutów do poprawnych nazw XML Dokumenty DTD nie pozwalają na wpisywanie dużej ilości danych, ale jest jedno ograniczenie, które możesz zastosować do atrybutów. Wartość atrybutu zdefiniowanego jako typ NMTOKEN musi być poprawną nazwą XML. Oznacza to, że dana wartość musi rozpoczynać się od litery lub znaku podkreślenia i powinna zawierać jedynie litery, liczby, znaki podkreślenia, myślniki i kropki.
Aby zapewnić, że wartości atrybutów będą zgodne z regułami pisania nazw XML:
Rysunek 6.35. W tym dość sztucznym przykładzie potrzebuję dla każdego cudu pojedynczego słowa, które mógłbym wykorzystać jako podstawowe słowo kluczowe w specjalnej aplikacji online o nazwie Cudowna Wycieczka. Utworzyłem więc element cud_w z atrybutem slowo_kluczowe. Aby ograniczyć wartość atrybutu slowo_kluczowe do jednego słowa (bez białych znaków), mogę zdefiniować go jako typ NMTOKEN
1. Rozpocznij definicję atrybutu według punktów 1. i 2. procedury opisanej w podrozdziale „Definiowanie atrybutów”.
Ograniczanie atrybutów
2. Wpisz NMTOKEN, jeśli chcesz, żeby wartość atrybutu była poprawną nazwą XML (patrz rozdział 1., podrozdział „Tworzenie elementu głównego”). 3. Możesz też wpisać NMTOKENS, jeśli chcesz, żeby wartość atrybutu była listą poprawnych nazw XML rozdzielonych białymi znakami. 4. Określ opcjonalne statusy atrybutu w sposób opisany w punkcie 4. procedury z podrozdziału „Definiowanie atrybutów” oraz w punkcie 2. procedury z podrozdziału „Definiowanie wartości domyślnych”. 5. Wpisz >, aby zakończyć definicję atrybutu (rysunek 6.35).
Wskazówki Atrybuty NMTOKEN nie mogą zawierać żadnych białych znaków, co może być dobrym powodem, żeby zastosować właśnie ten konkretny typ atrybutów. Jeśli chcesz, aby wartość atrybutu była nie tylko poprawną nazwą XML, ale żeby była również unikatowa dla całego dokumentu XML, zastosuj ID zamiast NMTOKEN (patrz podrozdział „Definiowanie atrybutów z wartościami unikatowymi”).
108
Rysunek 6.36. Tylko drugi fragment kodu z tego przykładu zostanie uznany za poprawny względem DTD z rysunku 6.35. W pierwszym fragmencie kodu atrybut slowo_kluczowe ma wartość „piramida cheopsa”, która jest zapisana z wykorzystaniem spacji, a spacje nie są dopuszczalne w atrybutach NMTOKEN
Encje i notacje w dokumentach DTD
7
Rozdział 7. Encje i notacje w dokumentach DTD Encje są podobne do wpisów autotekstu lub skrótów. W encji definiujesz jej nazwę oraz tekst, w który powinna się ona rozwijać, gdy jest wywoływana w dokumencie. Następnie, kiedy wpiszesz w dokumencie XML lub DTD referencję do tej encji, referencja jest zastępowana zdefiniowanym przez Ciebie tekstem. Istnieje kilka typów encji, ale wszystkie działają w ten sam sposób i wszystkie są definiowane za pomocą DTD. Różnice dotyczą tego, gdzie dana encja może być rozwinięta i jaki rodzaj danych zawiera. Encje możemy podzielić na dwa główne typy: encje ogólne (ang. general entities) oraz encje parametryczne (ang. parameter entities). Encje ogólne mogą być rozwijane tylko w dokumentach XML, natomiast encje parametryczne mogą być rozwijane tylko w dokumentach DTD.
109
Encje i notacje w dokumentach DTD
Encje ogólne można dalej podzielić na wewnętrzne i zewnętrzne oraz parsowane i nieparsowane. Encje parametryczne można również podzielić na wewnętrzne i zewnętrzne, ale encje parametryczne zawsze są parsowane.
Rozdział 7.
Tworzenie encji ogólnej Najprostszy rodzaj encji definiowany jest w DTD i reprezentuje po prostu tekst. Oficjalnie encje te zwane są wewnętrznymi opcjami ogólnymi (ang. internal general entities). Ja często nazywam je skrótami.
Aby utworzyć wewnętrzną encję ogólną: 1. W DTD wpisz , aby zakończyć definicję encji (rysunek 7.1).
Tworzenie encji ogólnej
Wskazówki Szczegółowe informacje na temat korzystania z tych skrótów znajdziesz w podrozdziale „Korzystanie z encji ogólnych”. Referencja nazwy encji (w punkcie 2. powyższej procedury) musi być zgodna z regułami pisania poprawnych nazw XML (patrz rozdział 1., podrozdział „Tworzenie elementu głównego”). W XML-u istnieje pięć wbudowanych encji ogólnych: &, <, >, " oraz &apost; (patrz rozdział 1., podrozdział „Encje predefiniowane — pięć znaków specjalnych”). Wszystkie pozostałe encje muszą być zadeklarowane w DTD, zanim zostaną użyte. Wiele typowych encji zostało już zdefiniowanych i można je łatwo załączyć do własnych dokumentów DTD. Więcej szczegółowych informacji na ten temat znajdziesz w punkcie „Wskazówki” w podrozdziale „Korzystanie z zewnętrznych encji ogólnych”.
110
Rysunek 7.1. Wewnętrznych encji ogólnych możesz używać do szybkiego wpisywania długich fraz, które mogą się często pojawiać w Twoim dokumencie XML
Encje i notacje w dokumentach DTD
Korzystanie z encji ogólnych Kiedy zdefiniujesz już encję w swoim DTD, możesz z niej korzystać w dowolnym dokumencie XML, który odwołuje się do tego DTD.
Aby użyć encji ogólnych: 1. W dokumencie XML wpisz & (znak et).
Rysunek 7.2. Łatwiej i szybciej jest wpisać &css; niż pełną frazę „Cuda starożytnego świata”
2. Następnie wpisz nazwa_encji, gdzie nazwa_encji określa nazwę danej encji (tej z punktu 2. procedury opisanej w podrozdziale „Tworzenie encji ogólnej”). 3. Na koniec wpisz ; (średnik) (rysunek 7.2).
Wskazówki Encji ogólnych możesz używać dopiero po tym, jak zostaną zdefiniowane w dokumencie DTD, do którego odwołuje się Twój dokument XML. W przeciwnym razie parser zwróci błąd z informacją, że encja nie została zdefiniowana.
Encje ogólne są stosowane tylko w dokumentach XML. Nie można ich używać w dokumentach XSLT (istnieją pewne sposoby, żeby to obejść, ale są to zaawansowane i skomplikowane techniki). Rysunek 7.3. Encja utworzona na przykładzie z rysunku 7.2 jest „rozwijana”, gdy dokument XML jest parsowany
Możesz użyć encji w ramach definicji innej encji, pod warunkiem że nie istnieje żadna referencja cykliczna.
111
Korzystanie z encji ogólnych
Referencje znakowe są wykorzystywane w celu dodania do dokumentu symboli specjalnych, np. napisanie &246; wygeneruje symbol ö itd. Wyglądają one całkiem podobnie do encji, ale nimi nie są i nie muszą być deklarowane w DTD (patrz dodatek B).
Rozdział 7.
Tworzenie zewnętrznej encji ogólnej Jeśli posiadasz obszerniejszą encję lub encję, która może być wielokrotnie wykorzystywana w różnych dokumentach DTD, z reguły wygodniej jest zapisać ją w osobnym dokumencie zewnętrznym.
Aby utworzyć zewnętrzną encję ogólną: Utwórz zawartość dla danej encji w pliku zewnętrznym. Zapisz ten plik jako plik wyłącznie tekstowy z rozszerzeniem .ent (rysunek 7.4).
Aby zdefiniować zewnętrzną encję ogólną: 4. W dokumencie DTD, w którym chcesz użyć danej zawartości, wpisz
Tworzenie zewnętrznej encji ogólnej
5. Następnie wpisz nazwa_encji, gdzie nazwa_encji określa nazwę danej encji zewnętrznej. Do tej nazwy będziesz odwoływał się, korzystając z danej encji w swoim dokumencie XML. 6. Dalej wpisz SYSTEM, aby wskazać, że dana encja jest zdefiniowana zewnętrznie w innym dokumencie. 7. Następnie wpisz "encja.uri", gdzie encja.uri jest lokalizacją pliku, w którym znajduje się zawartość encji. 8. Wreszcie wpisz >, aby zakończyć definicję encji (rysunek 7.5).
Wskazówki Adres "encja.uri" w punkcie 4. powyższej procedury może odwoływać się do pliku znajdującego się na Twoim komputerze, w sieci lokalnej lub w internecie. Stosowanie rozszerzenia pliku .ent dla zewnętrznych encji ogólnych nie jest wymagane (można zastosować dowolne rozszerzenie), ale rozszerzenie to jest najbardziej popularne. Korzystając z encji zewnętrznych, możesz faktycznie utworzyć pojedynczy dokument DTD z kilku innych.
112
Rysunek 7.4. Tym razem zdefiniuję encję, którą będzie cały fragment kodu XML. Zwróć uwagę, że fragment ten zawiera encję ogólną zdefiniowaną w przykładzie z rysunku 7.1. Utworzony plik zapiszę jako plik tekstowy o nazwie ogrody.ent
Rysunek 7.5. Dana encja o nazwie ogrody_dzieje wskazuje URI pliku, w którym znajduje się zawartość encji pokazanej na rysunku 7.4
Encje i notacje w dokumentach DTD
Korzystanie z zewnętrznych encji ogólnych Gdy utworzysz już swoją encję, możesz z niej korzystać, udostępniać ją innym użytkownikom, a także pożyczać encje od innych użytkowników (pod warunkiem że będą to również zewnętrzne encje ogólne).
Aby skorzystać z zewnętrznych encji ogólnych: 1. W dokumencie XML, który będzie odwoływał się do danego DTD, dodaj standalone="no" do początkowej deklaracji XML (patrz rozdział 1., podrozdział „Jak zacząć”). Jest to instrukcja dla parsera XML, że dany dokument będzie opierał się na pliku zewnętrznym. W naszym przypadku jest to plik zawierający definicję encji. Rysunek 7.6. Najpierw upewnij się, że dodałeś do deklaracji XML instrukcję standalone="no". Po tym będziesz już mógł w danym dokumencie używać zewnętrznej encji ogólnej w taki sposób, jak w tym przykładzie użyta została encja &ogrody_dzieje
2. Następnie w danym dokumencie XML wpisz & (znak et). 3. Dalej wpisz nazwa_encji, gdzie nazwa_encji określa nazwę Twojej encji (tej z punktu 2. procedury opisanej w podrozdziale „Tworzenie zewnętrznej encji ogólnej”).
Wskazówki URI (ang. Uniform Resource Identifier), czyli jednolity identyfikator zasobu, jest ciągiem znaków wykorzystywanym do identyfikacji i lokalizacji zasobu. Jest on często używany zamiennie z URL (ang. Uniform Resource Locator), czyli jednolitym wskaźnikiem zasobu. Technicznie rzecz biorąc, adresem URI może być zarówno URL, jak i URN (ang. Uniform Resource Name), czyli uniwersalna nazwa zasobu. Jednak dla celów tej książki będę korzystał z pojęć URI i URL w tym samym znaczeniu.
Rysunek 7.7. Ta encja (zdefiniowana w przykładzie z rysunku 7.5) zawiera element, tekst oraz drugą encję. Idea pozostaje ta sama: wpisujesz krótki ciąg znaków, a parser zastępuje go wskazaną zawartością. Zwróć uwagę, że aby dokument był prawidłowy, wszelkie elementy pochodzące z zewnętrznej encji ogólnej muszą być również zdefiniowane w danym DTD
Możesz odwoływać się do znormalizowanej listy encji, takiej jak ta, która jest dostępna pod adresem www.w3.org/TR/xhtml1/#h-A2. Pozwoli Ci to używać łatwych do zapamiętania referencji encji dla znaków akcentowanych, bez konieczności ręcznego definiowania każdego z nich. Encje ogólne (takie jak te opisane w podrozdziałach „Tworzenie encji ogólnej” i „Tworzenie zewnętrznej encji ogólnej”) są definiowane jako część DTD i wykorzystywane w zawartości głównej dokumentu XML. Istnieje też inny rodzaj encji używanych w celu dodawania komentarzy do samych dokumentów DTD. Są to tzw. encje parametryczne i mają nieco inną składnię (patrz podrozdział „Tworzenie i wykorzystywanie encji parametrycznych”).
113
Korzystanie z zewnętrznych encji ogólnych
4. Na koniec wpisz ; (średnik) (rysunek 7.6).
Rozdział 7.
Tworzenie encji dla zawartości nieparsowanej Dotychczas mówiliśmy jedynie o encjach, których zawartością jest tekst. Encje zawierające tekst są nazywane encjami parsowanymi (ang. parsed entities), ponieważ parser XML przegląda je i analizuje podczas procesu przetwarzania dokumentu XML. Encje nieparsowane (ang. unparsed entities), którymi zajmę się teraz, zazwyczaj nie zawierają tekstu (chociaż mogą), ale co najważniejsze, są całkowicie pomijane przez parser XML. Mogą one być wykorzystane do wstawienia do dokumentu XML zawartości nietekstowej lub niebędącej XML-em.
Rysunek 7.8. Oto typowy fragment nieparsowanych danych: obrazek JPEG o nazwie lighthouse.jpg
Aby utworzyć zawartość nieparsowaną:
Tworzenie encji dla zawartości nieparsowanej
Utwórz dane, które chcesz wstawić do dokumentu XML. Mogą one być czymkolwiek lub zawierać praktycznie cokolwiek, w tym zwykły tekst, plik graficzny, plik wideo, plik PDF itd. (rysunek 7.8). W celu utworzenia encji dla nieparsowanej zawartości musisz najpierw za pomocą notacji (ang. notation) określić, w jaki sposób przetwarzać tę nieparsowaną zawartość.
Aby utworzyć notację dotyczącą zawartości nieparsowanej: 1. W dokumencie DTD, do którego chcesz załączyć daną zawartość, wpisz , aby zakończyć notację (rysunek 7.9).
114
Rysunek 7.9. Nazwa identyfikująca elementu NOTATION, czyli „jpg”, będzie wykorzystywana przy tworzeniu encji dla nieparsowanej zawartości
Encje i notacje w dokumentach DTD Aby zdefiniować encję dla zawartości nieparsowanej: 1. Po odpowiedniej notacji dla zawartości nieparsowanej, w nowym wierszu tego samego DTD, wpisz
Rysunek 7.10. Nazwa tej encji, czyli „latarnia_obrazek”, odwołuje się do zewnętrznego pliku (instrukcja SYSTEM) o nazwie lighthouse.jpg, a więcej informacji o tym pliku mogę uzyskać, spoglądając na identyfikator notacji NDATA jpg
2. Następnie wpisz nazwa_encji, gdzie nazwa_encji określa nazwę danej encji zewnętrznej. Do tej nazwy będziesz odwoływał się, korzystając z danej encji w swoim dokumencie XML. 3. Dalej wpisz SYSTEM, aby wskazać, że encja jest definiowana w osobnym dokumencie. 4. Następnie wpisz "encja.uri", gdzie encja.uri jest lokalizacją pliku z nieparsowaną zawartością. 5. Wpisz NDATA nazwa_notacji, gdzie nazwa_notacji jest nazwą identyfikującą zawartość nieparsowaną utworzoną w punkcie 1. poprzedniej procedury opisanej w tym podrozdziale.
Wskazówki Parametr "instrukcje_notacji" w punkcie 3. pierwszej z procedur opisanych w tym podrozdziale może być: typem MIME (internetowym standardem opisującym typy zawartości), adresem URI wskazującym lokalną lub zewnętrzną aplikację, która może obsłużyć zawartość nieparsowaną lub dosłownie czymkolwiek innym. Zgodnie ze specyfikacją, nie istnieje żaden wymagany format dla tych informacji, a każda aplikacja XML może używać tej informacji tak, jak chce. Encje nieparsowane są właściwie encjami ogólnymi, ponieważ stają się częścią zawartości głównej dokumentu XML. Zawartością encji nieparsowanej może być praktycznie wszystko. Często jest to plik graficzny, plik audio, plik wideo lub jakiś inny rodzaj pliku multimedialnego. Może być to również zwykły tekst. W sumie nie ma znaczenia, co to jest, ponieważ parser XML nie podgląda tej zawartości.
115
Tworzenie encji dla zawartości nieparsowanej
6. Wpisz >, aby zakończyć definicję encji (rysunek 7.10).
Rozdział 7.
Wstawianie zawartości nieparsowanej Po zdefiniowaniu encji dla zawartości nieparsowanej w sposób opisany w podrozdziale „Tworzenie encji dla zawartości nieparsowanej” możesz wstawić ją do swojego dokumentu XML. Encje nieparsowane nie posiadają referencji encji (w przeciwieństwie do encji parsowanych, które zostały opisane wcześniej). Zamiast tego do encji nieparsowanych można się odwoływać poprzez specjalny typ atrybutu ENTITY.
Aby zadeklarować atrybut, który będzie zawierał referencje do encji nieparsowanej: 1. W DTD zdefiniuj najpierw element. Jest to element, który będzie zawierał atrybut z referencją do encji nieparsowanej.
Wstawianie zawartości nieparsowanej
2. Wpisz , aby zakończyć definicję atrybutu (rysunek 7.11).
116
Rysunek 7.11. Najpierw definiuję element fotka, który będzie zawierał atrybut z referencjami do nieparsowanych danych. Następnie za pomocą typu atrybutu ENTITY definiuję atrybut encji, który nazywa się zrodlo
Encje i notacje w dokumentach DTD Aby wstawić encję nieparsowaną do dokumentu XML: 7. W dokumencie XML, który będzie odwoływał się do danego DTD, dodaj instrukcję standalone="no" do początkowej deklaracji XML. Instrukcja ta informuje parser XML, że dany dokument będzie opierał się na pliku zewnętrznym. W naszym przypadku jest to plik zawierający encję nieparsowaną.
Rysunek 7.12. Wartość atrybutu zrodlo elementu fotka odpowiada nazwie encji odwołującej się do nieparsowanych danych
8. W głównej zawartości dokumentu XML, w obrębie atrybutu zadeklarowanego typem ENTITY (w poprzedniej procedurze opisanej w tym podrozdziale), wpisz nazwa_atrybutu="nazwa_encji", gdzie nazwa_atrybutu identyfikuje atrybut, a nazwa_encji jest nazwą encji nieparsowanej, którą utworzyłeś w punkcie 2. procedury opisanej w podrozdziale „Tworzenie encji dla zawartości nieparsowanej” (rysunek 7.12).
Wskazówki
W rzeczywistości istnieje ogólna zgoda co do tego, że korzystanie z encji nieparsowanych jest skomplikowane i mylące. Zamiast tego można ustawić jako wartość elementu adres URL wskazujący dowolny wybrany przez Ciebie plik oraz, w razie potrzeby, wykorzystać atrybuty do objaśnienia dodatkowych informacji.
117
Wstawianie zawartości nieparsowanej
Rysunek 7.13. Po zastosowaniu arkusza stylów XSLT do przekształcenia dokumentu XML rezultaty wyświetlone w przeglądarce Internet Explorer 8 są rozczarowujące. Problem ten dotyczy większości bieżących przeglądarek
Chociaż parsery XML powinny być w stanie wykorzystać informacje z notacji, aby móc podejrzeć (bądź odtworzyć lub wyświetlić) encję nieparsowaną, to aktualne przeglądarki nie mogą tego zrobić. Mówiąc w skrócie, nie wyświetlą one wstawionych danych (rysunek 7.13).
Rozdział 7.
Tworzenie i wykorzystywanie encji parametrycznych Wszystkie omawiane do tej pory encje odwołują do tekstu lub plików, które mają być wykorzystane w dokumencie XML. W DTD możesz również tworzyć encje dla samych dokumentów DTD. Ten rodzaj skrótów zwany jest encjami parametrycznymi (ang. parameter entities).
Rysunek 7.14. Oto bardzo prosty przykład. Utworzyłem encję parametryczną o nazwie „p” dla czegoś, co jest dość często wpisywane w większości dokumentów DTD: (#PCDATA)
Aby utworzyć encję parametryczną: 1. W DTD wpisz
Tworzenie i wykorzystywanie encji
4. Wpisz "zawartość", gdzie zawartość jest tekstem skrótu, który pojawi się, gdy użyjesz tej encji w swoim dokumencie DTD. 5. Wpisz >, aby zakończyć definicję encji (rysunek 7.14). Po utworzeniu opcji parametrycznej możesz jej użyć.
Aby użyć opcji parametrycznej: 1. W dokumencie DTD wpisz % (bez spacji po tym znaku). 2. Następnie wpisz nazwa_encji, gdzie nazwa_encji jest identyfikującą nazwą Twojej encji (utworzonej w punkcie 3. poprzedniej procedury z tego podrozdziału). 3. Wpisz ; (średnik) (rysunek 7.15).
Wskazówki Encje parametryczne muszą być najpierw utworzone w DTD, zanim zostaną w DTD użyte. W tym przypadku kolejność ma znaczenie. Encje parametryczne mogą być używane tylko w DTD, a od encji ogólnych odróżnia je znak procentu (%).
118
Rysunek 7.15. W swoim głównym dokumencie DTD używam opcji parametrycznej %p; do wstawiania instrukcji (#PCDATA)
Encje i notacje w dokumentach DTD
Tworzenie zewnętrznej encji parametrycznej Rysunek 7.16. Oto fragment kodu DTD, który zapisałem w osobnym pliku o nazwie obrazek.ent. Chcę wykorzystać go w kilku innych dokumentach DTD, ponieważ zawiera deklaracje dla elementu obrazek_głowny i jego atrybutów
Rysunek 7.17. W tym DTD, i w każdym innym, w którym chcę zadeklarować element obrazek_glowny i jego atrybuty, muszę najpierw zdefiniować tę encje (tak jak pokazano w tym przykładzie)
Podobnie jak w przypadku encji ogólnych, encje parametryczne mogą być tworzone w plikach zewnętrznych.
Aby utworzyć zewnętrzną opcję parametryczną: Utwórz zawartość encji w pliku zewnętrznym i zapisz go jako plik wyłącznie tekstowy z rozszerzeniem .ent (rysunek 7.16).
Aby zdefiniować zewnętrzną encję parametryczną: 1. W swoim dokumencie DTD wpisz
4. Wpisz SYSTEM, aby wskazać, że dana encja jest definiowana zewnętrznie w innym dokumencie. Rysunek 7.18. Po zdefiniowaniu tej encji można z niej korzystać, wpisując jej referencję, czyli w naszym przypadku %full_pic;
5. Następnie wpisz "encja.uri", gdzie encja.uri jest lokalizacją pliku z zawartością encji. 6. Wpisz >, aby zakończyć definicję encji (rysunek 7.17).
Wskazówki Używaj tej zewnętrznej encji parametrycznej (rysunek 7.18) w taki sam sposób jak wewnętrznej opcji parametrycznej (patrz podrozdział „Tworzenie i wykorzystywanie encji parametrycznych”).
Rysunek 7.19. Kiedy dokument DTD pokazany na rysunku 7.18 jest parsowany, procesor zastępuje referencję encji parametrycznej %full_pic zawartością pliku pokazaną na rysunku 7.16. Teraz element obrazek_glowny w pliku XML jest uznawany za prawidłowy według danego dokumentu DTD
Jeśli używasz wewnętrznego DTD (patrz rozdział 8., podrozdział „Deklarowanie i tworzenie wewnętrznego DTD”), wtedy w dokumencie XML zawierającym to DTD dodaj instrukcję standalone="no" do początkowej deklaracji XML. Instrukcja ta wskazuje parserowi XML, że dany dokument będzie opierał się na pliku zewnętrznym.
119
Tworzenie zewnętrznej encji parametrycznej
3. Dalej wpisz nazwa_encji, gdzie nazwa_encji określa nazwę danej encji zewnętrznej. Do nazwy tej będziesz się odwoływał, używając tej encji w swoim dokumencie XML.
Rozdział 7.
120
Walidacja i używanie DTD
8
Rozdział 8. Walidacja i używanie DTD [RS1] W poprzednich dwóch rozdziałach nauczyłeś się tworzyć dokumenty DTD. W tym rozdziale dowiesz się, jak z nich korzystać. Dokumenty DTD definiują w szczególności reguły dla każdego elementu i atrybutu, które mogą pojawić się w dokumencie XML. Jednak aby użyć DTD, musisz zadeklarować je w swoim dokumencie XML. Po dokonaniu tej deklaracji możesz używać różnych narzędzi do walidacji dokumentu XML względem danego DTD. Jest to główny powód tworzenia DTD: zapewnienie, że dany dokument XML jest skonstruowany w określony sposób, czyli tak jak zostało zdefiniowane w DTD.
121
Walidacja i używanie DTD
Dokumenty DTD mogą być tworzone i zapisywane jako osobne pliki lub też mogą być pisane całkowicie wewnątrz dokumentu XML. Zaletą pisania wewnętrznych DTD jest to, że musimy zarządzać tylko jednym plikiem, który zawiera zarówno strukturę DTD, jak i zawartość XML. Z kolei korzyścią z pisania zewnętrznych DTD jest możliwość łatwego ich wykorzystania do walidacji wielu dokumentów XML. W rzeczywistości mogą one być wykorzystywane przez inne osoby i firmy generujące dokumenty XML w celu walidacji tych dokumentów, zanim zostaną one wysłane do Ciebie. Działa to oczywiście w obie strony. W ten sposób proces walidacji umożliwia udostępnianie dokumentów XML oraz weryfikację, czy wszystkie te dokumenty mają konsekwentną strukturę.
Rozdział 8.
Tworzenie zewnętrznego dokumentu DTD Jeśli posiadasz zbiór powiązanych ze sobą dokumentów XML, możesz chcieć, aby wszystkie używały tego samego DTD. Zamiast kopiowania tego DTD do każdego dokumentu, możesz stworzyć zewnętrzny plik zawierający to DTD (rysunek 8.1), a następnie odwoływać się do niego w każdym dokumencie XML, który tego potrzebuje.
Aby utworzyć zewnętrzne DTD: 1. Zdefiniuj reguły dla danego DTD w zewnętrznym pliku, tak jak to zostało opisane w rozdziałach 6. i 7. 2. Zapisz ten plik jako plik wyłącznie tekstowy z rozszerzeniem .dtd.
Wskazówki
Tworzenie zewnętrznego dokumentu DTD
Jak pewnie zauważyłeś w poprzednich dwóch rozdziałach, wszystkie przykłady DTD wykorzystywane przez dokumenty XML były zewnętrznymi DTD. Jest to najbardziej powszechny sposób używania DTD. Szczegółowe informacje na temat używania zewnętrznych DTD znajdziesz w podrozdziale „Deklarowanie zewnętrznego DTD”.
122
Rysunek 8.1. To DTD zostało zapisane jako plik o nazwie 08-01.dtd (nazwa pliku nie ma większego znaczenia poza tym, że odpowiada numeracji rysunku). Zwróć uwagę, że nie ma tu jeszcze żadnej relacji z jakimkolwiek dokumentem XML. Plik ten zawiera po prostu definicje DTD i został zapisany jako plik wyłącznie tekstowy z rozszerzeniem .dtd
Walidacja i używanie DTD
Deklarowanie zewnętrznego DTD Jeśli utworzyłeś już zewnętrzne DTD, musisz odwołać się do niego w swoim dokumencie XML. Odbywa się to za pomocą deklaracji typu dokumentu (patrz punkt „Wskazówki” w dalszej części tego podrozdziału), która deklaruje określone DTD (rysunek 8.2).
Aby zadeklarować zewnętrzne DTD: 1. Wpisz , aby zakończyć deklarację typu dokumentu. 5. Następnie w deklaracji XML na początku dokumentu dodaj instrukcję standalone="no". Instrukcja ta informuje parser XML, że dany dokument będzie opierał się na zewnętrznym pliku. W naszym przypadku będzie to plik zawierający DTD.
Wskazówki Jak już wspomniano, aby dokument XML był poprawny (ang. valid), musi być zgodny z regułami odpowiadającego mu DTD. Adres "dtd.uri" w punkcie 3. powyższej procedury może odwoływać się do pliku na Twoim komputerze, w sieci lokalnej lub w internecie. Domyślną wartością atrybutu standalone w deklaracji XML w punkcie 5. powyższej procedury jest no. W przykładach z rysunku 8.2 atrybut ten nie był potrzebny. Zabawmy się nieco terminologią. Zbiór reguł elementów i atrybutów zwany jest DTD (ang. document type definition), czyli definicją typu dokumentu. Wiersze kodu, które odwołują się do tego DTD, zwane są deklaracją typu dokumentu (ang. document type declaration). Aby rozróżnić te dwa pojęcia, potraktuj deklarację typu dokumentu jako instrukcję, która odwołuje się do definicji typu dokumentu lub deklaruje tę definicję.
123
Deklarowanie zewnętrznego DTD
Rysunek 8.2. Zgodnie z DTD wskazanym w każdej z deklaracji typu dokumentu tych dokumentów XML (08-01.dtd na rysunku 8.1), tylko pierwszy dokument XML jest poprawny. Drugi z dokumentów posiada element wysokosc, który ma niezdefiniowany atrybut jednostka. W trzecim znajdują się dwa elementy nazwa, a dopuszczalny jest tylko jeden
Rozdział 8.
Deklarowanie i tworzenie wewnętrznego DTD Dla indywidualnych dokumentów XML (takich, których nie będziesz raczej udostępniał lub będziesz udostępniał w ograniczony sposób) najprościej jest zadeklarować i utworzyć DTD w obrębie samego dokumentu XML. Zasady tworzenia DTD są takie same, bez względu na to, czy są to DTD wewnętrzne, czy zewnętrzne. Różnicę między nimi stanowi sposób pisania deklaracji typu dokumentu. Innymi słowy, chodzi o sposób deklarowania DTD.
Aby zadeklarować i utworzyć wewnętrzne DTD:
Deklarowanie i tworzenie wewnętrznego DTD
1. Na samym początku dokumentu XML, po deklaracji XML (patrz rozdział 1., podrozdział „Jak zacząć”), wpisz
Rysunek 8.3. Oto proste wewnętrzne DTD. Rozpoczyna się zaraz po deklaracji XML, a kończy tuż przed faktycznymi znacznikami umieszczonymi w zawartości głównej tego dokumentu. Odpowiada to pierwszemu przykładowi z rysunku 8.2
2. Następnie, posługując się informacjami z poprzednich dwóch rozdziałów, utwórz swoje DTD, definiując jego elementy i atrybuty. 3. Wreszcie wpisz ]>, aby zakończyć deklarację typu dokumentu (rysunek 8.3).
Wskazówki Chociaż wewnętrzne deklaracje DTD są częścią samego dokumentu XML, nie są elementami XML i dlatego nie wymagają zamykającego ukośnika przed końcowym nawiasem trójkątnym (>). W rzeczywistości, chociaż specyfikacja schematów DTD jest częścią specyfikacji XML, DTD używa specyficznej składni, która w ogóle nie jest zgodna z XML. W tym samym dokumencie XML możesz użyć zarówno wewnętrznego, jak i zewnętrznego DTD (rysunek 8.4). W takim przypadku reguły wewnętrznego DTD uchylają te z zewnętrznego DTD. Niestety większość procesorów XML traktuje konflikty między wewnętrznym i zewnętrznym DTD jak błędy (rysunek 8.5).
124
Rysunek 8.4. Połączenie zewnętrznego i wewnętrznego DTD może być czasem korzystne. Tutaj zaktualizowałem drugi przykład z rysunku 8.2, dodając wewnętrzne DTD, które deklaruje atrybut jednostka dla elementu wysokosc. Teraz jest to poprawny dokument XML
Rysunek 8.5. Niestety, chociaż trzeci przykład z rysunku 8.2 wydaje się teraz być poprawny, większość procesorów XML zwróci błąd z informacją, że niedopuszczalne jest przedefiniowanie elementu cud
Walidacja i używanie DTD
Walidacja dokumentów XML względem DTD Teraz, kiedy utworzyłeś już swoje DTD i wstawiłeś deklarację w dokumencie XML, będziesz chciał przeprowadzić walidację tego dokumentu względem danego DTD. Każdy parser XML powinien zwracać błąd, jeśli analizowany dokument XML nie jest poprawny składniowo, jednak nie każdy oferuje możliwość walidacji XML względem DTD.
Rysunek 8.6. Skopiowałem kod XML ze swojego edytora i wkleiłem go w polu tekstowym opisanym jako „Validate by direct input”. Czy dostrzegasz błąd w kodzie?
Jeśli parser, z którego korzystasz, nie posiada takiej funkcji, możesz użyć jednego z kilku walidatorów dostępnych online. Osobiście preferuję usługę Markup Validation Service dostępną na stronie organizacji W3C.
Aby skorzystać z walidatora online: 1. Upewnij się, że zadeklarowałeś DTD w swoim dokumencie. 2. Za pomocą przeglądarki otwórz stronę http://validator.w3.org/ (rysunek 8.6).
4. Kliknij Check, aby uruchomić sprawdzanie. Walidator przedstawi Ci użyteczny raport zawierający wszelkie znalezione błędy (rysunek 8.7). Rysunek 8.7. Walidator informuje mnie, że zapomniałem o otwierającym cudzysłowie przed wartością atrybutu ("grecki"). Zwróć uwagę, że problem ten spowodował wystąpienie dwóch błędów, jednak po dodaniu brakującego cudzysłowu oba błędy znikną
Wskazówki Jeśli używasz zewnętrznego DTD, musi on być również publicznie dostępny, inaczej walidator online nie będzie w stanie do niego dotrzeć. Często jeden błąd może powodować wystąpienie tzw. błędów duchów (ang. ghost errors). W tym przypadku większość kodu poniżej tego pierwszego błędu jest źle interpretowana (patrz rysunek 8.7). Zazwyczaj jeśli poprawisz pierwszy błąd z listy, a następnie dokonasz ponownej walidacji, wiele z tych dodatkowych błędów (błędów duchów) zniknie. Innym dostępnym online walidatorem jest narzędzie dostarczone przez grupę Scholarly Technology Group z Uniwersytetu Browna. Jest ono dostępne na stronie http://www.stg.brown.edu/service/xmlvalid/.
125
Walidacja dokumentów XML względem DTD
3. Wybierz jedną z trzech dostępnych opcji: Validate by URI (sprawdzenie pliku pod podanym adresem URI), Validate by File Upload (sprawdzenie załadowanego pliku) lub Validate by Direct Input (sprawdzenie pliku wklejonego bezpośrednio w pole do wprowadzania tekstu).
Rozdział 8.
Nazywanie publicznego zewnętrznego DTD Jeśli Twoje DTD będzie używane przez inne osoby, powinieneś nazwać ten dokument, stosując się do określonego standardu, czyli korzystając z identyfikatora FPI (ang. formal public identifier), zwanego formalnym identyfikatorem publicznym. Parser XML może wtedy wykorzystać dane FPI, aby na publicznym serwerze WWW odnaleźć najnowszą wersję danego DTD.
Aby nazwać zewnętrzne DTD: 1. Wpisz: –//, jeśli Twoje DTD nie jest rozpoznawalnym
standardem (najbardziej typowy przypadek); +//, jeśli Twoje DTD jest zatwierdzonym
standardem innym niż ISO; ISO//, jeśli Twoje DTD jest zatwierdzonym
Nazywanie publicznego zewnętrznego DTD
standardem ISO. 2. Następnie wpisz właściciel//, gdzie właściciel identyfikuje osobę lub organizację, która napisała dane DTD i utrzymuje je. 3. Dalej wpisz DTD opis//, gdzie opis zawiera referencje do danego DTD i powinien zawierać unikatowy element, taki jak numer wersji. 4. Na koniec wpisz XX, gdzie XX to dwuliterowy kod języka wykorzystywanego w DTD. Dla języka polskiego wpisz PL (w punkcie „Wskazówki” znajdziesz więcej informacji na temat innych języków).
Wskazówki Kompletną oficjalną listę dwuliterowych kodów języków w standardzie ISO 639 znajdziesz na stronie http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes. ISO (ang. International Organization for Standardization) to Międzynarodowa Organizacja Normalizacyjna, podobna do organizacji W3C.
126
Rysunek 8.8. Oto oficjalna nazwa publiczna dokumentu DTD opisującego moje dokumenty XML „Cuda starożytnego świata”
Walidacja i używanie DTD
Deklarowanie publicznego zewnętrznego DTD Jeśli moje dokumenty DTD „Cuda starożytnego świata” staną się bardzo popularne i znajdą się w szerokim obiegu, mógłbym zechcieć umożliwić publicznym użytkownikom deklarowanie ich we własnych dokumentach XML przy wykorzystaniu formalnego identyfikatora publicznego (nazwy, którą utworzyłem w podrozdziale „Nazywanie publicznego zewnętrznego DTD”). Rysunek 8.9. Tym razem parser XML wykorzysta publiczny identyfikator i spróbuje odnaleźć (prawdopodobnie w repozytorium publicznym) wskazane DTD. Jeśli ta operacja nie zakończy się powodzeniem, parser wykorzysta DTD wskazane danym adresem URI
Aby zadeklarować publiczne zewnętrzne DTD: 1. Wpisz
4. Wpisz "dtd.uri", gdzie dtd.uri jest lokalizacją DTD na serwerze publicznym. 5. Wpisz >, aby zakończyć deklarację typu dokumentu. 6. Następnie w deklaracji XML znajdującej się na początku dokumentu dodaj instrukcję standalone="no". Instrukcja ta informuje parser XML, że dany dokument będzie opierał się na pliku zewnętrznym. W naszym przypadku jest to publiczny zewnętrzny dokument DTD.
Wskazówka Kiedy parser XML znajduje formalny identyfikator publiczny, zazwyczaj stara się pobrać kopię danego DTD z możliwie najlepszego serwera. Prawdopodobnie będzie to serwer, który jest dostępny najbliżej w internecie lub posiada najbardziej aktualną wersję tego dokumentu DTD. Jeśli parser nie odnajdzie DTD na podstawie FPI, może wtedy skorzystać z URI.
127
Deklarowanie publicznego zewnętrznego DTD
3. Dalej wpisz "FPI", gdzie FPI jest formalnym identyfikatorem publicznym dla tego DTD (patrz podrozdział „Nazywanie publicznego zewnętrznego DTD”).
Rozdział 8.
Wady i zalety DTD Dokumenty DTD są schematami. Określają elementy, atrybuty i relacje, które powinien zawierać poprawny dokument XML. Dokumenty DTD dają wiele możliwości i są bardzo użyteczne. Istnieją jednak również inne języki schematów dla XML. Najbardziej znaną i najczęściej używaną alternatywą jest XML Schema, a każdy z języków schematów ma pewne koszty i przynosi określone korzyści. XML Schema został omówiony w kolejnej części książki.
Niektóre zalety korzystania z DTD: Dokumenty te są spójne i łatwe do zrozumienia przy niewielkiej liczbie wskazówek. Można je definiować, wplatając w kod (wewnętrzne DTD), co przyspiesza przygotowanie dokumentów. Pozwalają na definiowanie encji (patrz rozdział 7.). Są prawdopodobnie najbardziej powszechnie akceptowane i są obsługiwane przez większość parserów XML.
Niektóre wady korzystania z DTD:
Wady i zalety DTD
Nie są pisane z wykorzystaniem składni XML i wymagają obsługi dodatkowych języków przez parsery. Nie obsługują przestrzeni nazw (patrz rozdziały 12. i 13.). Nie posiadają typów danych (nie ma wymagania, aby dane były liczbą całkowitą, ciągiem znaków, datą itd.), co zmniejsza moc walidacji. Mają ograniczoną zdolność do określania, jak wiele elementów-dzieci może być zagnieżdżonych w danym elemencie-rodzicu.
128
XML Schema
IV
Część IV XML Schema
Rozdział 9.
Podstawy XML Schema
131
Rozdział 10. Definiowanie typów prostych
137
Rozdział 11. Definiowanie typów złożonych
155
129
Rozdział x.
130
Podstawy XML Schema
9
Rozdział 9. Podstawy XML Schema [RS1] Specyfikacja XML obejmuje składnię dla języka schematów, który jest sposobem definiowania, co powinien zawierać prawidłowy dokument XML. Język ten, znany jako DTD (definicja typu dokumentu), umożliwia użytkownikom definiowanie dla każdej wymaganej aplikacji XML elementów i atrybutów oraz ich wzajemnej relacji (patrz część III).
XML Schema, napisany w samym języku XML, jest bardziej zaawansowany i wydajniejszy niż DTD. Do przykładowych mocnych stron XML Schema można zaliczyć system typów danych, który pozwala określać, kiedy element powinien zawierać np. liczbę całkowitą, przedział czasu lub ciąg znaków. Język ten obsługuje przestrzenie nazw, które zostały omówione w rozdziałach 12. i 13. Pozwala również definiować zarówno elementy lokalne, jak i globalne, dzięki czemu dwa elementy mogą mieć różne definicje, chociaż posiadają tę samą nazwę. W skrócie XML Schema daje większą kontrolę nad zawartością dokumentu XML, a w niedalekiej przyszłości prawdopodobnie zastąpi DTD jako najszerzej akceptowany język schematu.
131
Podstawy XML Schema
W roku 2001 organizacja W3C opracowała nowy język schematów, aby usunąć wiele niedociągnięć charakterystycznych dla DTD (patrz rozdział 8., podrozdział „Wady i zalety DTD”). Ten język schematów został nazwany XML Schema, czyli Schemat XML, co może być wprawdzie nieco mylące, ponieważ DTD jest rodzajem schematu XML (pisane małą literą). Mimo to nadal najczęściej stosowaną nazwą jest XML Schema, choć czasem stosuje się również określenie XML Schema Definition (XSD), czyli Definicja Schematu XML. Obecnie, wraz z pojawieniem się wersji 1.1, język ten jest określany jako XML Schema Definition Language (XSDL), czyli Język Definicji Schematu XML. Jednak na potrzeby tej książki będę się posługiwał nazwą XML Schema, która jest nadal najbardziej rozpowszechniona spośród wszystkich tych nazw.
Rozdział 9.
Praca z XML Schema
Praca z XML Schema
XML Schema określa strukturę prawidłowych dokumentów XML (rysunek 9.1), definiując zbiór elementów, ich wzajemne relacje oraz atrybuty, które elementy te mogą zawierać. W DTD wszystkie elementy XML są definiowane za pomocą jednego typu elementów. W XML Schema element XML może być zdefiniowany Rysunek 9.1. Oto jeden z pierwszych dokumentów jako typ prosty lub typ złożony. Zasadniczo typ prosty XML wykorzystanych w tej książce (ang. simple type) jest elementem XML zawierającym jedynie tekst, podczas gdy element złożony (ang. complex type) jest elementem XML zawierającym elementy-dzieci i (lub) atrybuty. Przyjrzyjmy się bliżej typom prostym. Jak już wspomniano, w XML Schema typem prostym jest element zawierający jedynie tekst. W DTD element wyłącznie tekstowy jest definiowany jako #PCDATA, co oznacza, że jego zawartością może być nazwa, liczba, data lub praktycznie cokolwiek innego. W XML Schema możesz (a właściwie musisz) określić dokładnie, jakiego rodzaju zawartość ma posiadać dany element. Odbywa się to w wyniku przydzielenia elementowi typu danych (ang. data type). Istnieje wiele wbudowanych typów danych, takich jak ciąg znaków (ang. string), liczba całkowita (ang. integer) oraz data (ang. date) (rysunek 9.2). Możesz również tworzyć niestandardowe typy danych, aby zwiększyć jeszcze kontrolę nad zawartością elementów. O ile elementy będące typami prostymi opisują zawartość tekstową dokumentu XML, to elementy będące typami złożonymi opisują jego strukturę (rysunek 9.3). Istnieją cztery rodzaje elementów będących typami złożonymi. Są to elementy zawierające elementy-dzieci, elementy zawierające elementy-dzieci i tekst, elementy zawierające tylko tekst oraz elementy puste. Bardziej szczegółowe informacje na ten temat znajdziesz w rozdziale 11., „Definiowanie typów złożonych”.
Rysunek 9.2. Te elementy zostały zdefiniowane za pomocą wbudowanych prostych typów danych XML Schema. Elementy nazwa i lokalizacja muszą być ciągami znaków, a element wysokosc musi być liczbą całkowitą
Rysunek 9.3. Ta definicja typu złożonego definiuje za pomocą XML Schema element cud, który ma zawierać sekwencję elementów (sekwencja elementów-dzieci nie została pokazana na tym rysunku)
Rysunek 9.4. Łącząc kody z rysunków 9.2 i 9.3, uzyskamy większą część dokumentu XML Schema, który definiuje dokument XML pokazany na rysunku 9.1. Reszta kodu tego XML Schema została objaśniona w kolejnym podrozdziale
132
Podstawy XML Schema Wskazówki Jedną z zalet XML Schema jest to, że język ten wykorzystuje składnię XML-a, co już prawdopodobnie wiesz! Ponieważ XML Schema jest dokumentem XML, musi rozpoczynać się od deklaracji XML, posiadać jeden element główny i być poprawny składniowo, tak jak wszystkie inne dokumenty XML (rysunek 9.4).
133
Praca z XML Schema
Co ciekawe, gdy publikowana była pierwsza wersja tej książki, XML Schema był wciąż działającą wersją roboczą. Obecnie organizacja W3C pracuje nad zakończeniem XML Schema w wersji 1.1. Wersja ta jest opracowywana, aby poprawić błędy i wprowadzić ulepszenie tam, gdzie jest to możliwe, zachowując przy tym ten sam zakres możliwości co wersja 1.0 (i utrzymując w znacznej mierze kompatybilność z tą wersją). Aktualne informacje dotyczące wersji znajdziesz na stronie grupy roboczej XML Schema organizacji W3C: http://www.w3.org/XML/Schema.
Rozdział 9.
Rozpoczynanie prostego dokumentu XML Schema XML Schema jest dokumentem wyłącznie tekstowym i rozpoczyna się standardową deklaracją XML. Zwyczajowo jest on zapisywany z rozszerzeniem .xsd, a jego elementem głównym musi być schema.
Aby rozpocząć dokument XML Schema:
Rysunek 9.5. XML Schema jest sam w sobie dokumentem XML. Elementem głównym musi być schema, a jako przestrzeń nazw deklarowana jest przestrzeń nazw XML Schema organizacji W3C
Rozpoczynanie prostego dokumentu XML
1. Na początku dokumentu wpisz . 2. Wpisz
aby zadeklarować przestrzeń nazw XML Schema (xmlns). Jest to również deklaracja, że elementy i typy danych będące częścią tej przestrzeni nazw powinny być poprzedzane prefiksem xs:, tak jak widziałeś w punkcie 2. tej procedury. 4. Wpisz >, aby zamknąć znacznik elementu głównego. 5. Zostaw kilka pustych wierszy na wpisanie reguł XML Schema. 6. Wpisz , aby zakończyć element główny oraz sam dokument XML Schema (rysunek 9.5).
Wskazówki Przestrzeń nazw (ang. namespace) jest „przestrzenią”, w której rezydują nazwy. Nazwy będące częścią jednej przestrzeni nazw nie są tymi samymi nazwami, co nazwy będące częścią innej przestrzeni nazw (nawet jeśli pisane są w ten sam sposób). Organizacja W3C stworzyła przestrzeń nazw, która zawiera wszystkie elementy i typy danych XML Schema. Ta przestrzeń nazw została zadeklarowana w punkcie 3. powyższej procedury. Po zadeklarowaniu tej przestrzeni nazw każdy element i typ danych powinien być poprzedzany prefiksem przestrzeni nazw xs: (rysunek 9.6). Ma to na celu wskazanie, że dany element i typ danych powinien być traktowany jako część przestrzeni nazw XML Schema organizacji W3C. Przestrzenie nazw zostały szerzej omówione w rozdziałach 12. i 13.
134
Rysunek 9.6. Tutaj połączyłem fragment XML Schema z rysunku 9.4 z poprawną deklaracją XML i definicją elementu głównego xs:schema. Poprzedziłem również wszystkie elementy XML Schema prefiksem xs: przestrzeni nazw XML Schema
Podstawy XML Schema
Wiązanie XML Schema z dokumentem XML
Rysunek 9.7. Aby powiązać XML Schema z dokumentem XML, musisz w elemencie głównym tego dokumentu XML zadeklarować lokalizację danego dokumentu XML Schema
Aby przeprowadzić walidację dokumentu XML względem XML Schema, musisz w samym dokumencie XML określić lokalizację dokumentu XML Schema.
Aby zadeklarować dokument XML Schema i jego lokalizację:
2. Wpisz xsi:noNamespaceSchemaLocation=.
Rysunek 9.8. Tutaj dodałem do dokumentu z rysunku 9.1 powiązanie z określonym dokumentem XML Schema. Po przeprowadzeniu walidacji względem dokumentu XML Schema z rysunku 9.6 dany dokument XML okaże się prawidłowy.
3. Na koniec wpisz "xsd.uri", gdzie xsd.uri jest lokalizacją pliku XML Schema, względem którego będziesz przeprowadzał walidację swojego pliku XML (rysunek 9.7).
Wskazówki Większość parserów XML może przeprowadzać walidację dokumentów XML względem zadeklarowanych dokumentów XML Schema (rysunek 9.8). Jeśli parser XML, którego używasz, nie oferuje takiej funkcji, możesz skorzystać z odpowiednich walidatorów dostępnych online. Organizacja W3C udostępnia swój walidator na stronie http://www.w3.org/2001/03/webdata/xsv. Listę innych walidatorów znajdziesz na stronie http://www.w3.org/XML/Schema. Adres "xsd.uri" w punkcie 3. powyższej procedury może odnosić się do pliku zamieszczonego w internecie, w sieci lokalnej lub znajdującego się na Twoim komputerze. Punkt 1. powyższej procedury deklaruje przestrzeń nazw instancji XML Schema, która obejmuje atrybut xsi:noNamespaceSchemaLocation wykorzystany w punkcie 2. oraz kilka innych atrybutów przestrzeni nazw. Przestrzenie nazw zostały omówione w rozdziałach 12. i 13.
135
Wiązanie XML Schema z dokumentem XML
1. W obrębie definicji elementu głównego dokumentu XML wpisz xmlns:xsi="http://www.w3.org/2001/XMLSchema". Pozwala to zdefiniować lokalizację Twojego XML w dwóch kolejnych krokach.
Rozdział 9.
Dodawanie adnotacji do schematów Ponieważ XML Schema jest dokumentem XML, możesz w swoich dokumentach XML umieszczać standardowe komentarze XML (patrz rozdział 1., podrozdział „Pisanie komentarzy”).
Dodawanie adnotacji do schematów
Poza tymi standardowymi komentarzami, XML Schema oferuje możliwość dodawania do dokumentów bardziej strukturalizowanych komentarzy. O ile komentarze XML mogą być czytane przez użytkowników, to są one ignorowane przez parsery i często nie są przekazywane w trakcie transformacji XML. Komentarze XML Schema Rysunek 9.9. Adnotacje pomagają udokumentować (zwane adnotacjami) mogą być parsowane i przetwarzane, XML Schema. Może to być pomocne przy ponieważ same są elementami (rysunek 9.9). wprowadzaniu poprawek w przyszłości
Aby dodać adnotację w dokumencie XML Schema: 1. Wpisz . 2. Następnie wpisz , aby rozpocząć komentarz. 3. Wpisz swój komentarz. 4. Wpisz , aby zakończyć komentarz. 5. Wpisz , aby zakończyć adnotację.
Wskazówki Bez względu na to, czy stosujesz komentarze XML, czy adnotacje XML Schema (lub obydwie te formy), opatrywanie dokumentów XML Schema komentarzami ułatwia pracę z tymi dokumentami. Adnotacje możesz tworzyć w dowolnym miejscu dokumentu XML Schema po elemencie głównym. Mogą one być umieszczane zaraz po elemencie głównym xs:schema (jako komentarz do całego schematu) lub po definicjach poszczególnych elementów (jako informacje na temat tych elementów). Mogą być także umieszczane w obydwu tych miejscach jednocześnie.
136
Definiowanie typów prostych
10
Rozdział 10. Definiowanie typów prostych [RS1] W XML Schema element zdefiniowany jako typ prosty może zawierać wyłącznie tekst. Innymi słowy, nie może posiadać atrybutów ani elementów-dzieci. Jednak stwierdzenie, że element taki może zawierać tylko tekst, jest nieco mylące. Należałoby raczej powiedzieć, że może on zawierać jedynie wartość, ponieważ W XML Schema możesz zadeklarować konkretny rodzaj tekstu. Inaczej mówiąc, możesz zadeklarować, że element zawiera tylko liczby, tylko daty, tylko wartości logiczne itd. XML Schema posiada duży zbiór wbudowanych typów prostych dla najbardziej powszechnych rodzajów tekstu. Zbiór ten obejmuje ciągi znaków, wartości logiczne, adresy URL, różne formaty daty i czasu oraz wszelkiego rodzaju liczby.
137
Definiowanie
Do tych typów prostych możesz również stosować pewne restrykcje lub określać konkretne aspekty, aby dalej te typy ograniczyć. W ten sposób możesz faktycznie tworzyć własne niestandardowe typy proste. Możesz na przykład zechcieć zdefiniować, że dany element zawiera ciąg znaków odpowiadający określonemu wzorcowi (jak numer telefonu lub kod produktu). Mógłbyś również zechcieć zdefiniować, że dany element może zawierać jedynie konkretny zestaw dat. Funkcja ta pozwala Ci bardziej konkretnie i efektywnie definiować dopuszczalne wartości elementów składających się na poprawny dokument XML.
Rozdział 10.
Definiowanie elementu jako typu prostego Jak już wspomniano, w XML Schema element będący typem prostym może zawierać jedynie wartość. Nie może on zawierać żadnych elementów-dzieci ani żadnych atrybutów. W typach prostych możesz definiować, że dany element XML będzie ciągiem znaków, liczbą całkowitą, wartością logiczną (rysunek 10.1) lub jednym z pozostałych prostych typów danych wbudowanych w język XML Schema (patrz podrozdziały „Używanie typów daty i czasu” i „Używanie typów liczbowych”).
Rysunek 10.1. Definiując element w dokumencie XML Schema, identyfikujesz nazwę tego elementu w dokumencie XML oraz rodzaj zawartości, jaką ten element powinien posiadać (jego prosty typ danych). W tym przypadku zawartość elementu wysokosc jest zdefiniowana jako ciąg znaków, a zawartość elementu rok_wybudowania jako liczba całkowita
Definiowanie elementu jako typu prostego
Aby zdefiniować element jako typ prosty: 1. Wpisz
Rysunek 10.2. Ciąg jest serią liter, liczb i (lub) symboli. Liczba całkowita jest liczbą bez części ułamkowych. Z tego względu obydwa elementy (wysokosc i rok_wybudowania) traktowane są jako prawidłowe po przeprowadzeniu porównania z definicją XML Schema przedstawioną na rysunku 10.1
3. Dalej wpisz type=". 4. Teraz, aby określić prosty typ danych swojego elementu XML, wpisz: xs:string, jeśli element będzie zawierał ciąg
znaków;
xs:decimal, jeśli element będzie zawierał ułamek
dziesiętny. Pozostałe dopuszczalne typy liczb zostały opisane w podrozdziale „Używanie typów liczbowych”; xs:boolean, jeśli element będzie zawierał wartości
prawda (ang. true) lub fałsz (ang. false) (albo 1 lub 0);
xs:date, jeśli element będzie datą. Pozostałe
dopuszczalne typy dat zostały opisane w podrozdziale „Używanie typów daty i czasu”;
xs:time, jeśli element będzie czasem dnia. Pozostałe
dopuszczalne typy czasu zostały opisane w podrozdziale „Używanie typów daty i czasu”;
xs:anyURI (tak jak w URI, a nie w URL), jeśli
element będzie zawierał odwołanie do pliku w internecie, w sieci lokalnej lub nawet na danym komputerze. 5. Następnie wpisz ", aby zakończyć typ danych. 6. Wreszcie wpisz />, aby zakończyć definicję.
138
Rysunek 10.3. W tym fragmencie kodu XML element wysokosc wygląda, jakby był niepoprawny względem definicji XML Schema przedstawionej na rysunku 10.1. W rzeczywistości jednak jest on poprawny, ponieważ liczba jest ciągiem (choć nie wszystkie ciągi są liczbami). Z kolei element rok_wybudowania jest niepoprawny. Fraza „dawno temu” nie jest liczbą całkowitą
Definiowanie typów prostych Wskazówki
Rysunek 10.4. W tym fragmencie dokumentu XML Schema element ostatnia_modyfikcja został zdefiniowany w taki sposób, aby zawierał datę. Do tego celu wykorzystuje się wbudowany typ prosty XML Schema: date
Rysunek 10.6. Chociaż element ostatnia modyfikacja zawiera datę, nie jest faktycznie poprawny, ponieważ data nie jest zapisana w odpowiednim formacie
Wbudowane typy proste zawsze rozpoczynają się od prefiksu przestrzeni nazw XML Schema, która jest zazwyczaj deklarowana jako xs: (rysunek 10.4). Przestrzenie nazw zostały omówione szczegółowo w części V tej książki. Możesz również tworzyć niestandardowe typy proste poprzez rozszerzanie wbudowanych typów prostych. Więcej szczegółowych informacji na ten temat znajdziesz w podrozdziale „Wywodzenie niestandardowych typów prostych”. Atrybuty same w sobie są również typami prostymi (ponieważ mogą zawierać tylko wartości, a nie mogą zawierać własnych elementów-dzieci ani atrybutów) i są deklarowane w taki sam sposób, jak elementy będące typami prostymi. Zostały one omówione w rozdziale 11., w podrozdziale „Definiowanie atrybutów”. Podsumujmy: elementy będące typami prostymi nie mogą zawierać elementów-dzieci ani atrybutów. Jeśli element musi zawierać elementy-dzieci lub atrybuty, powinien być zdefiniowany jako typ złożony. Więcej szczegółów na ten temat znajdziesz w rozdziale 11., „Definiowanie typów złożonych”.
139
Definiowanie elementu jako typu prostego
Rysunek 10.5. W tym fragmencie kodu XML element ostatnia_modyfikacja jest poprawny względem definicji XML Schema przedstawionej na rysunku 10.4. Jest tak dlatego, że zawiera on datę w odpowiednim formacie. W XML Schema format daty to RRRR-MM-DD (czyli czterocyfrowe oznaczenie roku, myślnik, dwucyfrowa reprezentacja miesiąca, myślnik oraz dwucyfrowe oznaczenie dnia). Przy wszystkich wbudowanych typach prostych istotna jest znajomość właściwego formatu, w którym powinny być zapisane dane
Istnieje wiele innych wbudowanych typów prostych. Całą ich listę znajdziesz na stronie www.w3.org/TR/xmlschema-2/#built-in-datatypes.
Rozdział 10.
Używanie typów daty i czasu Poza prostymi typami danych, które właśnie zostały omówione, XML Schema posiada kilka bardziej wyrafinowanych typów danych dla określania daty i czasu. Aby zdefiniować element XML z wykorzystaniem jednego z tych typów, zastąp punkt 4. procedury opisanej w podrozdziale „Definiowanie elementu jako typu prostego” jedną z odpowiadających Ci opcji wymienionych poniżej.
Aby zastosować typy daty i czasu:
Rysunek 10.7. Albert Einstein urodził się 14 marca 1879 r. (W roku 1921 Einstein otrzymał za swoją pracę Nagrodę Nobla w kategorii fizyka teoretyczna, a w roku 1999 został wybrany osobowością stulecia przez czasopismo Time)
Używanie typów daty i czasu
Użyj typu xs:date, aby określić, że zawartością danego elementu ma być data (rysunek 10.7). Musi ona mieć format RRRR-MM-DD, więc data 23 maja 2008 r. powinna być zapisana jako 2008-05-23. Użyj typu xs:time, aby określić, że zawartością danego elementu powinien być czas dnia (rysunek 10.8). Musi on mieć format gg:mm:ss, więc godzina 16:21 powinna być zapisana jako 16:21:00. (Czas jest zapisywany w formacie zwanym „wojskowym” lub uniwersalnym). Użyj typu xs:dateTime, aby określić, że zawartością danego elementu powinna być data i czas (rysunek 10.9). Wymagany format to RRRR-MM-DDTgg:mm:ss, więc godzina 16:21 dnia 23 maja 2008 r. powinna być zapisana następująco: 2008-05-23T16:21:00. Użyj typu xs:duration, aby określić, że zawartością danego elementu powinien być przedział czasu (rysunek 10.10). Czas trwania musi mieć format PnYnMnDTnHnMnS, gdzie P jest zawsze wymagane (i oznacza przedział czasu), a T jest wymagane tylko wtedy, gdy podajesz jakieś jednostki czasu. Każdy argument n wskazuje liczbę występujących jednostek: lat (Y), miesięcy (M), dni (D), godzin (H), minut (M) i sekund (S). Argument n nie jest opcjonalny i musi być nieujemną liczbą całkowitą. Przykładowo przedział czasu trwający 3 miesiące, 4 dni, 6 godzin i 17 minut powinien być zapisany jako P3M4DT6H17M, a 90 dni zapiszemy jako P90D. Opcjonalnie możesz również dodać na początku znak myślnika, aby wskazać, że czas trwania podawany jest wstecz (a nie w przód). Przykładowo –P90D będzie oznaczać: 90 dni temu.
140
Rysunek 10.8. Obecnie uważa się, że obraz „Wschód księżyca” autorstwa malarza ekspresjonisty Vincenta van Gogha przedstawia nocne niebo w Saint-Rémy uchwycone o godzinie 21:08 13 lipca 1889 r., choć początkowo twierdzono, że jest to zachodzące słońce. (Zwróć uwagę, że czas jest zapisany w formacie „wojskowym”, czyli uniwersalnym)
Rysunek 10.9. Martin Luther King Junior, znany lider amerykańskiego ruchu na rzecz swobód obywatelskich, został zamordowany o godzinie 6:01 4 kwietnia 1968 r. Zdarzenie to miało miejsce w Tennessee, więc czas został zapisany z dodatkowym parametrem –05:00, który wskazuje pięciogodzinne przesunięcie względem czasu UTC (patrz punkt „Wskazówki” w dalszej części tego podrozdziału)
Rysunek 10.10. Mahatma Gandhi był znanym na świecie liderem, który upowszechnił ideę oporu poprzez stosowanie nieposłuszeństwa obywatelskiego. W roku 1939 podczas pobytu w więzieniu odbył pięciodniowy strajk głodowy w imię pokoju
Definiowanie typów prostych Użyj typu xs:gYear, aby określić, że zawartością danego elementu powinien być rok (rysunek 10.11). Powinien on mieć format RRRR.
Rysunek 10.11. Prace nad radioaktywnością przyniosły Marii Skłodowskiej-Curie dwie Nagrody Nobla: w 1903 i w 1911 r. W roku 1995 jej prochy przeniesiono do Panteonu w Paryżu, dzięki czemu stała się pierwszą w historii kobietą uhonorowaną w ten sposób
Rysunek 10.13. 29 lutego jest dniem przestępnym. Występuje co cztery lata (z wyjątkiem pełnych stuleci niepodzielnych przez 400, takich jak rok 1800) i pozwala na synchronizację kalendarza z cyklem obiegu Ziemi wokół Słońca
Rysunek 10.14. Słowo „idy” pochodzi od łacińskiego słowa „idus” oznaczającego „podział na pół”. Często uważa się, że pojęcie to oznacza piętnasty dzień miesiąca, z uwagi na dzień zabójstwa Juliusza Cezara w idy marcowe, czyli 15 marca. W rzeczywistości w czasach rzymskich idy wypadały 15 dnia marca, maja, lipca i października, ale 13 dnia w przypadku pozostałych miesięcy
Użyj typu xs:gMonth, aby określić, że zawartością danego elementu powinien być miesiąc (rysunek 10.12). Powinien on mieć format --MM. (Na początku występują dwie kreski. Jedna reprezentuje „brakujący” rok, a druga spełnia rolę separatora). W ten sposób np. kwiecień zapisalibyśmy jako --04. Użyj typu xs:gMonthDay, aby określić, że zawartością danego elementu powinien być dzień miesiąca (rysunek 10.13). Powinien on mieć format --MM-DD. (Na początku występują dwie kreski. Jedna reprezentuje „brakujący” rok, a druga spełnia rolę separatora). W ten sposób np. 14 września zapisalibyśmy jako --09-14. Użyj typu xs:gDay, aby określić, że zawartością danego elementu powinien być dzień określonego miesiąca (rysunek 10.14). Powinien on mieć format ---DD. (Na początku występują trzy kreski. Dwie z nich reprezentują „brakujące” elementy, a jedna spełnia rolę separatora). W ten sposób np. siódmy dzień danego miesiąca zapisalibyśmy jako ---07.
Wskazówki Wszystkie typy czasu mogą również kończyć się opcjonalnym wskaźnikiem strefy czasowej. Dla określenia strefy czasowej UTC należy wpisać literę Z, a w celu określenia przesunięcia względem strefy UTC można użyć formatów -gg:mm lub +gg:mm. Czas UTC (ang. Coordinated Universal Time), czyli uniwersalny czas koordynowany, jest tożsamy z czasem Greenwich (ang. Greenwich Mean Time). Typy czasu mogą również zawierać ułamki sekund w formacie gg:mm:ss.sss. Możesz podawać tyle cyfr, ile chcesz. Litera g w nazwach typów prostych omówionych w tym podrozdziale pochodzi od słowa „gregoriański” (ang. Gregorian). Jest to odniesienie do kalendarza gregoriańskiego, który jest obecnie najbardziej powszechnie stosowanym kalendarzem.
141
Używanie typów daty i czasu
Rysunek 10.12. Nostradamus był aptekarzem, ale najbardziej jest znany ze swojego zbioru przepowiedni. Choć wiadomo, że urodził się w grudniu, historycy nie mają pewności, który był to konkretnie dzień miesiąca
Użyj typu xs:gYearMonth, aby określić, że zawartością danego elementu powinien być rok i miesiąc. Wymagany format to RRRR-MM.
Rozdział 10.
Używanie typów liczbowych XML Schema oferuje również kilka bardziej wyrafinowanych typów prostych dla liczb (rysunek 10.15). Aby zdefiniować dopuszczalną zawartość dla elementu XML z wykorzystaniem jednego z tych typów, zastąp punkt 4. procedury opisanej w podrozdziale „Definiowanie elementu jako typu prostego” jedną z odpowiadających Ci opcji wymienionych poniżej.
Aby zastosować typy liczbowe:
Rysunek 10.15. Bardziej precyzyjne jest wymaganie dla elementu lata_przetrwane dodatniej liczby całkowitej. (Liczba całkowita, lub nawet nieujemna liczba całkowita, byłaby niewłaściwa, dopuszczając albo wartość ujemną, albo nawet zero). Dla elementu wysokosc można by zastosować precyzję ułamka dziesiętnego
Użyj typu xs:decimal, jeśli chcesz, aby zawartością elementu były dodatnie lub ujemne liczby, które mają skończoną liczbę cyfr przed opcjonalnym przecinkiem i po nim, np. 4.26, –100 lub 0.
Używanie typów liczbowych
Użyj typu xs:integer, jeśli chcesz, aby zawartością elementu były dodatnie lub ujemne liczby całkowite, czyli liczby, które nie mają części ułamkowych, np. 542 lub –7. Użyj typu xs:positiveInteger (1, 2 itd.), xs:negativeInteger (–1, –2 itd.), xs:nonPositiveInteger (0, –1, –2 itd.) lub xs:nonNegativeInteger (0, 1, 2 itd.), jeśli chcesz, aby zawartością elementu był jeden z tych rodzajów liczb. Użyj typu xs:int, jeśli chcesz, aby zawartością elementu była 32-bitowa liczba całkowita ze znakiem, często używana w polach ID (identyfikatorów) baz danych. Użyj typu xs:float, jeśli chcesz, żeby zawartością elementu była 32-bitowa liczba zmiennoprzecinkowa pojedynczej precyzji, np. 43e–2. Obejmuje to dodatnie i ujemne zero (0 i –0), dodatnią i ujemną nieskończoność (INF i –INF) oraz wartość typu „nieliczba” (NaN).
Wskazówki Na stronie http://www.w3.org/TR/xmlschema-2/ znajdziesz objaśnienie pozostałych typów liczbowych, takich jak short, byte, oraz wersje bez znaku dla tych typów, które tutaj opisałem. Opisanych w tym i poprzednim podrozdziale typów możesz używać również jako podstawy do definiowania własnych typów danych (patrz podrozdział „Wywodzenie niestandardowych typów prostych”).
142
Rysunek 10.16. Według definicji XML Schema przedstawionej na rysunku 10.15, dopóki wartość elementu lata_przetrwane jest liczbą całkowitą większą niż 0, element ten jest poprawny. Element wysokosc może mieć zarówno część ułamkową, jak i całkowitą
Rysunek 10.17. Element lata_przetrwane z tego fragmentu kodu jest niepoprawny. Ponieważ został on zdefiniowany jako liczba całkowita, nie może posiadać części ułamkowych. Z kolei element wysokosc jest poprawny, ponieważ liczba ułamkowa może mieć część ułamkową, ale nie musi
Definiowanie typów prostych
Rysunek 10.18. Zdefiniowanie elementu sposob_zniszczenia z wartością ustaloną oznacza, że kiedy pojawia się on w dokumencie XML, musi być ciągiem „pożar” (lub być pusty, co powoduje, że jest traktowany tak, jakby zawierał ciąg „pożar”)
Predefiniowanie zawartości elementu Istnieją dwa sposoby wykorzystania XML Schema do predefiniowania tego, jaka powinna być zawartość elementu. Możesz ustawić wartość elementu, wykorzystując wartość ustaloną (ang. fixed) (rysunek 10.18) lub, jeśli element jest pusty albo pomijany, możesz ustawić jego wartość za pomocą wartości domyślnej (ang. default) (rysunek 10.20).
Aby ustawić ustaloną wartość elementu: 1. W obrębie znacznika elementu wpisz fixed=.
Aby ustawić domyślną wartość elementu: 1. W obrębie znacznika elementu wpisz default=. 2. Następnie wpisz "wartość", gdzie wartość jest tym, co ma być wartością elementu, jeśli ten element jest pusty lub pomijany.
Wskazówki Rysunek 10.20. Zdefiniowanie elementu sposob_zniszczenia z wartością domyślną oznacza, że wartość ta będzie ustawiona jako zawartość początkowa, bez względu na to, czy element sposob_zniszczenia pojawi się w dokumencie XML
Atrybut fixed ustawia wartość tylko wtedy, kiedy dany element faktycznie pojawia się w dokumencie XML jako element pusty (rysunek 10.19). Jeśli element jest pomijany, nie jest ustawiana żadna wartość. Jeśli dany element ma wartość inną niż ustalona, wtedy dany dokument XML nie jest poprawny. Atrybut default ustawia wartość, jeśli dany element pojawia się w dokumencie XML jako element pusty lub jest pomijany (rysunek 10.21). Jeśli dany element ma wartość inną niż wartość domyślna, dokument XML jest poprawny, a wartością tego elementu jest wartość określona w danym dokumencie XML.
Rysunek 10.21. Wszystkie te przykłady kodu XML są poprawne względem fragmentu XML Schema przedstawionego na rysunku 10.20. Atrybut default ustawia jedynie wartość początkową, ale każda inna wartość jest również akceptowana
Nie możesz jednocześnie ustawić atrybutów default i fixed. Ponieważ atrybuty te zaprzeczają sobie wzajemnie, procesor XML Schema nie dopuści do takiej sytuacji.
143
Predefiniowanie zawartości elementu
Rysunek 10.19. Pierwszy fragment kodu XML jest poprawny, ponieważ element sposob_zniszczenia odpowiada wartości ustalonej we fragmencie dokumentu XML Schema przedstawionym na rysunku 10.18. Drugi fragment kodu XML jest poprawny, ponieważ element ten jest pusty, więc automatycznie nadawana jest mu wartość ustalona. Element z trzeciego fragmentu nie jest poprawny, ponieważ nie odpowiada ustalonej wartości
2. Następnie wpisz "wartość", gdzie wartość jest tym, co ma być wartością elementu, żeby element ten mógł być uznany za prawidłowy (chyba że element jest pomijany w dokumencie XML, co również jest prawidłowe).
Rozdział 10.
Wywodzenie niestandardowych typów prostych Język XML Schema zawiera wiele wbudowanych typów prostych. Na bazie tych typów możesz wywodzić własne niestandardowe typy proste w tym języku.
Aby utworzyć niestandardowy typ prosty: 1. Najpierw określ nazwę elementu XML, który definiujesz za pomocą XML Schema. W tym celu wpisz , gdzie etykieta jest nazwą danego elementu XML (rysunek 10.22).
Wywodzenie niestandardowych typów prostych
2. Wpisz , aby rozpocząć tworzenie swojego niestandardowego typu prostego. 3. Wpisz , gdzie podstawa jest jednym z wbudowanych typów prostych, na bazie którego chcesz utworzyć swój typ niestandardowy. 4. Określ tyle restrykcji (lub aspektów), ile potrzeba do zdefiniowania Twojego nowego typu. Aspekty, służące do dostosowywania wbudowanych typów prostych, zostały omówione szczegółowo w podrozdziałach „Określanie zakresu dopuszczalnych wartości”, „Określanie zbioru dopuszczalnych wartości”, „Ograniczanie długości elementu”, „Określanie wzorca dla elementu” oraz „Ustawianie limitu cyfr w liczbie”. 5. Wpisz . 6. Wpisz , aby zakończyć swój nowy niestandardowy typ prosty. 7. Wreszcie wpisz , aby zakończyć definicję tego elementu.
Wskazówki Taki niestandardowy typ prosty jest zwany anonimowym typem niestandardowym (ang. anonymous custom type). Istnieje także coś, co określane jest nazwanym typem niestandardowym (patrz podrozdział „Wywodzenie nazwanych typów niestandardowych”). Różnica pomiędzy nimi polega na tym, że typy nazwane mogą być używane więcej niż raz (dzięki ustawieniu niestandardowej nazwy dla atrybutu type tego typu prostego), a typy anonimowe (nieposiadające nazwy) mogą być używane tylko dla elementu, w którym zostały zawarte. Możesz również tworzyć typy proste listy. Więcej informacji na ten temat znajdziesz w podrozdziale „Wywodzenie typu listy”.
144
Rysunek 10.22. Utworzyłem tutaj typ niestandardowy dla elementu dzieje. Zacząłem od podstawy typu prostego xs:string. Następnie rozszerzyłem ją, dodając restrykcję, która ogranicza długość zawartości do maksymalnie 1024 znaków
Definiowanie typów prostych
Wywodzenie nazwanych typów niestandardowych
Rysunek 10.23. Porównaj tę definicję typu niestandardowego z definicją elementu wykorzystującą typ niestandardowy, przedstawioną na rysunku 10.22. Definicja elementu dzieje w tych dwóch przykładach jest identyczna. Zasadnicza różnica jest taka, że definicja typu niestandardowego przedstawiona w tym przykładzie może być ponownie wykorzystana dla każdego innego elementu w Twoim dokumencie XML Schema. Zwróć uwagę, że atrybut name (nazwa) elementu xs:simpleType ma wartość typ_dzieje. Jest to nazwa, która może być użyta podczas odwoływania się do tego typu niestandardowego
Jeśli zamierzasz używać typu niestandardowego do definiowania więcej niż jednego w swoim XML Schema, możesz ten typ nazwać (rysunek 10.23). Wtedy za każdym razem, gdy będziesz chciał go użyć, możesz załączyć odsyłacz, który będzie wskazywał powiązanie pomiędzy elementem XML i Twoim nowym typem niestandardowym.
Aby utworzyć nazwany typ niestandardowy: 1. Wpisz , gdzie nazwa_typu_niestandardowego identyfikuje Twój
3. Wpisz , gdzie podstawa to typ prosty, na którym budujesz swój typ niestandardowy.
Rysunek 10.24. Mogę teraz użyć tego nowego typu niestandardowego o nazwie typ_dzieje w tylu definicjach elementów, w ilu będę chciał
4. Określ tyle restrykcji (lub aspektów), ile potrzeba do zdefiniowania Twojego nowego typu niestandardowego (patrz podrozdziały „Określanie zakresu dopuszczalnych wartości”, „Określanie zbioru dopuszczalnych wartości”, „Ograniczanie długości elementu”, „Określanie wzorca dla elementu” oraz „Ustawianie limitu cyfr w liczbie”). 5. Wpisz .
Wskazówki Po zdefiniowaniu własnego nazwanego typu niestandardowego możesz używać go zamiast typów prostych opisanych w podrozdziale „Definiowanie elementu jako typu prostego”. Zwróć uwagę, że do swojego nowego typu niestandardowego odwołujesz się, wpisując nazwa_typu_niestandardowego zamiast xs:nazwa_typu_niestandardowego. Jest tak dlatego, że prefiks xs: odnosi się do przestrzeni nazw XML Schema, a Twój nowy typ niestandardowy nie jest częścią tej przestrzeni. Więcej informacji na temat przestrzeni nazw znajdziesz w części V tej książki.
6. Wpisz , aby zakończyć definicję niestandardowego typu prostego. 7. Teraz, aby zastosować ten nowy typ niestandardowy do definicji elementu, powinieneś wpisać , gdzie nazwa_typu_niestandardowego jest nazwą utworzoną
w punkcie 2. (rysunek 10.24).
145
Wywodzenie typów niestandardowych
nowy niestandardowy typ prosty.
Rozdział 10.
Określanie zakresu dopuszczalnych wartości W XML Schema, poza definiowaniem typów elementów XML, możesz również nakładać restrykcje określające, co ma być uważane za poprawną zawartość. Restrykcje te zwane są aspektami (ang. facets). Używając aspektów, możesz tworzyć niestandardowe typy proste, tak jak to zostało omówione w podrozdziałach „Wywodzenie niestandardowych typów prostych” i „Wywodzenie niestandardowych typów nazwanych”.
Określanie zakresu dopuszczalnych wartości
Jednym z najbardziej typowych stosowanych aspektów jest określenie najwyższej lub najniższej wartości (albo obydwu naraz), którą może posiadać dokument XML, aby został uznany za poprawny.
Rysunek 10.25. Aspekt xs:maxInclusive określa największą dopuszczalną wartość dla elementu. W tym przypadku jest to rekord wszech czasów Hanka Aarona, który w Major League Baseball zaliczył całkowitą liczbę 6856 baz
Aby określić najwyższą możliwą wartość: 1. W obrębie definicji typu niestandardowego (w miejsce punktu 4. w procedurach opisanych w podrozdziałach „Wywodzenie niestandardowych typów prostych” i „Wywodzenie niestandardowych typów nazwanych”) wpisz
Rysunek 10.26. Obydwa przedstawione elementy zaliczone_bazy są poprawne względem dokumentu XML Schema przedstawionego na rysunku 10.25, ponieważ wartość pierwszego jest mniejsza od wartości xs:maxInclusive, a wartość drugiego jest równa tej wartości
2. Następnie wpisz value="n", gdzie zawartość elementu musi być mniejsza lub równa n, aby była poprawna. 3. Wreszcie wpisz />, aby zakończyć aspekt xs:maxInclusive (rysunek 10.25).
Inny sposób określenia najwyższej możliwej wartości 1. W obrębie definicji typu niestandardowego (w miejsce punktu 4. w procedurach opisanych w podrozdziałach „Wywodzenie niestandardowych typów prostych” i „Wywodzenie niestandardowych typów nazwanych”) wpisz , aby zakończyć aspekt xs:maxExclusive (rysunek 10.27).
146
Rysunek 10.27. Ten typ niestandardowy XML Schema wykorzystuje aspekt xs:maxExclusive do określenia, że najwyższa akceptowalna wartość jest o jeden mniejsza niż maksymalna. Oznacza to, że element zaliczone_bazy musi być mniejszy niż (ale nie równy) wartość xs:maxExclusive, czyli rekord Hanka Aarona
Rysunek 10.28. Przy zmienionym XML Schema z rysunku 10.27 pierwszy element zaliczone_bazy jest nadal poprawny, podczas gdy drugi już nie. (I nikt jeszcze nie wyrównał ani nie pobił rekordu całkowitej liczby zaliczonych baz, ustanowionego przez Hanka Aarona!)
Definiowanie typów prostych Aby określić najniższą możliwą wartość:
Rysunek 10.29. Tutaj aspekt xs:minInclusive określa najwcześniejszy dzien_gry: debiut Hanka Aarona w Major League 13 kwietnia 1954 r.
1. W obrębie definicji typu niestandardowego (w miejsce punktu 4. w procedurach opisanych w podrozdziałach „Wywodzenie niestandardowych typów prostych” i „Wywodzenie niestandardowych typów nazwanych”) wpisz , aby zakończyć aspekt xs:minInclusive (rysunek 10.29).
Rysunek 10.30. Obydwa te fragmenty kodu są poprawne względem definicji XML Schema przedstawionej na rysunku 10.29
1. W obrębie definicji typu niestandardowego (w miejsce punktu 4. w procedurach opisanych w podrozdziałach „Wywodzenie niestandardowych typów prostych” i „Wywodzenie niestandardowych typów nazwanych”) wpisz , aby zakończyć aspekt xs:minExclusive.
Rysunek 10.31. Ten typ niestandardowy XML Schema wykorzystuje obydwa aspekty, xs:minInclusive i xs:maxInclusive, do określenia, że poprawny element powinien zawierać datę, która zawiera się w przedziale od 13 kwietnia 1954 r. (włącznie) do 3 października 1976 r. (włącznie). Jest to okres kariery Hanka Aarona w Major League
Wskazówki O ile nie możesz użyć dwóch limitów minimalnych (lub dwóch limitów maksymalnych) jednocześnie dla tego samego typu (nie miałoby to sensu), możesz mieszać i dobierać w pary minima i maksima, tak jak jest Ci to potrzebne (rysunek 10.31). Oczywiście możesz użyć tylko jednego z tych limitów. Aspektów minimów i maksimów możesz używać z prostymi typami daty, czasu i liczb.
Rysunek 10.32. Ten element jest poprawny (755. gra Aarona, w której wykonał home run) względem definicji XML Schema przedstawionej na rysunku 10.31
Znaczenie warunku określającego wymaganie, aby jedna liczba była większa lub mniejsza od innej, jest całkiem oczywiste. Aby data lub czas były większe, muszą one reprezentować późniejszą datę lub czas. Aby data i czas były mniejsze, muszą one reprezentować wcześniejszą datę lub czas.
Rysunek 10.33. Ten element dzien_gry nie jest poprawny
147
Określanie zakresu dopuszczalnych wartości
Inny sposób określenia najniższej możliwej wartości
Rozdział 10.
Określanie zbioru dopuszczalnych wartości Za pomocą aspektów opisanych w poprzednim podrozdziale możesz ustawiać minima, maksima i zakresy wartości dla poprawnych elementów XML. Jednak w niektórych przypadkach możemy mieć do czynienia z określonym zbiorem dopuszczalnych wartości, które zechcesz zdefiniować jako poprawne. W takich sytuacjach należy zastosować aspekt enumeracji (ang. enumeration) (rysunek 10.34).
Określanie zbioru dopuszczalnych wartości
Aby określić zbiór dopuszczalnych wartości: 1. W obrębie definicji typu niestandardowego (w miejsce punktu 4. w procedurach opisanych w podrozdziałach „Wywodzenie niestandardowych typów prostych” i „Wywodzenie niestandardowych typów nazwanych”) wpisz
Rysunek 10.34. Ten element nazwa_cudu może (i musi) teraz zawierać jedną z wymienionych wartości
3. Wpisz />, aby zakończyć element xs:enumeration. 4. Powtarzaj czynności z punktów 1. – 3. dla każdego dodatkowego wyboru wartości, którą element może posiadać.
Rysunek 10.35. Przedstawiony element nazwa_cudu jest całkowicie poprawny, ponieważ odpowiada jednemu z enumerowanych wyborów z definicji XML Schema przedstawionej na rysunku 10.34
Wskazówki Każda wartość enumeracji musi być unikatowa. Wartości enumeracji mogą zawierać białe znaki. Aspektu xs:enumeration możesz używać ze wszystkimi typami prostymi, z wyjątkiem typu logicznego boolean. Rysunek 10.36. Żaden z tych dwóch elementów nazwa_cudu nie jest poprawny. Pierwszy zawiera tylko fragment wyboru. Drugi zawiera dwa wybory, a przy enumeracji dopuszczalny jest tylko jeden. Definiowanie elementu pozwalającego na zastosowanie kilku wyborów ze zbioru wartości jest zaawansowanym tematem, który nie został omówiony w tej książce
148
Definiowanie typów prostych
Ograniczanie długości elementu Jednym ze sposobów wprowadzenia dalszych restrykcji dla elementu XML będącego typem niestandardowym jest zastosowanie aspektu, który określa lub ogranicza jego długość.
Aby określić dokładną długość elementu: Rysunek 10.37. Możesz utworzyć typ niestandardowy, który określa długość wartości ciągu poprawnego elementu
Aby określić minimalną długość elementu: W obrębie definicji typu niestandardowego (w miejsce punktu 4. w procedurach opisanych w podrozdziałach „Wywodzenie niestandardowych typów prostych” i „Wywodzenie niestandardowych typów nazwanych”) wpisz , gdzie n jest minimalną długością (liczbą znaków) danego elementu.
Aby określić maksymalną długość elementu:
Rysunek 10.39. Możesz ograniczyć długość wartości ciągu elementu, aby nie był on zbyt długi albo żeby odpowiadał określonym limitom długości, na przykład takich jak te, które spotyka się w bazach danych
W obrębie definicji typu niestandardowego (w miejsce punktu 4. w procedurach opisanych w podrozdziałach „Wywodzenie niestandardowych typów prostych” i „Wywodzenie niestandardowych typów nazwanych”) wpisz , gdzie x jest maksymalną długością (liczbą znaków) danego elementu (rysunek 10.39).
Wskazówki Aspektu length możesz używać z typem string lub innymi prostymi typami XML Schema opartymi na ciągu znaków, takimi jak anyURI lub hexBinary. Wartości xs:length, xs:minLength i xs:maxLength muszą być nieujemnymi liczbami całkowitymi.
Rysunek 10.40. Ten element krotki_opis jest poprawny, ponieważ jego wartość składa się z 244 znaków, co mieści się w maksymalnym limicie 256 znaków, zdefiniowanym przez typ niestandardowy z rysunku 10.39
Jeśli element jest oparty na typie binarnym, tak jak hexBinary, aspekt length ogranicza liczbę oktetów danych binarnych. Jeśli element jest wywiedziony z listy (patrz podrozdział „Wywodzenie typu listy”), aspekt length ogranicza liczbę pozycji na liście.
149
Ograniczanie długości elementu
Rysunek 10.38. Ten element kod_cudu jest poprawny, ponieważ zawiera pięć znaków, tak jak zostało to określone typem niestandardowym przedstawionym na rysunku 10.37. Jeśli elementy kod_cudu konsekwentnie będą posiadały jeden znak, podkreślnik i trzy cyfry, mógłbym użyć aspektu wzorca, w celu bardziej precyzyjnego zdefiniowania tego elementu (patrz podrozdział „Określanie wzorca dla elementu”)
W obrębie definicji typu niestandardowego (w miejsce punktu 4. w procedurach opisanych w podrozdziałach „Wywodzenie niestandardowych typów prostych” i „Wywodzenie niestandardowych typów nazwanych”) wpisz , gdzie g jest liczbą znaków, jaką dany element musi posiadać (rysunek 10.37).
Rozdział 10.
Określanie wzorca dla elementu W XML Schema można również ograniczyć zawartość poprawnego elementu XML, stosując aspekt wzorca (rysunki 10.41 i 10.42). Aby skonstruować wzorzec, możesz użyć języka wyrażeń regularnych (regex). Pozwala Ci to zdefiniować wzorzec, któremu musi odpowiadać zawartość elementu XML, aby została uznana za poprawną. Język regex w XML Schema jest oparty na języku regex Perla, a jego omówienie mogłoby zająć cały rozdział, dlatego przedstawię tu jedynie najważniejsze informacje.
Określanie wzorca dla elementu
Aby określić wzorzec dla elementu:
Rysunek 10.41. Ten wzorzec ogranicza zawartość elementu kod_cudu do ciągów rozpoczynających się literą „w”, po której następują podkreślnik oraz trzy cyfry. Aby element ten mógł być uznany za poprawny, każdy znak pojawiający się w tym elemencie musi pojawiać się na tej samej pozycji, co w wyrażeniu regularnym dla tego elementu
1. W obrębie definicji typu niestandardowego (w miejsce punktu 4. w procedurach opisanych w podrozdziałach „Wywodzenie niestandardowych typów prostych” i „Wywodzenie niestandardowych typów nazwanych”) wpisz
niebędący białym znakiem; x* oznacza zero lub większą liczbę znaków x; (xy)*
oznacza zero lub większą liczbę par xy; x? oznacza zero lub jeden znak x; (xy)? oznacza
zero lub jedną parę xy; x+ oznacza jeden znak lub większą liczbę znaków x; (xy)+ oznacza jedną parę lub większą liczbę par xy; [abc] dodaje jedną z grup wartości (a, b lub c); [0–9] załącza zakres wartości od 0 do 9;
150
Rysunek 10.42. Pierwszy fragment kodu XML przedstawia poprawną instancję elementu kod_cudu, biorąc pod uwagę definicję XML Schema z rysunku 10.41. Drugi element nie jest poprawny, ponieważ kolejność znaków w zawartości nie odpowiada wzorcowi wyrażenia regularnego
Definiowanie typów prostych to | tamto, aby mieć to lub tamto w zawartości. Dodatkowe wybory należy rozdzielać kolejnymi pionowymi kreskami; x{5}, aby mieć dokładnie 5 znaków x (z rzędu); x{5,}, aby mieć co najmniej 5 znaków x (z rzędu);
Rysunek 10.44. Oto dwa poprawne przykłady elementu czas_biegu, zdefiniowanego na rysunku 10.43. Pierwszy reprezentuje aktualny rekord świata mężczyzn w maratonie, ustanowiony przez Etiopczyka Haile Gebrselassie. Drugi reprezentuje aktualny rekord świata kobiet w maratonie, ustanowiony przez Paulę Radcliffe z Wielkiej Brytanii
(xyz){2}, aby mieć dokładnie dwie sekwencje znaków xyz (z rzędu).
Uwaga! Nawiasy okrągłe kontrolują to, na co wpływ mają nawiasy klamrowe i inne modyfikatory, takie jak ?, + oraz *. 3. Wreszcie wpisz />, aby zakończyć element xs:pattern.
Wskazówki Szczegółowe omówienie wyrażeń regularnych wykracza nieco poza zakres tej książki. Zamiast tego możesz odwołać się np. do pozycji Wyrażenia regularne. Wprowadzenie Michaela Fitzgeralda (wyd. Helion, 2013). Ponadto więcej szczegółowych informacji na temat wyrażeń regularnych XL Schema znajdziesz na stronie www.w3.org/TR/2004/ REC-xmlschema-2-20041028/datatypes.html#regexs. Wyrażenia regularne wykorzystywane w XML Schema są bardzo podobne do tych stosowanych w języku Perl. Aczkolwiek jedna istotna różnica techniczna polega na tym, że w XML Schema regex porównanie dokonuje się zawsze pomiędzy wyrażeniem regularnym a całą zawartością elementu. Nie ma znaków ^ lub $ ograniczających dopasowanie do początku lub końca wiersza (jak to ma miejsce w języku Perl). Aspektu wzorca możesz używać z dowolnymi typami prostymi.
151
Określanie wzorca dla elementu
Rysunek 10.43. Wzorce możesz również wykorzystywać do kontrolowania zawartości elementów opartych na innych typach niż ciąg znaków. Jeśli chcesz na przykład, aby element czas_biegu posiadał wartość xs:duration, zawierającą jedynie godziny, minuty i sekundy, możesz zdefiniować wzorzec taki jak ten przedstawiony na przykładzie. Zwróć uwagę, że ten wzorzec nie „rozumie”, czego potrzebuje typ duration. Po prostu wymaga, żeby zawartość składała się z wielkiej litery „P”, wielkiej litery „T”, jednej lub kilku cyfr, wielkiej litery „H”, jednej lub kilku cyfr, wielkiej litery „M”, jednej lub kilku cyfr i wreszcie wielkiej litery „S”
x{5,8}, aby mieć co najmniej 5 i co najwyżej 8 znaków x (z rzędu);
Rozdział 10.
Ustawianie limitu cyfr w liczbie W podrozdziale „Określanie zakresu dopuszczalnych wartości” dowiedziałeś się, w jaki sposób można ograniczać wartości elementów liczbowych za pomocą aspektów minimów i maksimów. W XML Schema możesz również dla elementów liczbowych ograniczać całkowitą liczbę cyfr, a także liczbę cyfr w części ułamkowej (rysunek 10.45).
Aby określić całkowitą liczbę cyfr w wartości liczbowej:
Rysunek 10.45. Wartość totalDigits określa całkowitą liczbę cyfr, a wartość fractionDigits określa, ile cyfr musi się pojawić w części ułamkowej danej liczby
Ustawianie limitu cyfr w liczbie
1. W obrębie definicji typu niestandardowego (w miejsce punktu 4. w procedurach opisanych w podrozdziałach „Wywodzenie niestandardowych typów prostych” i „Wywodzenie niestandardowych typów nazwanych”) wpisz , aby zakończyć aspekt xs:totalDigits.
Aby określić liczbę cyfr w części ułamkowej: 1. W obrębie definicji typu niestandardowego (w miejsce punktu 4. w procedurach opisanych w podrozdziałach „Wywodzenie niestandardowych typów prostych” i „Wywodzenie niestandardowych typów nazwanych”) wpisz
Rysunek 10.46. Biorąc pod uwagę definicję XML Schema przedstawioną na rysunku 10.45, obydwa te elementy są poprawne, ponieważ zawierają maksymalnie sześć cyfr (a czasem mniej) i maksymalnie cztery cyfry (a czasem mniej) w części ułamkowej. John Dalton i Jöns Jakob Berzeliu są uznawani za pierwszych naukowców, którym udało się ustalić masę atomową. Te dwa elementy XML reprezentują masy atomowe, odpowiednio: węgla i żelaza
2. Następnie wpisz value="n", gdzie n jest maksymalną liczbą cyfr, które mogą wystąpić w części ułamkowej. 3. Wpisz />, aby zakończyć aspekt xs:fractionDigits.
Wskazówki Każdego z tych dwóch aspektów możesz używać z dowolnym typem liczbowym. Aspekt xs:totalDigits musi być liczbą dodatnią i nie może być mniejszy niż wartość aspektu xs:fractionDigits. Aspekt xs:fractionDigits musi być nieujemną liczbą całkowitą (0, 1, 2 lub większą). Obydwa aspekty określają maksymalne dopuszczalne wartości. Dana liczba jest nadal uważana za poprawną, nawet jeśli ma mniej cyfr.
152
Rysunek 10.47. Te dwa elementy masa_atomowa są niepoprawne. Pierwszy dlatego, że ma zbyt dużą całkowitą liczbę cyfr (7 zamiast 6). Drugi, choć ma poprawną całkowitą liczbę cyfr, ma za dużo cyfr w części ułamkowej (5 zamiast 4). Mimo że elementy te nie są poprawne przy danej definicji XML Schema, reprezentują właściwe masy atomowe, odpowiednio: złota i wodoru
Definiowanie typów prostych
Wywodzenie typu listy
Rysunek 10.48. Lista musi być oparta na istniejącym wbudowanym lub niestandardowym typie prostym. Ten typ listy dla elementu ostatnie_zacmienia jest oparty na typie xs:dateTime
Dotychczas każdy z Twoich elementów mógł zawierać tylko jedną jednostkę. Jeśli zdefiniowałeś element, który miał być datą, mógł on zawierać tylko jedną datę. Jeśli jednak potrzebujesz elementu zawierającego całą listę dat, możesz dostosować się do tego wymogu, wyprowadzając z typu daty typ listy (rysunek 10.48).
Aby wyprowadzić typ listy: 1. Najpierw określ nazwę elementu XML, który definiujesz za pomocą XML Schema. W tym celu wpisz , gdzie etykieta jest nazwą danego elementu XML.
3. Wpisz , gdzie element_listy jest typem prostym (wbudowanym lub niestandardowym), który definiuje każdą poszczególną jednostkę na Twojej liście. 4. Wpisz , aby zakończyć swój nowy niestandardowy typ prosty. 5. Wpisz , aby zakończyć definicję danego elementu.
Wskazówki Rysunek 10.50. Porównaj ten fragment XML Schema z fragmentem przedstawionym na rysunku 10.48. W tamtym fragmencie wykorzystałem anonimowy typ listy do zdefiniowania elementu ostatnie_zacmienia. W przykładzie bieżącym zdefiniowałem element ostatnie_zacmienia za pomocą nazwanego typu listy lista_typu_dateTime. W obu przypadkach element jest uznawany za poprawny, jeśli zawiera listę typów xs:dateTime rozdzielonych białymi znakami
Rysunek 10.51. Element ostatnie_zacmienia z tego przykładu jest poprawny względem XML Schema z rysunku 10.50. Zawiera on listę trzech kolejnych całkowitych zaćmień Księżyca
List nie należy mylić z enumeracjami (patrz podrozdział „Określanie zbioru dopuszczalnych wartości”). Enumeracje dostarczają zbiór opcjonalnych wartości dla elementu. Listy są sekwencjami wartości w ramach samego elementu. Na liście spacje oddzielają jedną pozycję od kolejnej. Dlatego też lista ciągów znaków zostanie błędnie zinterpretowana, jeśli któraś z pozycji na tej liście sama zawiera wewnątrz spację. Przykładowa lista „Kolos Rodyjski Latarnia morska na Faros” reprezentowałaby sześć pozycji, a nie dwie. Podobnie jak w przypadku wywodzenia typów prostych (patrz podrozdziały „Wywodzenie niestandardowych typów prostych” i „Wywodzenie niestandardowych typów nazwanych”), jeśli nie zamierzasz ponownie wykorzystywać danej listy, utwórz anonimowy typ listy, tak jak opisano to w powyższej procedurze (rysunek 10.48). Jeśli jednak chcesz ponownie wykorzystać daną listę, utwórz nazwany typ listy (rysunek 10.50).
153
Wywodzenie typu listy
Rysunek 10.49. Zgodnie z XML Schema z rysunku 10.48, poprawny element ostatnie_zacmienia musi zawierać listę składającą się z zera lub kilku jednostek xs:dateTime. Jednostki te są rozdzielone białymi znakami, tak jak pokazano w tym poprawnym przykładzie dla dwóch ostatnich całkowitych zaćmień Księżyca
2. Wpisz , aby rozpocząć wyprowadzanie własnego niestandardowego typu prostego.
Rozdział 10.
Wywodzenie typu łączonego Tak samo, jak mogę zdefiniować, żeby element XML był jedną z kilku różnych wartości, czasem mogę potrzebować zdefiniować element XML, który będzie kilkoma różnymi typami prostymi (rysunek 10.52). Aby zdefiniować element składający się z dwóch (lub większej liczby) różnych typów prostych, możesz wyprowadzić nowy typ jako kombinację tych dwóch typów prostych. Taki nowo wywiedziony typ prosty zwany jest typem łączonym (ang. union type) i jest tworzony z grupy innych typów prostych (rysunek 10.53).
Aby wyprowadzić typ łączony:
Wywodzenie typu łączonego
1. Najpierw określ nazwę elementu XML, który definiujesz za pomocą XML Schema. W tym celu wpisz , gdzie etykieta jest nazwą danego elementu XML.
Rysunek 10.52. W tym fragmencie XML Schema zdefiniowałem dwa nazwane niestandardowe typy proste: isbn10 oraz isbn13. Każdy z tych typów niestandardowych jest ciągiem znaków ograniczonym w taki sposób, aby spełniać wymagania formatu dla odpowiedniego standardu ISBN
2. Wpisz , aby rozpocząć swój niestandardowy typ prosty. 3. Wpisz , gdzie elementy_łączone to grupa rozdzielonych białymi
znakami typów prostych (wbudowanych lub niestandardowych), które definiują poprawne typy proste dla tego elementu. 4. Wpisz , aby zakończyć swój nowy niestandardowy typ prosty.
Rysunek 10.53. Tutaj element ksiazka został zdefiniowany jako typ łączony składający się z typów niestandardowych zdefiniowanych na rysunku 10.52. Oznacza to, że element ksiazka może być zarówno typem niestandardowym isbn10, jak i typem niestandardowym isbn13
5. Wpisz , aby zakończyć definicję danego elementu.
Wskazówka Podobnie jak w przypadku wywodzenia typów prostych (patrz rozdziały „Wywodzenie niestandardowych typów prostych” i „Wywodzenie niestandardowych typów nazwanych”), jeśli nie zamierzasz ponownie wykorzystywać danego typu łączonego, utwórz anonimowy typ łączony, tak jak opisano to w powyższej procedurze. Jeśli jednak chcesz ponownie wykorzystać dany typ łączony, utwórz nazwany typ łączony. Rysunek 10.54. Wszystkie trzy fragmenty kodu XML dla elementu ksiazka są poprawne względem definicji XML Schema przedstawionej na rysunku 10.53. Pierwsze dwa wykorzystują niestandardowy typ isbn10, a ostatni wykorzystuje niestandardowy typ isbn13
154
Definiowanie typów złożonych
11
Rozdział 11. Definiowanie typów złożonych[RS1] W poprzednim rozdziale omówione zostały elementy XML będące typami prostymi, które mogą zawierać jedynie wartość, a nie mogą zawierać elementów-dzieci ani atrybutów. W tym rozdziale zajmiemy się elementami, które są typami złożonymi (ang. complex types). Element będący typem złożonym może zawierać elementy-dzieci, atrybuty lub kombinację tych dwóch składników.
Choć z pewnością uda Ci się pojąć istotę pisania typów złożonych, to postaram się jeszcze dostarczyć Ci podstawowych informacji na temat sposobu ich konstruowania. Szczegóły na ten temat znajdziesz w podrozdziale „Podstawy typów złożonych”, a dalsze informacje będę zawierał w kolejnych przykładach typu krok po kroku.
155
Definiowanie typów złożonych
W społeczności osób zajmujących się językiem XML toczy się dyskusja na temat zawiłości typów złożonych, a w szczególności w kwestii tego, jak trudne są one do zrozumienia. Mimo to, jeśli chcesz, aby Twój dokument XML zawierał coś więcej niż tylko element główny, będziesz potrzebował co najmniej jednego elementu będącego typem złożonym, żeby element główny mógł posiadać własne elementy-dzieci. Innym istotnym powodem zastosowania typów złożonych w XML Schema jest umożliwienie elementom posiadania atrybutów.
Rozdział 11.
Podstawy typów złożonych W XML Schema wszystkie elementy XML są definiowane za pomocą typów prostych lub typów złożonych. Elementy Rysunek 11.1. Element rok_wybudowania jest typem złożone — w przeciwieństwie do elementów prostych złożonym zawierającym jedynie tekst (i atrybut), stąd — mogą posiadać elementy-dzieci i (lub) atrybuty. Elementy będące typami złożonymi dzielimy dalej na te z zawartością prostą (ang. simple content) oraz te z zawartością złożoną (ang. complex content). Obydwa rodzaje mogą posiadać atrybuty, ale zawartość prosta dopuszcza tylko ciągi znaków, natomiast zawartość złożona dopuszcza stosowanie elementów-dzieci.
Cztery typy złożone Pierwszy z nich zwany jest „wyłącznie tekst” i jest elementem typu złożonego z prostą zawartością (dopuszcza tekst i atrybuty) (rysunek 11.1).
Podstawy typów złożonych
Drugi z nich, określany jako „wyłącznie element”, jest elementem typu złożonego z zawartością złożoną (dopuszcza dzieci i atrybuty) (rysunek 11.2). Trzeci typ, „pusty element”, jest również elementem typu złożonego z zawartością złożoną (rysunek 11.3). Jest to element będący typem złożonym, ponieważ może zawierać atrybuty. Traktuje się go jako zawartość złożoną, gdyż zawartość prosta dopuszcza tekst, a skoro definiuję pusty element, to nie może on mieć zawartości tekstowej. Wreszcie czwarty typ złożony elementów XML zwany jest „zawartością mieszaną”. Jest to spowodowane tym, że jest to element typu złożonego z zawartością zarówno złożoną, jak i prostą (dopuszcza tekst, elementy-dzieci oraz atrybuty) (rysunek 11.4).
określany jest mianem „wyłącznie tekst”
Rysunek 11.2. Element cuda_starozytnosci jest typem złożonym, który zawiera element-dziecko (cud), ale nie zawiera tekstu. Taki element jest określany mianem „wyłącznie element”. Choć ten konkretny element nie posiada atrybutów, to jako typ złożony „wyłącznie element” mógłby atrybuty posiadać
Rysunek 11.3. Element zrodlo jest typem złożonym określanym jako „pusty element”. Element ten nie ma zawartości. Element przedstawiony na przykładzie posiada atrybuty (ale nie wszystkie takie elementy atrybuty posiadają)
Hierarchia typów XML Schema Istotnym modułem konstrukcyjnym języka XML Schema jest to, że wszystkie typy elementów są hierarchicznie wywiedzione od jednego typu głównego (ang. root type). W rzeczywistości wszystkie wbudowane typy proste są również wywiedzione z tego typu głównego. Ten pojedynczy typ główny rozgałęzia się na dwa typy, które już zostały omówione: typy proste i typy złożone. Następnie typy złożone dzielą się na zawartość prostą i zawartość złożoną. Typ główny nosi nazwę anyType i jest wykorzystywany do definiowania elementów XML, które mają dowolną zawartość dowolnego typu.
156
Rysunek 11.4. Ten element dzieje jest typem złożonym zawierającym tekst i element dziecko o nazwie para. Jest on określany jako „zawartość mieszana”. Zwróć uwagę, że nie jest to zbyt popularna struktura dla elementów XML, szczególnie tych w aplikacjach bazodanowych
Definiowanie typów złożonych Wywodzenie typu złożonego W poprzednim rozdziale dowiedziałeś się, jak wywodzić niestandardowe typy proste z wbudowanych typów prostych (rozdział 10., podrozdział „Wywodzenie niestandardowych typów prostych”). Jeśli chodzi o typy złożone, nie ma żadnych typów wbudowanych, które mógłbyś wykorzystać. Abyś mógł użyć typu złożonego, musi on najpierw zostać wywiedziony. Rysunek 11.5. Ten dokument XML Schema definiuje element XML z rysunku 1.1. Dany typ złożony został wyprowadzony z rozszerzenia zawartości prostej z atrybutem
Aby wyprowadzić typ złożony „tylko element” (taki jak ten pokazany na rysunku 11.2), możesz użyć elementu (rysunek 11.6). Tutaj element cuda_starozytnosci został wywiedziony z zawartości złożonej, która ogranicza element główny anyType. Zastosowano restrykcję , dopuszczając, aby element cuda_starozytnosci posiadał elementy-dzieci. Zostało to omówione szczegółowo w podrozdziale „Definiowanie typów złożonych, które zawierają elementy-dzieci”.
Warunek domyślny Przy pracy z typami złożonymi prawdopodobnie najistotniejszą informacją jest to, że domyślną derywacją dla typów złożonych jest: zawartość złożona, która ogranicza typ anyType Przy tym warunku domyślnym możesz i powinieneś zawsze pomijać w swoich definicjach typów złożonych XML Schema elementy i (rysunek 11.7).
Rysunek 11.7. Ten dokument XML Schema również definiuje element XML z rysunku 11.2. Zwróć uwagę, że usunąłem domyślny warunek dla typów złożonych: wywodzenie z zawartości złożonej z ograniczeniem podstawy anyType. Nie tylko zajmuje to mniej miejsca, ale również jest łatwiejsze do odczytania!
Ten warunek domyślny bywa często przemilczany przy omawianiu typów złożonych w XML Schema, dlatego będzie często przywoływany w niniejszym rozdziale.
157
Podstawy typów złożonych
Rysunek 11.6. Ten dokument XML Schema definiuje element XML z rysunku 11.2. Przedstawia on typ złożony wyprowadzony z elementu complexContent, który ogranicza typ anyType
Aby wyprowadzić typ zawartości „wyłącznie tekst” (taki jak ten pokazany na rysunku 11.1), możesz użyć elementu (rysunek 11.5). Tutaj element rok_wybudowania został wywiedziony z zawartości prostej z podstawą, którą jest dodatnia liczba całkowita. Posiada on również atrybut wartości ciągu o nazwie era. Zostało to omówione bardziej szczegółowo w podrozdziale „Definiowanie elementów zawierających wyłącznie tekst”.
Rozdział 11.
Wywodzenie anonimowych typów złożonych Podobnie jak w przypadku typów prostych, możesz wyprowadzać typy złożone anonimowo lub je nazywać (i wykorzystywać wielokrotnie w całym dokumencie XML Schema). Jeśli nie potrzebujesz ponownie wykorzystywać danego typu prostego, szybciej utworzysz go jako typ anonimowy w obrębie definicji samego elementu (rysunek 11.8).
Aby wyprowadzić anonimowy typ złożony:
Wywodzenie anonimowych typów złożonych
1. Rozpocznij definicję elementu, wpisując , gdzie etykieta jest nazwą definiowanego elementu XML. Innymi słowy, piszesz właśnie schemat XML w celu zdefiniowania elementu z Twojego dokumentu XML.
Rysunek 11.8. Ten fragment XML Schema jest definicją anonimowego typu złożonego. Definiuje on element rok_wybudowania jako element „wyłącznie tekst” wymagający dla wartości tekstowej dodatniej liczby całkowitej. Definiuje on również, że rok_wybudowania będzie posiadał atrybut o nazwie era, którego wartością jest ciąg
2. Następnie wpisz , aby rozpocząć anonimowy typ złożony. 3. W obrębie elementu xs:complexType: zadeklaruj typ zawartości (ang. content type)
jako zawartość prostą lub zawartość złożoną (patrz podrozdział „Podstawy typów złożonych”); utwórz wnętrze danego elementu (czego objaśnieniu
poświęcona jest większa część tego rozdziału); zdefiniuj atrybuty (patrz podrozdział
„Definiowanie atrybutów”), które powinny się pojawić w definiowanym typie złożonym. 4. Następnie wpisz , aby zakończyć definicję anonimowego typu złożonego. 5. Wpisz , aby zakończyć definicję danego elementu jako typu złożonego.
Wskazówka Jedyną różnicą pomiędzy typem anonimowym a typem nazwanym jest to, że typ nazwany może być wykorzystywany więcej niż raz i może być również wykorzystywany jako podstawa dla nowych typów złożonych. Typ anonimowy może być zastosowany tylko dla elementu, w którym jest zawarty.
158
Rysunek 11.9. Oto element XML, który jest poprawny względem definicji XML Schema przedstawionej na rysunku 11.8
Definiowanie typów złożonych
Wywodzenie nazwanych typów złożonych
Rysunek 11.10. Porównując tę definicję z definicją typu anonimowego z rysunku 11.8, zauważysz, że „wnętrzności” obu tych definicji są identyczne. Podstawowa różnica polega na tym, że nazwany typ złożony może być ponownie wykorzystany dla innego dowolnego elementu w XML Schema. Zwróć uwagę, w jaki sposób element xs:complexType definiuje swój atrybut name (nazwa) jako „typRok”. Tej nazwy pozostałe elementy będą używać, odwołując się do tego typu złożonego
Jeśli zamierzasz używać jakiegoś typu złożonego do definiowania więcej niż jednego elementu w swoim dokumencie XML Schema, możesz utworzyć nazwany typ prosty (rysunek 11.10). Wtedy za każdym razem, kiedy będziesz chciał go użyć, możesz załączyć odsyłacz, który będzie wskazywał powiązanie pomiędzy elementem XML i Twoim nowym typem niestandardowym.
Aby wyprowadzić element będący nazwanym typem złożonym: 1. Wpisz , gdzie nazwa_typu_złożonego identyfikuje Twój nowy typ złożony.
zadeklaruj typ zawartości (ang. content type)
jako zawartość prostą lub zawartość złożoną (patrz podrozdział „Podstawy typów złożonych”);
utwórz wnętrze danego elementu (czego objaśnieniu
Rysunek 11.11. Mogę teraz użyć nowego typu typRok w tylu definicjach elementów, w ilu będę chciał
poświęcona jest większa część tego rozdziału); zdefiniuj atrybuty (patrz podrozdział
„Definiowanie atrybutów”), które powinny się pojawić w definiowanym typie złożonym. 4. Wpisz , aby zakończyć definicję nazwanego typu złożonego.
Rysunek 11.12. Oto instancja elementu XML, która jest poprawna względem definicji XML Schema przedstawionej na rysunku 11.10. Zwróć uwagę, że mogę użyć jednego nazwanego typu złożonego dla obydwu elementów: rok_wybudowania i rok_zniszczenia
5. Teraz, żeby użyć danego nazwanego typu złożonego do zdefiniowania elementu XML, musisz wpisać , gdzie nazwa_typu_złożonego jest nazwą, którą nadałeś temu nowemu typowi złożonemu w punkcie 2. (rysunek 11.11).
Wskazówka Zwróć uwagę, że do swojego nowego typu złożonego odwołujesz się, wpisując nazwa_typu_złożonego zamiast xs:nazwa_typu_złożonego. Jest to spowodowane tym, że prefiks xs: odnosi się do przestrzeni nazw XML Schema, a nie do przestrzeni nazw typów niestandardowych. Więcej szczegółów na ten temat znajdziesz w części V.
159
Wywodzenie nazwanych typów złożonych
3. W obrębie elementu xs:complexType:
Rozdział 11.
Definiowanie typów złożonych, które zawierają elementy-dzieci Jednym z najbardziej powszechnych typów złożonych jest taki typ, który zawiera elementy-dzieci. Ten typ złożony może również zawierać atrybuty, ale nie może zawierać własnej wartości. Jest on opisywany jako „tylko element” (nawet jeśli zawiera atrybuty).
Aby zdefiniować typ złożony „tylko element”: 1. Wpisz , gdzie nazwa_typu_złożonego identyfikuje Twój nowy typ złożony.
Definiowanie typów złożonych
3. Teraz musisz zdefiniować strukturę i kolejność elementów-dzieci tego elementu-rodzica. Musisz zadeklarować sekwencję, listę bez określonej kolejności lub wybór (każda z tych możliwości została opisana w jednym z trzech kolejnych podrozdziałów).
Rysunek 11.13. Oto definicja anonimowego typu złożonego typCud zawierającego sekwencję jednego elementu-dziecka o nazwie cud. (Zwróć uwagę, że ten element typu złożonego został wywiedziony z zawartości złożonej, która ogranicza typ anyType, co jest domyślnym warunkiem dla typów złożonych)
4. Następnie zadeklaruj atrybuty (patrz podrozdział „Definiowanie atrybutów”), które powinny pojawić się w tym elemencie będącym typem złożonym, jeśli w ogóle jakieś mają się pojawić. 5. Wpisz , aby zakończyć definicję typu złożonego „tylko element” (rysunek 11.13).
Wskazówki Jak opisano w podrozdziale „Podstawy typów złożonych”, domyślnym warunkiem dla typów złożonych jest to, że wywodzą się one z elementu xs:complexContent, który ogranicza element xs:anyType. Z tego względu możesz pominąć deklaracje tych elementów XML Schema (rysunek 11.14). Elementy-dzieci typu złożonego są określane mianem modelu zawartości (ang. content model). Model zawartości typu złożonego może być sekwencją, listą bez określonej kolejności lub wyborem. Są to tak zwane grupy modelowe (ang. model groups) i określają one strukturę oraz kolejność elementów-dzieci w obrębie elementu-rodzica.
160
Rysunek 11.14. Oto kolejna definicja typu złożonego dla elementu cuda_starozytnosci. Pominąłem elementy warunku domyślnego: oraz . Ponieważ są to warunki domyślne, ten fragment XML Schema definiuje dokładnie taki sam element XML jak ten pokazany na rysunku 11.13, a ponadto w taki właśnie sposób prawie zawsze definiuje się elementy typu złożonego
Definiowanie typów złożonych
Ustalanie określonej sekwencji dla występowania elementów-dzieci Jeśli chcesz, aby element będący typem złożonym zawierał elementy-dzieci w określonej kolejności, musisz zdefiniować sekwencję tych elementów (rysunek 11.15).
Aby elementy-dzieci musiały pojawiać się w określonej sekwencji: 1. Wpisz
3. Następnie wpisz >, aby zakończyć znacznik otwierający. 4. Zadeklaruj elementy typu prostego i (lub) elementy typu złożonego, które mają się znaleźć w sekwencji. Zadeklaruj je w takiej kolejności, w jakiej powinny występować. 5. Wpisz , aby zakończyć daną grupę modelową.
Wskazówki Sekwencja definiuje kolejność, w jakiej należące do niej elementy muszą występować w dokumencie XML. Ponieważ element XML nie musi posiadać więcej niż jeden element-dziecko, jest całkowicie uzasadnione, aby sekwencja posiadała tylko jeden element. Sekwencja może zawierać inne sekwencje, wybory (patrz podrozdział „Tworzenie zbioru wyborów”) lub referencje do grup nazwanych (patrz podrozdział „Definiowanie nazwanych grup modelowych”). Sekwencja może być zawarta w definicji typu złożonego, w innych sekwencjach, w zbiorze wyborów (patrz podrozdział „Tworzenie zbioru wyborów”) lub w definicjach grup nazwanych (patrz podrozdział „Definiowanie nazwanych grup modelowych”). Element jest zasadniczo ekwiwalentem przecinka (,) w DTD.
161
Ustalanie określonej sekwencji
Rysunek 11.15. Ten fragment XML Schema definiuje typ złożony o nazwie typCud. Teraz każdy element XML zdefiniowany jako typCud będzie musiał zawierać następujące elementy-dzieci w takiej kolejności: nazwa, lokalizacja, wysokosc, historia, obrazek_glowny oraz zrodlo. W rzeczywistości na rysunku 11.14 element cud jest zdefiniowany jako typ złożony typCud. Nie jest to wcale rzadkością, że jeden typ złożony posiada elementy-dzieci, które również są typami złożonymi
2. W razie potrzeby określ, ile razy ma pojawiać się sama sekwencja. W tym celu ustaw atrybuty minOccurs i maxOccurs, tak jak zostało to opisane w podrozdziale „Kontrolowanie liczby wystąpień”.
Rozdział 11.
Dopuszczanie, aby elementy-dzieci pojawiały się w dowolnej kolejności Jeśli chcesz, aby element będący typem złożonym zawierał elementy-dzieci w dowolnej kolejności, możesz wymienić te elementy-dzieci za pomocą elementu all (wszystko) (rysunek 11.16).
Aby elementy-dzieci mogły pojawiać się w dowolnej kolejności: 1. Wpisz
Rysunek 11.16. Tutaj za pomocą elementu xs:all zdefiniowałem typ złożony o nazwie typHistoria. Oznacza to, że każdy element XML zdefiniowany z wykorzystaniem typu typHistoria będzie poprawny, jeśli będzie zawierał w dowolnej kolejności elementy: rok_wybudowania, rok_zniszczenia, sposob_zniszczenia oraz dzieje
elementy-dzieci w dowolnej kolejności
3. Następnie wpisz >, aby zakończyć znacznik otwierający. 4. Zadeklaruj elementy typu prostego i (lub) elementy typu złożonego, które mają się znaleźć na danej liście. 5. Wpisz , aby zakończyć grupę modelową.
Wskazówki Elementy wymienione w elemencie xs:all (pomino jego nazwy) mogą pojawiać się raz lub w ogóle (w zależności od ich indywidualnych atrybutów minOccurs i maxOccurs), w dowolnej kolejności. Atrybut minOccurs może przyjmować jedynie wartości 0 lub 1. Atrybut maxOccurs może przyjmować tylko wartość 1 (patrz podrozdział „Kontrolowanie liczby wystąpień”). Element xs:all może zawierać tylko deklaracje lub referencje poszczególnych elementów, a nie innych grup. Ponadto żaden element nie może pojawiać się więcej niż raz. Element xs:all może być zawarty jedynie w definicji typu złożonego „tylko element” (patrz podrozdział „Definiowanie typów złożonych, które zawierają elementy-dzieci”) i musi być jego jedynym elementem-dzieckiem.
162
Rysunek 11.17. W tych dwóch fragmentach kodu XML obydwa elementy historia są poprawne względem definicji XML Schema przedstawionej na rysunku 11.6, ponieważ kolejność elementów-dzieci jest nieistotna
Definiowanie typów złożonych
Tworzenie zbioru wyborów Czasem korzystnie jest zadeklarować, aby element typu złożonego mógł zawierać ten lub inny element-dziecko (lub grupę elementów-dzieci). Możesz to zrobić, tworząc grupę modelową wyboru (rysunek 11.18).
Aby zaoferować wybór elementów-dzieci: 1. Wpisz
3. Następnie wpisz >, aby zakończyć otwarty znacznik. 4. Zadeklaruj elementy typu prostego i (lub) elementy typu złożonego, które mają tworzyć dany zbiór wyborów. 5. Wpisz , aby zakończyć grupę modelową.
Wskazówki
Rysunek 11.19. Zgodnie z fragmentem XML Schema z rysunku 11.8, obydwa przedstawione elementy cud są poprawne. W pierwszym fragmencie kodu XML obecne jest pole lokalizacja. W drugim przykładzie zamiast pola lokalizacja zastosowana została sekwencja składająca się z elementów miasto i kraj
Zbiór wyborów może również zawierać sekwencję (patrz podrozdział „Ustalanie określonej sekwencji dla występowania elementów-dzieci”), dodatkowe zbiory wyborów lub referencję do grup nazwanych (patrz podrozdział „Definiowanie nazwanych grup modelowych”). Zbiór wyborów może być zawarty w definicji typu złożonego, w sekwencjach (patrz podrozdział „Ustalanie określonej sekwencji dla występowania elementów-dzieci”), w innych zbiorach wyborów lub w definicjach grup nazwanych (patrz podrozdział „Definiowanie nazwanych grup modelowych”). Element jest zasadniczo równoważny z pionowymi kreskami w schematach DTD.
163
Tworzenie zbioru wyborów
Domyślną wartością dla atrybutów minOccurs i maxOccurs jest 1. Przy takich wartościach domyślnych tylko jeden z elementów ze zbioru wyborów może pojawić się w poprawnym dokumencie XML. Jeśli wartość atrybutu maxOccurs jest większa niż 1, określa ona liczbę wyborów, które mogą się pojawić. Zastosowanie atrybutu maxOccurs="unbounded" jest równoważne z dodaniem gwiazdki (*) do zbioru wyborów w DTD (patrz rozdział 6., „Tworzenie dokumentów DTD”).
Rozdział 11.
Definiowanie elementów zawierających wyłącznie tekst Innym typowym elementem typu złożonego jest element określany jako „wyłącznie tekst”. Posiada on wartość tekstową i nie zawiera elementów-dzieci. Nazwa tego typu złożonego jest jednak nieco myląca, ponieważ może on zawierać (i zazwyczaj będzie zawierał) jeden lub kilka atrybutów.
Aby zdefiniować typ złożony „wyłącznie tekst”: 1. Wpisz
Definiowanie elementów zawierających tekst
2. Następnie wpisz name="nazwa_typu_złożonego">, gdzie nazwa_typu_złożonego identyfikuje Twój nowy typ złożony.
Rysunek 11.20. Jest to definicja typu złożonego „wyłącznie tekst”. Wskazuje ona, że każdy element XML zdefiniowany z wykorzystaniem typu typRok musi zawierać dodatnią liczbę całkowitą, ale nie może zawierać żadnych elementów-dzieci. Element taki będzie również posiadał atrybut o nazwie era zawierający ciąg znaków. Więcej szczegółowych informacji na temat atrybutów znajdziesz w podrozdziale „Definiowanie atrybutów”
3. Wpisz . 4. Następnie wpisz , gdzie podstawa wskazuje typ prosty, na którym opierasz nowy element typu złożonego. 6. Jeśli wpisałeś xs:restriction w punkcie 4., zadeklaruj dodatkowe aspekty (patrz rozdział 10., „Definiowanie typów prostych”), które mają ograniczyć zawartość prostą w tej definicji typu złożonego. 7. Następnie zadeklaruj atrybuty (patrz podrozdział „Definiowanie atrybutów”), które powinny się pojawić w tym elemencie typu złożonego, jeśli w ogóle jakieś argumenty mają się w nim pojawić. 8. Wpisz, odpowiednio: lub , aby zakończyć element z punktu 4. 9. Wpisz . 10. Wpisz , aby zakończyć definicję typu złożonego (rysunek 11.20).
164
Rysunek 11.21. Biorąc pod uwagę definicję typu złożonego z rysunku 11.20, ten element_rok wybudowania jest poprawny, ponieważ zawiera liczbę całkowitą i posiada atrybut era
Rysunek 11.22. Z kolei ten element rok_wybudowania jest niepoprawny, ponieważ fraza „dawno temu” nie jest liczbą całkowitą. Typ złożony typRok wymaga, aby wartością elementu była dodatnia liczba całkowita (xs:positiveInteger) określona przez podstawowy typ prosty, z którego dany typ złożony został wyprowadzony
Definiowanie typów złożonych
Definiowanie pustych elementów Elementy, które mogą posiadać atrybuty, ale nie mają żadnej zawartości pomiędzy znacznikiem otwierającym i zamykającym, zwane są „elementami pustymi”. Ponieważ są to elementy typu złożonego, mogą zawierać (i często zawierają) jeden lub kilka atrybutów. Rysunek 11.23. Ta definicja typu złożonego definiuje typ złożony o nazwie typZrodlo. Jest to pusty element, który zawiera dwa atrybuty: id_sekcji i id_gazety
Aby zdefiniować „pusty element” typu złożonego: 1. Wpisz , gdzie nazwa_typu_złożonego identyfikuje Twój nowy typ złożony. 3. Teraz zadeklaruj atrybuty (patrz podrozdział „Definiowanie atrybutów”), które powinny się pojawić w tym elemencie typu złożonego, jeśli w ogóle jakieś atrybuty mają się w nim pojawić.
Rysunek 11.24. Oto kolejna definicja typu złożonego dla typu o nazwie typZrodlo. W tym fragmencie kodu dodałem na powrót elementy warunku domyślnego (wyprowadzanie z zawartości złożonej, która ogranicza typ anyType). Chociaż definiujemy tu dokładnie taki sam typ złożony jak ten przedstawiony na rysunku 11.23, zapis taki jest znacznie mniej wygodny i nie stosuje się go w praktyce
Wskazówka Jak zostało to omówione w podrozdziale „Podstawy typów złożonych”, domyślnym warunkiem dla typów złożonych jest to, że wywodzą się one z elementu xs:complexContent, który ogranicza element xs:anyType. Z tego względu możesz pominąć deklaracje tych elementów w XML Schema (rysunek 11.24).
Rysunek 11.25. Ten element zrodlo jest poprawny zarówno względem XML Schema z rysunku 11.23, jak i względem XML Schema z rysunku 11.24
165
Definiowanie pustych elementów
4. Wpisz , aby zakończyć definicję typu złożonego (rysunek 11.23).
Rozdział 11.
Definiowanie elementów z zawartością mieszaną Chociaż typowa zawartość wywodząca się z bazy danych rzadko posiada elementy zawierające zarówno elementy-dzieci, jak i tekst, to w przypadku dokumentów bardziej skoncentrowanych na tekście jest, co oczywiste, zupełnie inaczej. Typ złożony obsługujący taką konstrukcję Rysunek 11.26. Po ustawieniu true (prawda) dla zwany jest „zawartością mieszaną”. Tworząc ten typ złożony, musisz zadeklarować, że jego zawartość będzie atrybutu mixed (mieszany) element dzieje może zawierać zarówno tekst, jak i elementy-dzieci. Zwróć uwagę, mieszana (rysunek 11.26).
Aby utworzyć typ złożony „zawartość mieszana”: 1. Wpisz
że element para jest pustym typem złożonym bez atrybutów (patrz podrozdział „Definiowanie pustych elementów”). Atrybut XML Schema maxOccurs="unbounded" oznacza, że w elemencie dzieje może być nieograniczona liczba elementów para
2. Następnie wpisz name="nazwa_typu_złożonego">, gdzie nazwa_typu_złożonego identyfikuje Twój nowy typ złożony.
Definiowanie elementów
3. Dalej wpisz mixed="true">, aby wskazać, że dany element może zawierać inne elementy oraz tekst (a nawet atrybuty). 4. Zadeklaruj sekwencję (patrz podrozdział „Ustalanie określonej sekwencji dla występowania elementów-dzieci”), nieuporządkowaną listę (patrz podrozdział „Dopuszczanie, aby elementy-dzieci pojawiały się w dowolnej kolejności”) lub wybór (patrz podrozdział „Tworzenie zbioru wyborów”), aby określić elementy-dzieci i strukturę dla danego typu złożonego. 5. Następnie zadeklaruj atrybuty (patrz podrozdział „Definiowanie atrybutów”), które powinny się pojawić w danym typie złożonym, jeśli w ogóle jakieś atrybuty mają się pojawić. 6. Wreszcie wpisz , aby zakończyć definicję typu złożonego.
Wskazówki Elementy z zawartością mieszaną są idealne do opisowych, opartych na tekście fragmentach informacji. Nie są jednak zbyt popularne w aplikacjach bazodanowych. Jak zostało to omówione w podrozdziale „Podstawy typów złożonych”, domyślnym warunkiem dla typów złożonych jest to, że wywodzą się one z elementu xs:complexContent, który ogranicza element xs:anyType. Z tego względu pominąłem te elementy w XML Schema.
166
Rysunek 11.27. Ten poprawny element XML dzieje zawiera zarówno luźny tekst, jak i elementy para (zaznaczone pogrubieniem)
Definiowanie typów złożonych
Wywodzenie typów złożonych z innych istniejących typów złożonych Możesz również tworzyć nowe typy złożone na podstawie już istniejących typów złożonych. Taki nowy typ złożony rozpoczyna się wszystkimi informacjami z istniejącego typu (rysunek 11.28), a następnie określone jego cechy są dodawane lub usuwane. Rysunek 11.28. Ten typ o nazwie typHistoria jest podstawowym typem złożonym, który zostanie wykorzystany w dwóch kolejnych przykładach
Aby wyprowadzić nowy typ złożony z istniejącego typu: 1. Wpisz , gdzie nazwa_typu_złożonego identyfikuje Twój nowy typ złożony. 3. Wpisz .
Rysunek 11.29. Tutaj wyprowadziłem nowy typ złożony o nazwie nowyTypHistoria, będący rozszerzeniem typu typHistoria przedstawionego na rysunku 11.28. Ten nowy typ dodaje na końcu sekwencji istniejącego podstawowego typu złożonego element kto_zbudowal
5. Możesz też wpisać , gdzie istniejący_typ identyfikuje nazwę istniejącego typu, z którego wywodzony będzie nowy typ złożony. 7. Zadeklaruj atrybuty (patrz podrozdział „Definiowanie atrybutów”), które powinny być częścią nowego typu złożonego. 8. Dopasuj odpowiedni znacznik zamykający dla znacznika użytego w punkcie 4. 9. Wpisz . 10. Wpisz , aby zakończyć definicję typu złożonego.
Wskazówki
Rysunek 11.30. Podczas wyprowadzania nowego typu złożonego z wykorzystaniem restrykcji, podstawowy typ jest powielany, a następnie dostosowywany. W tym przykładzie ustawiłem dla elementu sposob_zniszczenia ustaloną wartość „pożar”
Nowe typy złożone wyprowadzane przy użyciu restrykcji muszą być poprawnymi podzbiorami istniejącego typu złożonego. Do dopuszczalnych restrykcji zaliczyć możemy wartości domyślne lub ustalone (rysunek 11.30). Ponieważ jest to dość zaawansowany temat, omówione zostały tutaj jedynie podstawy.
167
Wywodzenie typów złożonych
4. Dalej wpisz
Rozdział 11.
Odwoływanie się do elementów zdefiniowanych globalnie W dokumencie XML Schema elementy zdefiniowane jako elementy-dzieci elementu głównego xs:schema są określane jako elementy zdefiniowane globalnie. Nazwane typy złożone są przykładem elementów zdefiniowanych globalnie. Możesz również zdefiniować globalnie indywidualny element (rysunek 11.31). Aby taki element mógł zostać użyty w dokumencie XML Schema, należy po jego zdefiniowaniu wywołać go lub się do niego odwołać.
Odwoływanie się do elementów
Aby odwołać się do elementu zdefiniowanego globalnie: 1. Wpisz
Rysunek 11.31. Ten element nazwa, będący elementem-dzieckiem elementu xs:schema, jest traktowany jako zdefiniowany globalnie. Do takiego elementu można się odwoływać w ramach dowolnej definicji typu złożonego, tak jak zostało to pokazane w kolejnym przykładzie
2. Następnie wpisz ref="etykieta", gdzie etykieta jest nazwą elementu zdefiniowanego globalnie. 3. Na tym etapie możesz w razie potrzeby określić za pomocą atrybutów minOccurs lub maxOccurs (patrz podrozdział „Kontrolowanie liczby wystąpień”), ile razy dany element może się pojawiać. 4. Wpisz />, aby zakończyć referencję do globalnego elementu (rysunek 11.32).
Rysunek 11.32. W tej definicji typu złożonego dla typu o nazwie typCud odwołuję się do globalnie zdefiniowanego elementu nazwa przedstawionego na rysunku 11.31
Wskazówki W swoim dokumencie XML Schema możesz odwoływać się do globalnie zadeklarowanego elementu tyle razy, ile chcesz. Ponadto każda referencja może posiadać własne odrębne wartości dla atrybutów minOccurs i maxOccurs. Lokalnie zadeklarowane elementy są automatycznie wywoływane przez definicję elementu-rodzica, w której się pojawiają. Nie mogą być wywoływane nigdzie indziej. Więcej informacji na temat lokalnych i globalnych deklaracji znajdziesz w podrozdziale „Lokalne i globalne definicje”.
168
Rysunek 11.33. Ten fragment kodu XML jest poprawny zarówno względem XML Schema z rysunku 11.31, jak i względem XML Schema 11.32. Na przykładzie widać element cud zawierający poprawny element nazwa
Definiowanie typów złożonych
Kontrolowanie liczby wystąpień Korzystając z XML Schema, możesz kontrolować, ile razy dany element, sekwencja, nieuporządkowana lista czy zbiór wyborów mogą pojawić się w poprawnym dokumencie XML (rysunki 11.34 i 11.35).
Aby określić minimalną liczbę wystąpień:
Rysunek 11.34. Dodałem nowy element wspolpracownik do typu typCud. Posiada on jeden element-dziecko zwany nazwa i zdefiniowany z wykorzystaniem odwołania do globalnie zdefiniowanego elementu nazwa przedstawionego na rysunku 11.31. W poprawnym dokumencie XML element wspolpracownik może mieć od zera do nieskończonej liczby tych elementów-dzieci
W znaczniku otwierającym wpisz minOccurs="n", gdzie n wskazuje najmniejszą liczbę razy, jaką element, sekwencja, nieuporządkowana lista lub zbiór wyborów mogą pojawić się, aby dany dokument XML mógł być uznany za poprawny.
Aby określić maksymalną liczbę wystąpień: W znaczniku otwierającym wpisz maxOccurs="n", gdzie n wskazuje największą liczbę razy, jaką element, sekwencja, nieuporządkowana lista lub zbiór wyborów mogą pojawić się, aby dany dokument XML mógł być uznany za poprawny.
Domyślną wartością dla atrybutów minOccurs i maxOccurs jest 1. Innymi słowy, jeśli inna wartość nie zostanie zdefiniowana za pomocą któregoś z tych atrybutów, dany element musi pojawić się dokładnie raz w poprawnym dokumencie XML. Rysunek 11.35. Atrybuty minOccurs i maxOccurs mogą być również stosowane do sekwencji, nieuporządkowanych list lub zbiorów wyborów. W tym fragmencie kodu dopuszczalne jest zastosowanie od jednego do czterech elementów z tego zbioru wyborów. Oznacza to, że dopuszczalna liczba elementów-dzieci o nazwie wspolpracownik musi zawierać się w przedziale od jednego do czterech, a każdy z tych elementów może mieć dowolną liczbę elementów nazwa i (lub) organizacja
Wartość atrybutu minOccurs musi być nieujemną liczbą całkowitą (0, 1, 2, 3 lub większą). Wartość atrybutu maxOccurs może być dowolną nieujemną liczbą całkowitą i być zdefiniowana za pomocą argumentu unbounded (nieograniczony), który wskazuje, że dany element może pojawiać się dowolną liczbę razy. Atrybuty minOccurs i maxOccurs nie mogą być użyte przy definiowaniu elementu globalnie. Mają one sens jedynie przy lokalnych referencjach do elementów globalnych lub przy lokalnie definiowanych elementach. Korzystając z elementu xs:all (patrz podrozdział „Dopuszczanie, aby elementy-dzieci pojawiały się w dowolnej kolejności”), wartość atrybutu minOccurs możesz ustawić jedynie na 0 lub 1, a wartość atrybutu maxOccurs tylko na 0.
169
Kontrolowanie liczby wystąpień
Wskazówki
Rozdział 11.
Definiowanie nazwanych grup modelowych Jeśli jakiś zbiór elementów pojawia się w kilku miejscach w Twoim dokumencie XML, możesz połączyć te elementy w grupę, aby łatwiej można było odwoływać się do nich za jednym razem. Innymi słowy, podobnie jak możesz tworzyć globalnie definiowany element i odwoływać się do niego w całym XML Schema, możesz również nazwać grupę modelową (sekwencję, nieuporządkowaną listę lub wybór) i odwoływać się do niej w całym dokumencie XML Schema.
Aby zdefiniować nazwaną grupę modelową:
Definiowanie nazwanych grup modelowych
1. Wpisz , aby zakończyć znacznik otwierający grupy. 4. Zadeklaruj sekwencje (patrz podrozdział „Ustalanie określonej sekwencji dla występowania elementówdzieci”), nieuporządkowane listy (patrz podrozdział „Dopuszczanie, aby elementy-dzieci pojawiały się w dowolnej kolejności”) i (lub) zbiory wyborów (patrz podrozdział „Tworzenie zbioru wyborów”), które będą tworzyć daną grupę modelową. 5. Wpisz , aby zakończyć definicję grupy (rysunek 11.36).
Wskazówki Podobnie jak elementy definiowane globalnie, nazwana grupa modelowa może być definiowana jedynie na górnym poziomie schematu (element-dziecko elementu xs:schema). Ponadto również (tak jak ma to miejsce w przypadku elementów definiowanych globalnie), do nazwanej grupy modelowej możesz odwoływać się tyle razy, ile chcesz (patrz podrozdział „Odwoływanie się do nazwanej grupy modelowej”). Nazwana grupa modelowa jest konstrukcją analogiczną do encji parametrycznej w DTD (patrz rozdział 7., „Encje i notacje w dokumentach DTD”).
170
Rysunek 11.36. Ta nazwana grupa modelowa element_obrazek zawiera element o nazwie obrazek będący pustym typem złożonym oraz kolejny element-dziecko o nazwie zrodlo, którego wartością jest ciąg znaków
Definiowanie typów złożonych
Odwoływanie się do nazwanej grupy modelowej Po utworzeniu nazwanej grupy modelowej możesz odwoływać się do niej w tylu definicjach typów złożonych, w ilu chcesz (rysunek 11.37). Możesz nawet odwoływać się do niej w innych grupach.
Aby odwołać się do nazwanej grupy modelowej: 1. Wpisz
3. Wpisz />, aby zakończyć referencję.
Wskazówka Możesz odwoływać się do grupy w definicji typu złożonego (patrz podrozdział „Definiowanie typów złożonych, które zawierają elementy-dzieci”), w sekwencji (patrz podrozdział „Ustalanie określonej sekwencji dla występowania elementów-dzieci”), w nieuporządkowanej liście (patrz podrozdział „Dopuszczanie, aby elementy-dzieci pojawiały się w dowolnej kolejności”), w zbiorze wyborów (patrz podrozdział „Tworzenie zbioru wyborów”) lub w innych grupach nazwanych (patrz podrozdział „Definiowanie nazwanych grup modelowych”).
Rysunek 11.38. W tym poprawnym względem XML Schema z rysunków 11.36 i 11.37 fragmencie kodu XML elementy obrazek_glowny i obrazek_miniaturka posiadają elementy zdefiniowane w nazwanej grupie modelowej. Ponadto każdy z nich ma własne indywidualne elementy
171
Odwoływanie się do nazwanej grupy modelowej
Rysunek 11.37. Obydwa elementy, obrazek_glowny oraz obrazek_miniaturka, są teraz zdefiniowane przez nazwaną grupę modelową element_obrazek, zdefiniowaną na rysunku 11.36. Każdy z tych elementów może również posiadać dodatkowe indywidualne elementy podpis i brzeg_ramki
2. Następnie wpisz ref="nazwa_grupy_modelowej", gdzie nazwa_grupy_modelowej identyfikuje grupę, którą utworzyłeś w punkcie 2. procedury opisanej w podrozdziale „Definiowanie nazwanych grup modelowych”.
Rozdział 11.
Definiowanie atrybutów Atrybuty są elementami typu prostego, ponieważ nie zawierają ani elementów-dzieci, ani atrybutów. Ponieważ jednak zawsze pojawiają się w elementach typu złożonego, zostały omówione właśnie w tym rozdziale, a nie w poprzednim.
Aby zdefiniować atrybut: 1. W obrębie definicji typu złożonego wpisz
Rysunek 11.39. W tym fragmencie kodu element id_sekcji został zadeklarowany za pomocą typu podstawowego xs:positiveInteger. Element id_gazety został zadeklarowany za pomocą definicji anonimowego typu prostego z wykorzystaniem restrykcji aspektu wzorca, dopuszczającego dokładnie cztery cyfry
Definiowanie atrybutów
Aby użyć podstawowego lub nazwanego typu prostego: 3. Wpisz type="typ_prosty"/>, gdzie typ_prosty jest nazwanym lub podstawowym typem atrybutu, który definiujesz (rysunek 11.39).
Aby użyć anonimowego typu prostego: 3. Wpisz >, aby zakończyć znacznik otwierający. 4. Następnie wpisz . 5. Dodaj dowolne restrykcje (lub aspekty). 6. Wpisz , aby zamknąć element typu prostego. 7. Wpisz , aby zakończyć znacznik otwierający (rysunek 11.39).
Aby użyć atrybutu zdefiniowanego globalnie: 3. Wpisz ref="etykieta"/>, gdzie etykieta identyfikuje definicję atrybutu, który już zdefiniowałeś globalnie.
Wskazówka Atrybuty muszą być definiowane na samym końcu typu złożonego, do którego należą, czyli po wszystkich elementach zdefiniowanych w danym typie prostym.
172
Rysunek 11.40. Biorąc pod uwagę XML Schema z rysunku 11.39, ten fragment kodu XML jest niepoprawny. Chociaż obydwa atrybuty, id_sekcji i id_gazety, są dodatnimi liczbami całkowitymi, atrybut id_gazety powinien mieć teraz dokładnie cztery cyfry
Definiowanie typów złożonych
Wymaganie atrybutu Atrybut jest zawsze opcjonalny, chyba że zdefiniujesz inaczej. Innymi słowy, w poprawnym dokumencie XML może się on pojawiać, ale nie musi. Jednak jeśli chcesz, możesz wymagać obecności atrybutu (lub jego braku), gdy ustalasz zasady dla poprawnego dokumentu XML.
Aby wymusić obecność atrybutu:
Rysunek 11.41. Ponieważ domyślnym warunkiem dla atrybutu jest jego opcjonalność, musisz wyraźnie wskazać, że jest on wymagany
1. W obrębie definicji atrybutu wpisz use="required", aby wskazać, że dany atrybut musi się pojawić, żeby dokument XML mógł być uznany za poprawny (rysunek 11.41). 2. Możesz również dodać value="musi_być", gdzie musi_być jest jedyną dopuszczalną wartością dla tego atrybutu.
Aby wymusić brak atrybutu:
Wskazówka Możesz również w definicji atrybutu użyć instrukcji use="optional" (opcjonalne występowanie atrybutu), ponieważ jednak jest to warunek domyślny, ta instrukcja nie jest wymagana.
173
Wymaganie atrybutu
Rysunek 11.42. Obydwa przedstawione elementy zrodlo są poprawne, ponieważ zgodnie z definicją XML Schema z rysunku 11.41 wymagany jest jedynie atrybut id_sekcji. Jeśli atrybut nie jest wyraźnie wymagany, jest uznawany za opcjonalny
W obrębie definicji atrybutu wpisz use="prohibited", aby dokument XML mógł być uznany za poprawny tylko wtedy, gdy dany atrybut nie jest obecny.
Rozdział 11.
Predefiniowanie zawartości atrybutu W XML Schema istnieją dwa sposoby predefiniowania zawartości atrybutu. Możesz wskazać konkretną wartość atrybutu lub ustawić dla niego wartość początkową, bez względu na to, czy argument się pojawi, czy nie. Ta pierwsza opcja zwana jest wartością ustaloną (ang. fixed), a ta druga wartością domyślną (ang. default).
Rysunek 11.43. Jeśli atrybut id_gazety pojawia się w dokumencie XML, musi zawierać wartość „21”. Atrybut ten może być jednak pominięty
Aby wskazać zawartość atrybutu: W obrębie definicji atrybutu wpisz fixed="zawartość", gdzie zawartość określa, jaką wartość powinien mieć dany atrybut, aby dokument mógł być uznany za poprawny (rysunek 11.43). (Ma to zastosowanie tylko wtedy, kiedy dany atrybut pojawia się w dokumencie XML).
Predefiniowanie zawartości atrybutu
Aby ustawić wartość początkową atrybutu: W obrębie definicji atrybutu wpisz default="zawartość", gdzie zawartość określa wartość, jaką powinien przyjąć atrybut, jeśli jest on pomijany w dokumencie XML (rysunek 11.45).
Rysunek 11.44. Dwa pierwsze fragmenty kodu XML są poprawne. W pierwszym fragmencie atrybut id_gazety ma wartość równą wartości ustalonej. W drugim fragmencie atrybut id_gazety został pominięty (i pozostanie wykluczony). W trzecim fragmencie kodu wartość atrybutu id_gazety nie jest równa wartości ustalonej, więc element jest niepoprawny
Wskazówki Argument fixed ustala wartość tylko wtedy, gdy dany atrybut faktycznie pojawia się w dokumencie XML. Jeśli atrybut jest pomijany, nie jest ustawiana żadna wartość. Jeśli ustawiony jest argument default i atrybut jest pomijany w dokumencie XML, wtedy przyjmowana jest jego wartość domyślna.
Rysunek 11.45. Atrybut id_gazety ma teraz wartość domyślną. Będzie ona wartością początkową, bez względu na to, czy atrybut ten pojawi się w dokumencie XML
Jeśli ustawisz argument default, jedyną dopuszczalną wartością atrybutu use jest optional (patrz podrozdział „Wymaganie atrybutu”). Nie możesz stosować argumentów default i fixed jednocześnie w tej samej definicji atrybutu.
Rysunek 11.46. W tym przykładzie wszystkie trzy fragmenty kodu XML są poprawne. W drugim fragmencie atrybut id_gazety zostanie utworzony automatycznie i uzyska wartość domyślną
174
Definiowanie typów złożonych
Definiowanie grup atrybutów Jeśli potrzebujesz użyć tego samego zbioru atrybutów w kilku miejscach w swoim dokumencie XML, wówczas lepiej zdefiniować grupę atrybutów, a następnie odwoływać się do tych wszystkich atrybutów za jednym razem.
Rysunek 11.47. Dzięki zdefiniowaniu grupy atrybutów łatwiej jest wykorzystywać ponownie takie atrybuty w wielu definicjach elementów XML Schema (patrz podrozdział „Odwoływanie się do grup atrybutów”)
Jest to ta sama koncepcja, którą napotkałeś przy elementach definiowanych globalnie i nazwanych grupach modelowych.
Aby zdefiniować grupę atrybutów: 1. Wpisz , gdzie nazwa_grupy_atrybutów identyfikuje Twoją grupę atrybutów. 3. Zdefiniuj każdy atrybut należący do grupy lub odwołaj się do już zdefiniowanych atrybutów (patrz podrozdział „Definiowanie atrybutów”). 4. Wpisz , aby zakończyć definicję grupy atrybutów (rysunek 11.47).
Podobnie jak wszystkie elementy definiowane globalnie, grupa atrybutów może być zdefiniowana tylko na najwyższym poziomie schematu (element-dziecko elementu xs:schema). Ponadto — również tak jak w przypadku wszystkich elementów definiowanych globalnie — do grupy atrybutów możesz odwoływać się tyle razy, ile chcesz (patrz podrozdział „Odwoływanie się do grup atrybutów”). W punkcie 2. powyższej procedury możesz odwoływać się jedynie do atrybutów zdefiniowanych globalnie, czyli takich, które zostały zadeklarowane na najwyższym poziomie danego schematu. Więcej szczegółów na ten temat znajdziesz w podrozdziale „Lokalne i globalne definicje”. Grupa atrybutów może zawierać referencję do innych grup atrybutów.
175
Definiowanie grup atrybutów
Wskazówki
Rozdział 11.
Odwoływanie się do grup atrybutów Po zdefiniowaniu grupy atrybutów możesz odwoływać się do niej wszędzie tam, gdzie dane atrybuty są wymagane — bez względu na to, czy jest to definicja typu złożonego, czy nawet są to inne grupy atrybutów (rysunek 11.48).
Aby odwołać się do grupy atrybutów: 1. Wpisz , aby zidentyfikować grupę atrybutów, którą utworzyłeś w punkcie 2. procedury opisanej w podrozdziale „Definiowanie grup atrybutów”.
Rysunek 11.48. Wykorzystując zdefiniowaną na rysunku 11.47 grupę atrybutów o nazwie atrybutyObrazka, utworzyłem dwa nazwane typy złożone: typObrazek i typWideo. Typ o nazwie typObrazek zostanie wykorzystany dla elementu obrazek_glowny, a typ o nazwie typWideo zostanie użyty do utworzenia elementu wideo_glowne. Zwróć uwagę, że posiada on dodatkowy atrybut format, zadeklarowany po grupie atrybutów
Odwoływanie się do grup atrybutów
Wskazówki Atrybuty i grupy atrybutów muszą być definiowane na samym końcu typu złożonego, do którego należą, bądź po zdefiniowaniu wszystkich pozostałych elementów. Grupy atrybutów są konstrukcją analogiczną do encji parametrycznych w dokumentach DTD (patrz rozdział 7., „Encje i notacje w dokumentach DTD”). Są one jednak ograniczone do reprezentowania wyłącznie zbiorów atrybutów.
176
Rysunek 11.49. Obydwa elementy, obrazek_glowny i wideo_glowne, współdzielą atrybuty plik, szer i wys. Korzyścią płynącą z zastosowania grupy atrybutów jest to, że wszystkie te trzy atrybuty zostały zdefiniowane tylko raz, ale użyte w więcej niż jednej definicji typu złożonego
Definiowanie typów złożonych
Lokalne i globalne definicje W XML Schema elementy mogą być definiowane zarówno lokalnie, jak i globalnie. Element definiowany globalnie jest definiowany jako element-dziecko elementu xs:schema. Ponieważ jest on definiowany na najwyższym poziomie danego schematu, jego zasięg (czyli to, gdzie może być wykorzystany) obejmuje cały schemat.
Rysunek 11.50. Przykład z rysunku 11.34 działa poprawnie, po części dlatego, że globalnie zdefiniowany element nazwa nie wymaga atrybutu jezyk. Gdyby jednak wymagał on atrybutu jezyk, tak jak pokazano w tym przykładzie, wszystkie elementy nazwa będące elementami-dziećmi elementu wspolpracownik byłyby niepoprawne
Z kolei lokalnie definiowany element jest definiowany jako element-dziecko jakiegoś innego elementu. Z tego względu jego zasięg obejmuje jedynie ramy elementurodzica. Elementy definiowane globalnie, podobnie jak nazwane typy niestandardowe, nie stają się automatycznie częścią dokumentu XML Schema. Dana definicja determinuje jedynie, jak taki element powinien wyglądać. Do elementów globalnych trzeba się wyraźnie odwołać, żeby faktycznie pojawiły się w poprawnym dokumencie XML.
Przedstawiłem już w tym rozdziale, jakie korzyści płyną z wielokrotnego używania elementów zdefiniowanych globalnie (patrz podrozdziały „Odwoływanie się do elementów zdefiniowanych globalnie”, „Odwoływanie się do nazwanej grupy modelowej” oraz „Odwoływanie się do grup atrybutów”).
Rysunek 11.51. Biorąc pod uwagę kwestię opisaną w przykładzie z rysunku 11.50, lepiej byłoby zdefiniować każdy z elementów nazwa lokalnie — osobno dla elementów cud i wspolpracownik
Z drugiej strony jedną z korzyści używania elementów zdefiniowanych lokalnie jest wyizolowanie zasięgu elementu. Wyizolowany zasięg oznacza, że nazwa i definicja danego elementu nie mogą wejść w konflikt z innymi elementami z tego samego dokumentu XML Schema, wykorzystującymi tę samą nazwę. Wybór będzie uzależniony od Twoich potrzeb odnośnie do wielokrotności użycia danego elementu w zestawieniu z potrzebami izolowania tego elementu i jego definicji (rysunki 11.50 i 11.51).
Wskazówka W DTD każdy element jest deklarowany globalnie. Nie istnieje nic takiego jak lokalnie definiowany element.
177
Lokalne i globalne definicje
Jednak elementy definiowane lokalnie, podobnie jak anonimowe typy niestandardowe, automatycznie stają się częścią dokumentu XML. Miejsce ich zdefiniowania określa miejsce, w którym muszą pojawić się w dokumencie XML.
Rozdział 11.
178
Przestrzenie nazw
V
Część V Przestrzenie nazw
Rozdział 12. Przestrzenie nazw XML
181
Rozdział 13. Używanie przestrzeni nazw XML
187
179
Rozdział x.
180
Przestrzenie nazw XML
12
Rozdział 12. Przestrzenie nazw XML Nauczyłeś się już tworzyć dokumenty XML, przekształcać je i wyświetlać, a także definiować zbiory elementów i atrybutów, które te dokumenty mogą zawierać. Teraz wyobraź sobie, że chcesz połączyć kilka własnych dokumentów XML z dokumentami utworzonymi przez kogoś innego. W ten sposób możesz zorientować się, że czyjeś dokumenty wykorzystują niektóre z nazw elementów, które sam zastosowałeś. Przykładowo dokument „Cuda starożytnego świata” wykorzystuje element nazwa zawierający nazwy poszczególnych cudów, podczas gdy inna osoba używa elementu nazwa, który zawiera nazwę starożytnej cywilizacji. W przypadku połączenia takich dokumentów źródłowe dane elementów staną się niejasne i w efekcie stracą znaczenie.
Taka grupa nazw elementów jest zwana przestrzenią nazw (ang. namespace), a identyfikator, którego użyłem, jest określany mianem nazwy przestrzeni nazw (ang. namespace name). I choć zabawnie byłoby użyć imienia Kevin jako nazwy dla przestrzeni nazw, to wymagany w tym przypadku format jest nieco bardziej ustrukturyzowany, o czym dowiesz się w tym rozdziale.
181
Przestrzenie nazw XML
Rozwiązaniem tego problemu jest grupowanie nazw elementów dla każdego dokumentu XML w jego własnej przestrzeni nazw. Wtedy podczas odwoływania się do konkretnego elementu element ten będzie identyfikowany z przestrzenią nazw, w której rezyduje. Taki format zapewnia możliwość rozróżnienia elementów z jednej grupy dokumentów XML od elementów z innej grupy. Mógłbym na przykład nazwać swoją przestrzeń „Kevin” i identyfikować elementy w swoim dokumencie XML za pomocą tej nazwy. Wtedy element Kevin:nazwa nie zostanie pomylony z innym elementem nazwa.
Rozdział 12.
Projektowanie nazwy przestrzeni nazw Ponieważ istotą przestrzeni nazw jest rozróżnianie elementów o tej samej nazwie, przestrzeń nazw musi mieć bezwzględnie unikatową i niezmienną nazwę. W języku XML nazwy przestrzeni nazw są zapisywane w formie URI (ang. Uniform Resource Identifier), zwanego jednolitym identyfikatorem zasobu.
Aby zaprojektować nazwę przestrzeni nazw: 1. Rozpocznij od swojej nazwy domenowej. 2. Dodaj informacje opisowe (w formie ścieżki URI), aby utworzyć unikatową nazwę dla swojej przestrzeni nazw (rysunek 12.1).
Projektowanie nazwy przestrzeni nazw
Wskazówki URI to ciąg znaków identyfikujących zasób. Z kolei URL (ang. Uniform Resource Locator), czyli ujednolicony lokalizator zasobu, jest najbardziej powszechną formą URI i zalecam korzystanie z niej przy projektowaniu nazw przestrzeni nazw. Wykorzystanie własnej domeny jako podstawy dla nazwy przestrzeni nazw pozwala Ci zyskać pewność, że dana nazwa będzie unikatowa. Nikt inny nie może używać Twojej nazwy domenowej. Jedyne wymagania dla URI to unikatowość i trwałość (praktycznie permanentność). Zalecam również, aby URI było spójne, jeśli zamierzasz tworzyć wiele przestrzeni nazw. W razie potrzeby możesz do swojej przestrzeni nazw dodać informacje o wersji. Istnieje wiele nieporozumień w kwestii tego, na co wskazuje nazwa przestrzeni nazw. W rzeczywistości, choć nazwa przestrzeni nazw może wskazywać DTD lub XML Schema, to nie jest to powszechne ani wymagane w rekomendacji dla przestrzeni nazw XML wydanej przez organizację W3C. Ponadto, nawet jeśli URI wskazuje plik, oprogramowanie XML nawet go nie sprawdza.
182
Rysunek 12.1. Nazwa przestrzeni nazw powinna mieć postać adresu URI. Zalecam stosowanie formatu URL, ponieważ URL nie musi wskazywać (i zazwyczaj nie wskazuje) żadnego rzeczywistego pliku!
Przestrzenie nazw XML
Deklarowanie domyślnej przestrzeni nazw Po utworzeniu nazwy przestrzeni nazw możesz zadeklarować ją jako domyślną przestrzeń nazw dla swojego dokumentu XML (rysunek 12.2). Rysunek 12.2. Przy takiej deklaracji domyślnej przestrzeni nazw wszystkie elementy tego dokumentu są częścią przestrzeni nazw http://www.kehogo.com/ns/cuda/1.0
Aby zadeklarować domyślną przestrzeń nazw dla dokumentu XML: 1. W obrębie znacznika otwierającego elementu głównego wpisz xmlns=. (jest to atrybut dla zadeklarowania przestrzeni nazw XML — ang. XML namespace). 2. Następnie wpisz "URI", gdzie URI identyfikuje nazwę Twojej przestrzeni nazw (patrz podrozdział „Projektowanie nazwy przestrzeni nazw”).
Wskazówki
Rysunek 12.3. W tym przykładzie dodałem nowy element cywilizacja, zadeklarowany jako część przestrzeni nazw http://www.kehogo.com/ns/starozytne_cyw/2.3. W konsekwencji elementy cywilizacja, nazwa, polozenie i wszystkie pozostałe elementy-dzieci elementu cywilizacja są częścią jego domyślnej przestrzeni nazw (czyli przestrzeni nazw dotyczącej starożytnych cywilizacji). Deklarując tę domyślną przestrzeń nazw dla elementu cywilizacja, uniknąłem konfliktu pomiędzy elementem nazwa „cudów starożytnego świata” i elementem nazwa „starożytnych cywilizacji”
Możesz zadeklarować domyślną przestrzeń nazw dla dowolnego elementu w swoim dokumencie, a nie tylko dla elementu głównego. W tym celu zastosuj powyższą procedurę, zastępując element główny tym elementem, dla którego chcesz zadeklarować domyślną przestrzeń nazw. Uchyli to domyślną przestrzeń nazw zadeklarowaną przez jakikolwiek element będący przodkiem danego elementu (rysunek 12.3). Oznaczanie wybranego elementu domyślną przestrzenią nazw ma wpływ nie tylko na ten element, ale także na wszystkie jego elementy-dzieci. Możesz uchylić domyślną przestrzeń nazw, określając prefiksowaną przestrzeń dla indywidualnego elementu, w sposób opisany w podrozdziałach „Deklarowanie prefiksu nazwy przestrzeni nazw” i „Oznaczanie elementów prefiksem przestrzeni nazw”. W tym przypadku nie ma to wpływu na elementy-dzieci. W przypadku gdy domyślna przestrzeń nazw nie jest zadeklarowana do konkretnego elementu lub nie została odziedziczona po elementach-przodkach, element ten jest traktowany jako nierezydujący w żadnej przestrzeni nazw (ang. no namespace). Elementy nierezydujące w żadnej przestrzeni nazw mogą być przydzielane do domyślnych przestrzeni nazw, co uchyla ich stan no namespace.
183
Deklarowanie domyślnej przestrzeni nazw
Deklarowanie domyślnej przestrzeni nazw dla elementu głównego oznacza, że wszystkie elementy z danego dokumentu będą przypisane do tej przestrzeni nazw.
Rozdział 12.
Deklarowanie prefiksu nazwy przestrzeni nazw Zadeklarowanie domyślnej przestrzeni nazw dla danego elementu dotyczy również wszystkich jego elementów-dzieci. Możesz również zdecydować, aby oznaczyć konkretne indywidualne elementy w swoim dokumencie XML określoną przestrzenią nazw, ale nie stosować tej przestrzeni nazw do elementów-dzieci tych elementów. W tym celu możesz zadeklarować dla danej przestrzeni nazw specjalny przydomek, czyli prefiks, a następnie stosować ten prefiks dla poszczególnych elementów w określony sposób.
Aby zadeklarować prefiks dla nazwy przestrzeni nazw:
Deklarowanie prefiksu nazwy przestrzeni nazw
1. W elemencie głównym dokumentu wpisz xmlns:prefiks, gdzie prefiks będzie przydomkiem danej przestrzeni nazw. 2. Następnie wpisz ="URI", gdzie URI identyfikuje nazwę przestrzeni nazw, do której odnosił się będzie dany prefiks (rysunek 12.4).
Rysunek 12.4. Tutaj zadeklarowałem przestrzeń nazw starożytne cywilizacje w elemencie głównym dokumentu i przydzieliłem jej prefiks star_cyw. Mogę teraz używać tego prefiksu w całym dokumencie, aby wskazać poszczególne elementy należące do tej przestrzeni nazw
Wskazówki Prefiks nie może rozpoczynać się literami xml w żadnej kombinacji wielkich i małych liter. Prefiksu możesz używać w dowolnym elemencie znajdującym się tam, gdzie zadeklarowałeś dany prefiks, również w samym elemencie zawierającym ten prefiks. Oznacza to, że jeśli deklarujesz prefiks w elemencie głównym, możesz go używać w dowolnym elemencie w tym dokumencie, również w samym elemencie głównym. Jeśli deklarujesz prefiks w elemencie innym niż element główny, możesz go używać tylko w danym elemencie i (lub) w jego elementach potomnych (rysunek 12.5). W każdym elemencie możesz zadeklarować tyle prefiksów przestrzeni nazw, ile potrzebujesz.
184
Rysunek 12.5. W tym przykładzie prefiks przestrzeni nazw star_cyw nie został zadeklarowany w elemencie głównym, ale w elemencie star_cyw:cywilizacja. W konsekwencji przestrzeń ta może być stosowana tylko dla tego elementu i jego elementów-dzieci
Przestrzenie nazw XML
Oznaczanie elementów prefiksem przestrzeni nazw Po zadeklarowaniu prefiksu dla nazwy przestrzeni nazw, możesz używać tego prefiksu do oznaczania poszczególnych elementów. W ten sposób możesz przydzielić te elementy do różnych przestrzeni nazw w swoim dokumencie XML, bez wpływania na rodzeństwo lub dzieci tych elementów (rysunek 12.6).
Aby oznaczyć poszczególne elementy różnymi przestrzeniami nazw: 1. Wpisz <, aby rozpocząć element. 2. Następnie wpisz prefiks:, gdzie prefiks wskazuje przestrzeń nazw, do której dany element należy (tak jak zostało to zadeklarowane w podrozdziale „Deklarowanie prefiksu nazwy przestrzeni nazw”). 3. Dalej wpisz element, gdzie element jest nazwą elementu, którego chcesz użyć.
Wskazówki
Rysunek 12.6. Każdy element w przestrzeni nazw starożytne cywilizacje jest poprzedzony jej prefiksem star_cyw:, aby wskazać, że należy on do tej przestrzeni nazw. Choć wpisywanie za każdym razem star_cyw: może być nieco uciążliwe, to zastosowanie deklaracji http://www.kehogo.com/ns/starozytne_cyw/2.3 byłoby jeszcze gorszym rozwiązaniem
Tylko te elementy, których nazwy są poprzedzone prefiksem, są identyfikowane z przestrzenią nazw zadeklarowaną za pomocą tego prefiksu. Różni się to od domyślnych przestrzeni nazw, gdzie dany element i wszystkie jego elementy-dzieci są identyfikowane z tą przestrzenią nazw. Procesor XML traktuje elementy niepoprzedzone prefiksem jako elementy należące do domyślnej przestrzeni nazw (patrz podrozdział „Deklarowanie domyślnej przestrzeni nazw”), jeśli taka istnieje, lub jako nierezydujące w żadnej przestrzeni nazw, jeśli nie ma domyślnej przestrzeni nazw. Procesor XML traktuje prefiks jako część nazwy elementu. Z tego względu znacznik otwierający musi odpowiadać znacznikowi zamykającemu. Jeśli więc wpisałeś jako znacznik otwierający danego elementu, to jako znacznik zamykający musisz wpisać . Jeśli w określonej sekcji używasz wielu elementów z danej przestrzeni nazw, łatwiej jest zadeklarować dla tej sekcji domyślną przestrzeń nazw (patrz podrozdział „Deklarowanie domyślnej przestrzeni nazw”).
185
Oznaczanie elementów prefiksem
4. Zakończ element w standardowy sposób (szczegółowe informacje na ten temat znajdziesz w rozdziale1., „Pisanie dokumentów XML”).
Rozdział 12.
W jaki sposób przestrzenie nazw wpływają na atrybuty Chociaż mógłbyś powiązać atrybut z określoną przestrzenią nazw, poprzedzając go właściwym prefiksem, to prawie nigdy nie jest to konieczne. Atrybuty i tak są już unikatowe, z uwagi na to że zawarte są w określonych elementach.
Rysunek 12.7. Choć obydwa elementy, zrodlo i mapa, mają atrybut id_sekcji, to atrybuty te nie nakładają się na siebie w taki sposób jak elementy o tej samej nazwie
Jak przestrzenie nazw wpływają na atrybuty
Kiedy widzisz na przykład atrybut id_sekcji w elemencie zrodlo, wiesz, że atrybut ten należy do elementu zrodlo, a tym samym do jego przestrzeni nazw. Wszystko jest jasne. Jeśli mielibyśmy kolejny atrybut id_sekcji znajdujący się, powiedzmy, w elemencie mapa, potraktowalibyśmy ten atrybut jako należący do elementu mapa bez konieczności szukania jakichkolwiek innych wskazówek. Jest tak po prostu dlatego, że dany atrybut jest fizycznie zawarty w elemencie mapa (rysunek 12.7). Jeśli atrybut nie ma prefiksu, co jest najczęstszym przypadkiem, wtedy jest on traktowany jako nierezydujący w żadnej przestrzeni nazw (ponieważ domyślna przestrzeń nazw nie ma zastosowania do atrybutów). W takiej sytuacji atrybut ma zakres lokalny, co jest ciekawym sposobem wskazania, że jest on identyfikowany przez przestrzeń nazw elementu, w którym jest zawarty. Choć jest to dość rzadkie, istnieją przypadki, w których trzeba powiązać atrybut z określoną przestrzenią nazw, poprzedzając go odpowiednim prefiksem. Wyobraź sobie, że musisz połączyć w jeden element dwa elementy z różnych przestrzeni nazw, a obydwa te elementy posiadają atrybuty o tej samej nazwie. W tej sytuacji musisz rozróżnić te atrybuty, ponieważ pojedynczy element nie może mieć kilku atrybutów o tej samej nazwie. Poprzedzając każdy z atrybutów odpowiednim prefiksem jego przestrzeni nazw, stworzysz unikatowe atrybuty, ponieważ procesor XML traktuje prefiks jako część nazwy atrybutu (rysunek 12.8).
186
Rysunek 12.8. W tym przykładzie pierwsze dwa elementy to elementy obrazek_glowny zawierające atrybut plik. Pierwszy należy do przestrzeni nazw css:, a drugi do przestrzeni nazw star_cyw:. W trzecim fragmencie kodu XML połączyłem te dwa elementy obrazek_glowny w pojedynczy element, tworząc unikatowe atrybuty plik dzięki wykorzystaniu odpowiednich prefiksów ich przestrzeni nazw
Używanie przestrzeni nazw XML
13
Rozdział 13. Używanie przestrzeni nazw XML [RS1] Jak dowiedziałeś się w poprzednim rozdziale, przestrzeń nazw jest zbiorem powiązanych elementów i atrybutów, identyfikowanym za pomocą nazwy przestrzeni nazw. Nazwa przestrzeni nazw musi być unikatowa i najczęściej jest wywoływana za pomocą skróconej nazwy lub prefiksu. Przestrzenie nazw są najczęściej wykorzystywane w celu rozróżnienia elementów o tej samej nazwie. Mówiąc ściślej, przestrzenie nazw pomagają rozróżnić identycznie nazwane elementy globalne, ponieważ elementy lokalne i atrybuty są zasadniczo unikatowe z uwagi na ich kontekst. Połączenie nazwy przestrzeni nazw i nazwy elementu zwane jest nazwą rozszerzoną (ang. expanded name). Ponieważ nazwa przestrzeni nazw musi być unikatowa, nazwa rozszerzona również jest unikatowa. (Uwaga! Takie połączenie jest również określane mianem nazwy uniwersalnej, nazwy kwalifikowanej lub QName).
W tym rozdziale omówione zostaną pewne istotne szczegóły dotyczące sposobu używania dokumentów XML i przestrzeni nazw XML z tymi językami.
187
Używanie przestrzeni nazw XML
Aż do tej części książki wszystkie dokumenty XML, XSL, DTD i XML Schema nie posiadały żadnej przestrzeni nazw. Teraz, dzięki wprowadzeniu przestrzeni nazw w dokumentach XML, relacja pomiędzy dokumentami XML i tymi towarzyszącymi technologiami ulegnie zmianie.
Rozdział 13.
Wypełnianie przestrzeni nazw XML W części IV tej książki dowiedziałeś się, że definicje XML Schema określają elementy i atrybuty, z których składają się poprawne dokumenty XML. Jak się okazuje, definicje XML Schema mogą również określać elementy i atrybuty zawarte w przestrzeni nazw XML. Nie musisz robić nic specjalnego, jeśli chodzi o sposób definiowania elementów i atrybutów. Po prostu zastosuj się do instrukcji opisanych w rozdziałach 10. i 11. Musisz jednak określić docelową przestrzeń nazw (ang. target namespace), do której dane elementy i atrybuty będą należeć. Ten proces określania elementów i atrybutów dla docelowej przestrzeni nazw jest zwany wypełnianiem przestrzeni nazw (ang. populating the namespace).
Aby wypełnić przestrzeń nazw: W elemencie głównym swojego dokumentu XML Schema wpisz targetNamespace="URI", gdzie URI jest nazwą przestrzeni nazw, która ma być wypełniona (rysunek 13.1).
Wypełnianie przestrzeni nazw XML
Wskazówki W procesie wypełniania przestrzeni nazw tylko elementy i atrybuty zdefiniowane globalnie (na najwyższym poziomie) zostają powiązane z daną przestrzenią nazw. Pamiętaj, że globalnie zdefiniowany element lub atrybut jest dzieckiem elementu xs:schema i w rzeczywistości może być elementem, atrybutem, definicją typu złożonego lub prostego, nazwaną grupą modelową albo nazwaną grupą atrybutów. Nie oznacza to jednak, że nie możesz używać lub przeprowadzać walidacji elementów zdefiniowanych lokalnie, takich jak elementy cud, nazwa lub lokalizacja, przedstawione na rysunku 13.1. Kiedy wykonujesz walidację dokumentu XML względem definicji XML Schema z tego rysunku, upewniasz się, że żaden z tych lokalnie zdefiniowanych elementów nie jest powiązany z przestrzenią nazw.
188
Rysunek 13.1. W tym przykładzie element cuda_starozytnosci oraz typ złożony typCud są teraz identyfikowane z przestrzenią nazw http://www.kehogo.com/ns/css/1.0. Elementy cud, nazwa, lokalizacja, wysokosc, historia, obrazek_glowny i zrodlo nie są identyfikowane z tą przestrzenią nazw, ponieważ nie są elementami zdefiniowanymi globalnie
Używanie przestrzeni nazw XML
Dokumenty XML Schema, dokumenty XML oraz przestrzenie nazw Teraz, kiedy Twój dokument XML Schema posiada wypełnioną przestrzeń nazw, musisz dostosować relację pomiędzy XML Schema a dokumentem XML. Dowiedziałeś się już, jak wskazać w dokumencie XML lokalizację XML Schema, jeśli w grę nie wchodzi żadna przestrzeń nazw (patrz rozdział 9., podrozdział „Wiązanie XML Schema z dokumentem XML”). Określanie lokalizacji dokumentu XML Schema posiadającego wypełnioną przestrzeń nazw jest bardzo podobne (rysunek 13.2). Rysunek 13.2. Pierwszy z zaznaczonych pogrubieniem wierszy deklaruje przestrzeń nazw dla danego dokumentu XML. Drugi deklaruje przestrzeń nazw dla pozycji poprzedzonych prefiksem xsi:. Trzeci pogrubiony wiersz wskazuje przestrzeń nazw, a następnie faktyczny plik, którym ta przestrzeń nazw została wypełniona
Aby wskazać lokalizację dokumentu XML Schema oraz przestrzeni nazw, którą wypełnia: 1. W elemencie głównym, po deklaracji wypełnionej przez XML Schema przestrzeni nazw, wpisz xmlns:xsi="http://www.w3.org/2001/ XMLSchema-instance". Ta deklaracja pozwoli Ci
zdefiniować lokalizację Twojego XML Schema w trzech kolejnych krokach.
Dlaczego to jeszcze nie jest poprawne? Chociaż dwa przedstawione dotąd przykłady są zgodne z wytycznymi opisanymi w procedurach, ten dokument XML nie jest jeszcze poprawny. Dzieje się tak dlatego, że definicja typu złożonego typCud (oraz innych typów) jest częścią danej przestrzeni nazw wypełnionej przez XML Schema, ale odwołania do tego typu złożonego (jak widać na rysunku 13.1) nie używają samej przestrzeni nazw. Odwoływanie się do typu złożonego przy wykorzystaniu przestrzeni nazw zostało omówione w podrozdziale „Odwoływanie się do komponentów XML Schema w przestrzeniach nazw”.
3. Następnie zastosuj spację (lub znak powrotu karetki, jeśli wolisz), aby oddzielić nazwę przestrzeni nazw i lokalizację XML Schema. 4. Wpisz schemat.uri">, gdzie schemat.uri jest lokalizacją Twojego dokumentu XML Schema. (Zwróć uwagę, że w tym kroku nie ma otwierającego cudzysłowu podwójnego).
Wskazówki Jeśli potrzebujesz kilku przestrzeni nazw i kilku dokumentów XML Schema, możesz powtórzyć kroki 2. – 4. tyle razy, ile jest to wymagane. Tak na marginesie, w punkcie 1. powyższej procedury definiujesz kolejną przestrzeń nazw dla swojego dokumentu XML. Posiada ona prefiks xsi: i definiuje atrybut ustawiany w punktach 2. – 4.
189
Dokumenty XML Schema, dokumenty XML
2. Dalej wpisz xsi:schemaLocation="URI, gdzie URI jest nazwą przestrzeni nazw wypełnionej przez Twój dokument XML Schema. (Zwróć uwagę, że w tym kroku nie wpisujesz podwójnego cudzysłowu zamykającego).
Rozdział 13.
Odwoływanie się do komponentów XML Schema w przestrzeniach nazw W XML Schema komponentami są nazwane typy proste lub złożone, elementy, atrybuty, nazwane grupy modelowe lub nazwane grupy atrybutów. Po powiązaniu komponentów XML Schema z przestrzenią nazw (patrz podrozdział „Wypełnianie przestrzeni nazw XML”) możesz odwoływać się do nich w ramach tego (lub dowolnego innego) dokumentu XML Schema. Ponieważ jednak są one teraz powiązane z przestrzenią nazw, musisz określić tę przestrzeń nazw, kiedy odwołujesz się do tych komponentów.
Aby zadeklarować domyślną przestrzeń nazw dla komponentów XML Schema:
Odwoływanie się do komponentów XML Schema
W elemencie głównym swojego dokumentu XML Schema wpisz xmlns="URI", gdzie URI jest przestrzenią nazw, z którą powiązane są wskazywane komponenty (rysunek 13.3).
Aby zadeklarować dla komponentów XML Schema przestrzeń nazw z prefiksem: W elemencie głównym swojego dokumentu XML Schema wpisz xmlns:prefiks="URI", gdzie prefiks określa sposób identyfikowania w tym XML Schema komponentów, które należą do przestrzeni Rysunek 13.3. W elemencie głównym tego XML nazw wskazanej za pomocą URI.
Aby następnie odwołać się do tych komponentów w XML Schema: Jeśli zadeklarowałeś prefiks dla swojej przestrzeni nazw, wpisz prefiks:nazwa_komponentu, gdzie nazwa_komponentu jest poprzedzona przez zdefiniowany prefiks przestrzeni nazw. Jeśli zadeklarowałeś domyślną przestrzeń nazw, po prostu wpisz jak zazwyczaj nazwę komponentu (patrz rysunek 13.3).
Wskazówka Deklaracja przestrzeni nazw pozwala Ci identyfikować w Twoim dokumencie komponenty, które są częścią tej przestrzeni nazw. Docelowa przestrzeń nazw pozwala wypełniać tę przestrzeń nazw komponentami.
190
Schema zadeklarowałem domyślną przestrzeń nazw jako http://www.kehogo.com/ns/css/1.0. Oznacza to, że definicje niepoprzedzonych prefiksem typów globalnych (w tym fragmencie kodu jedynym takim typem jest typCud) można znaleźć w dokumencie XML odpowiadającym domyślnej przestrzeni nazw. (Definicje typów poprzedzonych prefiksem, czyli xs:complexType, xs:string itp., można znaleźć w dokumencie XML Schema odpowiadającym przestrzeni nazw http://www.w3.org/2001/XMLSchema)
Używanie przestrzeni nazw XML
Przestrzenie nazw i walidacja dokumentów XML Wypełniłeś już przestrzeń nazw XML i powiązałeś ją z dokumentem XML. W XML Schema wypełniającym tę przestrzeń nazw zadeklarowałeś ją jako domyślną przestrzeń nazw. Jesteś teraz gotowy do przeprowadzenia walidacji dokumentu XML względem dokumentu XML Schema, przy założeniu, że obydwa dokumenty odwołują się do tej samej przestrzeni nazw.
Rysunek 13.4. W definicji XML Schema przedstawionej na rysunku 13.3 element cuda_starozytnosci jest powiązany z przestrzenią nazw http://www.kehogo.com/ns/css/1.0. Aby więc ten dokument XML był poprawny, musiałem odpowiednio zakwalifikować element cuda_starozytnosci. Ponieważ element cud i pozostałe elementy nie były powiązane z docelową przestrzenią nazw (nie były one w schemacie elementami globalnymi), nie muszą być kwalifikowane
Przeprowadzając walidację dokumentów XML w rozdziałach 10. i 11., nie musiałeś przejmować się przestrzeniami nazw, ponieważ żaden z elementów nie był kwalifikowany (powiązany z docelową przestrzenią nazw). Teraz, skoro niektóre bądź wszystkie Twoje elementy należą do jakiejś przestrzeni nazw, przeprowadzając walidację dokumentów XML, będziesz musiał dla tych elementów określić daną przestrzeń nazw.
Aby napisać dokument XML z elementami kwalifikowanymi:
2. Poprzedź te elementy prefiksem przestrzeni nazw z punktu 1. (patrz rysunek 13.4). Więcej szczegółowych informacji na ten temat znajdziesz w rozdziale 12., „Przestrzenie nazw XML”.
Wskazówki
Wszystko jest w porządku Nasz dokument XML jest wreszcie poprawny, podobnie jak dokument XML Schema przedstawiony w podrozdziale „Odwoływanie się do komponentów XML Schema w przestrzeniach nazw”. Obydwa te dokumenty są teraz częścią tej samej przestrzeni nazw.
Możesz również w swoim dokumencie XML wskazać przestrzeń nazw wymaganych elementów za pomocą domyślnej przestrzeni nazw (xmlns="URI") i nie używać dla tych elementów prefiksu. Nie jest to jednak zbyt popularne rozwiązanie. Przestrzenie nazw są domyślnie wypełniane tylko elementami globalnymi. W konsekwencji może to spowodować, że większość dokumentów XML Schema będzie zawierała mieszaninę elementów kwalifikowanych i niekwalifikowanych. Pamiętaj, żeby kwalifikować tylko te elementy, które są rzeczywiście powiązane z odpowiadającą im przestrzenią nazw.
191
Przestrzenie nazw i walidacja dokumentów XML
1. Musisz wskazać przestrzeń nazw wymaganych elementów, deklarując ją za pomocą prefiksu. W obrębie elementu głównego wpisz xmlns:prefiks="URI", gdzie prefiks będzie identyfikował te elementy w dokumencie XML, które należą do przestrzeni nazw wskazanej przez URI (rysunek 13.4).
Rozdział 13.
Dodawanie wszystkich elementów zdefiniowanych lokalnie Przy wypełnianiu przestrzeni nazw za pomocą XML Schema tylko globalnie zdefiniowane (na najwyższym poziomie) komponenty są domyślnie wiązane z docelową przestrzenią nazw. Jako takie, tylko globalne komponenty w poprawnym dokumencie XML muszą być kwalifikowane (ang. qualified) lub identyfikowane nazwą przestrzeni nazw. Możesz również wymagać, aby lokalnie zdefiniowane komponenty (np. takie, które znajdują się jeden poziom lub kilka poziomów niżej w stosunku do elementu głównego) były dodane do docelowej przestrzeni nazw. W takim przypadku te elementy muszą być kwalifikowane, aby dany dokument XML mógł być uznany za poprawny.
Rysunek 13.5. Ponieważ atrybut elementFormDefault jest ustawiony jako qualified (kwalifikowany), elementy zadeklarowane lokalnie będą powiązane z docelową przestrzenią nazw. Jako takie, muszą być zapisane z użyciem kwalifikowanej nazwy, aby dokument XML mógł być uznany za poprawny
Jeśli chcesz dodać lokalnie zdefiniowane komponenty, możesz dodać deklaracje wszystkich tych elementów i (lub) atrybutów za jednym razem, tak jak zostało to opisane w dalszej części tego podrozdziału. Możesz również dodawać elementy i (lub) atrybuty indywidualnie, co zostało opisane w podrozdziale „Dodawanie poszczególnych elementów zdefiniowanych lokalnie”.
Dodawanie wszystkich elementów
Aby dodać wszystkie lokalnie zdefiniowane elementy do docelowej przestrzeni nazw: W elemencie xs:schema wpisz elementFormDefault="qualified" (rysunek 13.5).
Aby dodać wszystkie lokalnie zdefiniowane atrybuty do docelowej przestrzeni nazw: W elemencie xs:schema wpisz attributeFormDefault="qualified".
Wskazówki Domyślna wartość dla każdego z tych atrybutów to unqualified (niekwalifikowany), co oznacza, że tylko globalnie zdefiniowane (na najwyższym poziomie) komponenty są powiązane z docelową przestrzenią nazw, chyba że zdefiniujesz inaczej. Za najlepszą praktykę uznaje się dodawanie wszystkich lokalnie zdefiniowanych elementów przy wypełnianiu przestrzeni nazw, mimo że nadpisuje to ustawienia domyślne (rysunek 13.6).
192
Rysunek 13.6. W tym poprawnym dokumencie XML wszystkie elementy zdefiniowane lokalnie w XML Schema są teraz kwalifikowane za pomocą prefiksu css:
Używanie przestrzeni nazw XML
Dodawanie poszczególnych elementów zdefiniowanych lokalnie Atrybut form (forma) jest użyteczny przy określaniu, czy konkretny element zdefiniowany lokalnie powinien być powiązany z docelową przestrzenią nazw, bez względu na ustawienia domyślne (patrz podrozdział „Dodawanie wszystkich elementów zdefiniowanych lokalnie”).
Aby dodać konkretny lokalnie zdefiniowany element do docelowej przestrzeni nazw: W definicji elementu wpisz form="qualified". Bez względu na to, gdzie ten element jest zdefiniowany, zostanie powiązany z docelową przestrzenią nazw. Z kolei jeśli zdecydujesz się ustawić w elemencie xs:schema wartość qualified (kwalifikowany) dla atrybutu elementFormDefault (domyślna forma elementu), możesz wykorzystać atrybut form, aby zapobiec powiązaniu konkretnego lokalnie zdefiniowanego elementu z docelową przestrzenią nazw (rysunek 13.7).
Rysunek 13.7. Pomimo ustawienia atrybutu elementFormDefault w elemencie xs:schema, element obrazek_glowny nie zostanie powiązany z docelową przestrzenią nazw, ponieważ jego atrybut form nadpisuje wartość atrybutu elementFormDefault
W definicji elementu wpisz form="unqualified". Bez względu na to, gdzie ten element jest zdefiniowany, nie zostanie powiązany z docelową przestrzenią nazw.
Wskazówka Podobnie jak elementy, atrybuty XML Schema mogą wykorzystywać ten sam atrybut form w celu określenia, czy powinny być (lub nie) powiązane z docelową przestrzenią nazw, bez względu na ustawienia domyślne.
193
Dodawanie poszczególnych elementów
Aby zapobiec (mimo ustawień domyślnych) powiązaniu z docelową przestrzenią nazw konkretnego elementu zdefiniowanego lokalnie:
Rozdział 13.
Definicje XML Schema w kilku plikach Komponenty XML Schema możesz podzielić na kilka indywidualnych plików, aby użyć ich w kilku różnych dokumentach XML Schema lub po prostu ułatwić obsługę obszernych dokumentów XML Schema.
Aby załączyć komponenty XML Schema: 1. Rozdziel komponenty XML Schema na kilka różnych plików. Każdy z nich powinien być plikiem wyłącznie tekstowym i powinien być zapisany z rozszerzeniem .xsd (rysunek 13.8). 2. Odwołaj się do dokumentu XML Schema, w którym chcesz załączyć te komponenty. Bezpośrednio po elemencie xs:schema wpisz , gdzie załącz_plik.uri jest adresem URI dokumentu XML Schema zawierającego komponenty, które chcesz załączyć (rysunek 13.9).
Rysunek 13.8. Najpierw utworzyłem pokazany w tym przykładzie nowy dokument XML Schema zawierający definicję typu złożonego o nazwie typCyw. Teraz mogę użyć tej definicji w innych dokumentach XML Schema
Definicje XML Schema w kilku plikach
Wskazówki Atrybut targetNamespace (docelowa przestrzeń nazw) załączanego dokumentu XML Schema musi być taki sam jak atrybut targetNamespace dokumentu XML Schema, który pobiera dane komponenty. Aby dodać komponenty XML Schema należące do różnych docelowych przestrzeni nazw, zapoznaj się z podrozdziałem „Dokumenty XML Schema z kilkoma przestrzeniami nazw”. Jeśli załączona definicja XML Schema nie ma określonej docelowej przestrzeni nazw, przyjmuje się, że jej docelowa przestrzeń nazw jest tożsama z docelową przestrzenią nazw dokumentu XML Schema, w którym wspomniana definicja jest załączona. Rysunek 13.9. W tym przykładzie załączam typ złożony o nazwie typCyw i odwołuję się do niego. Typ ten został zdefiniowany w XML Schema z rysunku 13.8
194
Używanie przestrzeni nazw XML
Dokumenty XML Schema z kilkoma przestrzeniami nazw Jeśli chcesz używać komponentów XML Schema pochodzących z innych dokumentów XML Schema z różnymi docelowymi przestrzeniami nazw, możesz wykorzystać element xs:import. Umożliwia to walidację dokumentów XML, których elementy są powiązane z więcej niż jedną przestrzenią nazw.
Aby zaimportować elementy z dokumentów XML z różnymi docelowymi przestrzeniami nazw: 1. Wpisz
Rysunek 13.10. Importowanie jednej definicji XML Schema do drugiej sprawia, że komponenty z tej pierwszej są dostępne dla definiowania komponentów w drugiej
2. Następnie wpisz namespace="URI", gdzie URI wskazuje nazwę przestrzeni nazw komponentów XML Schema, które mają być zaimportowane. 3. Dalej wpisz schemaLocation="schemat.uri", gdzie schemat.uri określa lokalizację pliku zawierającego XML Schema definiujące przestrzeń nazw z punktu 2. 4. Wpisz />, aby zakończyć element xs:import (rysunek 13.10).
Wskazówka Elementu xs:import będziesz używał, kiedy potrzebne Ci będą definicje XML Schema z różnych przestrzeni nazw XML, ponieważ pojedynczy plik XML Schema nie może zawierać komponentów z więcej niż jednej przestrzeni nazw. Elementu xs:include (patrz podrozdział „Definicje XML Schema w kilku plikach”) możesz użyć, aby podzielić obszerny plik XML Schema na kilka różnych plików modułowych, a następnie załączyć wybrane pliki do konkretnego XML Schema.
195
Dokumenty XML Schema
5. Dodatkowo będziesz musiał w elemencie xs:schema zadeklarować prefiks dla importowanej przestrzeni nazw (patrz podrozdział „Odwoływanie się do komponentów XML Schema w przestrzeniach nazw”), abyś mógł odwoływać się do importowanych komponentów w swoim XML Schema (patrz rysunek 13.10).
Rozdział 13.
Schemat schematów jako ustawienie domyślne Z rozdziału 9., „Podstawy XML Schema”, dowiedziałeś się, jak rozpocząć podstawowy dokument XML Schema. Pierwszy wiersz XML Schema jest deklaracją XML. Oznacza to, że dokument XML Schema w rzeczywistości jest sam w sobie dokumentem XML. Drugi wiersz dokumentu XML Schema to element xs:schema, który jest elementem głównym. Ponadto, jak już pewnie się zorientowałeś, xs: jest prefiksem przestrzeni nazw XML Schema organizacji W3C. Ta przestrzeń nazw, często nazywana „schematem schematów”, zawiera definicje komponentów, które już poznałeś, np. xs:element, xs:complexType oraz xs:attribute.
Schemat schematów jako ustawienie domyślne
Jednak specyfikacja XML Schema nie wymaga używania prefiksu xs: dla tej przestrzeni nazw. Właściwie mógłbym bez problemu użyć prefiksu zorch:, fondo: lub praktycznie jakiegokolwiek innego. Jeśli więc Twój dokument XML Schema składa się w większej części z typów wbudowanych, prostszym i szybszym rozwiązaniem może być zadeklarowanie schematu schematów jako domyślnej przestrzeni nazw. Wtedy nie będziesz w ogóle używać prefiksu dla elementów z tej przestrzeni nazw (rysunek 13.11).
Aby zadeklarować schemat schematów jako domyślną przestrzeń nazw: 1. Aby rozpocząć definiowanie elementu głównego XML Schema, wpisz
aby zadeklarować schemat schematów jako domyślną przestrzeń nazw. 3. Kontynuuj standardowo, definiując wedle uznania docelowe przestrzenie nazw i przestrzenie nazw XML. 4. Wpisz >, aby zakończyć znacznik schema.
196
Rysunek 13.11. Ten dokument jest równoważny z dokumentem przedstawionym na rysunku 13.3. Jedyną różnicę stanowi sposób zapisu. Ponieważ schemat schematów jest domyślną przestrzenią nazw, nie poprzedzam prefiksem xs: nazw elementów XML Schema (schema, element, complexType itd.) ani typów wbudowanych (string, positiveInteger). Z drugiej strony, dokument XML Schema nie może posiadać dwóch domyślnych przestrzeni nazw. W konsekwencji muszę nadać przestrzeni nazw http://www.kehogo.com/ns/css/1.0 prefiks (css:) i stosować go do komponentów z przestrzeni nazw css:, takich jak css:typCud, css:typNazwa i css:typWysokosc
Używanie przestrzeni nazw XML
Przestrzenie nazw i dokumenty DTD Jednym z największych i konsekwentnie podnoszonych zarzutów wobec dokumentów DTD jest to, że nie obsługują one deklaracji przestrzeni nazw XML. Co ciekawe, w rzeczywistości można jednak używać struktury prefiks:element w nazwach DTD. Problem polega na tym, że parser w żaden sposób nie będzie w stanie rozpoznać, do której przestrzeni nazw XML ten prefiks się odnosi. Faktycznie parser w ogóle nie traktuje znaków umieszczonych przed dwukropkiem jako prefiksu. Możesz utworzyć element css:wysokosc, ale nazwa ta nie będzie oznaczała nic ponad to, co standardowa nazwa dowolnego innego elementu. Nie oznacza ona na przykład, że mamy do czynienia z elementem wysokosc w przestrzeni nazw css:, ale że jest to po prostu element css:wysokosc. Jeśli uważasz to za uciążliwe, nie jesteś jedyny. Brak bezpośredniej obsługi przestrzeni nazw XML jest jednym z głównych powodów wypierania DTD przez XML Schema. Więcej informacji na temat DTD znajdziesz w części III tej książki.
Przestrzenie nazw i dokumenty DTD 197
Rozdział 13.
XSLT i przestrzenie nazw Z rozdziału 2., „XSLT”, dowiedziałeś się, jak rozpocząć podstawowy arkusz stylów XSLT. Podobnie jak w przypadku dokumentów XML Schema, pierwszym wierszem arkusza stylów XSLT jest deklaracja XML. Z tego powodu arkusz stylów XSLT jest sam w sobie dokumentem XML. W konsekwencji, jeśli pracujesz z elementami XML należącymi do jakiejś przestrzeni nazw, będziesz musiał w swoim arkuszu stylów XSLT zadeklarować tę przestrzeń nazw i poprzedzić prefiksem każdy z tych elementów (rysunek 13.12).
Aby użyć przestrzeni nazw XML w arkuszu stylów XSLT: 1. W obrębie znacznika otwierającego elementu głównego xsl:stylesheet wpisz xmlns:prefiks, gdzie prefiks będzie identyfikował przestrzeń nazw XML w tym arkuszu stylów XSLT.
XSLT i przestrzenie nazw
2. Następnie wpisz ="URI", gdzie URI identyfikuje nazwę przestrzeni nazw, do której odwołuje się prefiks z punktu 1. 3. Wreszcie oznacz według potrzeb poszczególne elementy, wpisując , gdzie prefiks jest zdefiniowanym w punkcie 1. prefiksem przestrzeni nazw i wskazuje przestrzeń nazw, do której dany element należy.
Wskazówka W przeciwieństwie do dokumentów XML Schema, w arkuszu stylów XSLT domyślna przestrzeń nazw nie jest stosowana do nazw niepoprzedzonych prefiksem. Innymi słowy, nie możesz usunąć prefiksu xsl: z elementów arkusza stylów XSLT poprzez ustawienie przestrzeni nazw XSLT organizacji W3C jako domyślnej przestrzeni nazw.
198
Rysunek 13.12. Ten fragment arkusza stylów XSLT przedstawia deklarację przestrzeni nazw http://www.kehogo.com/ns/css/1.0 oraz jej prefiksu (css:). Element cuda_starozytnosci jest jedynym kwalifikowanym elementem z tej przestrzeni nazw i w tym arkuszu stylów XSLT został zapisany jako css:cuda_starozytnosci
Najnowsze rekomendacje W3C
VI
Część VI Najnowsze rekomendacje W3C
Rozdział 14. XSLT 2.0
201
Rozdział 15. XPath 2.0
211
Rozdział 16. XQuery 1.0
225
199
Rozdział x.
200
XSLT 2.0
14
Rozdział 14. XSLT 2.0[RS1] XSL (ang. eXtensible Stylesheet Language, czyli rozszerzalny język arkuszy stylów) jest używany do przekształcania dokumentów XML w inne dokumenty, takie jak HTML (patrz część II). Jest to rodzina trzech języków: XPath, służącego do wybierania węzłów z dokumentów źródłowych, XSLT, służącego do przekształcania tych wybranych węzłów, oraz XSL-FO, który jest językiem najczęściej wykorzystywanym do generowania plików PDF. 23 stycznia 2007 r. organizacja W3C opublikowała osiem nowych rekomendacji dotyczących XML-a. Rekomendacje te zdefiniowały nowe wersje XSLT oraz XPath, a także nowy język XML o nazwie XQuery.
W kwestii wybierania zawartości z informacji źródłowych zarówno XSLT, jak i XQuery opierają się na języku XPath. Ten proces selekcji wykorzystuje logiczną strukturę dokumentu XML, określaną jako model danych (ang. data model). Ten model danych XML (XDM) jest dokładnie taki sam dla wszystkich trzech języków: XQuery 1.0, XPath 2.0 oraz XSLT 2.0. Jest to w istocie element, który łączy je wszystkie. Więcej informacji na temat tych języków znajdziesz na stronie http://www.w3.org/2007/01/qt-pressrelease.
201
XSLT 2.0
Podobnie jak XSLT, XQuery daje użytkownikom możliwość kwerendowania danych XML na podstawie logicznej struktury dokumentu XML. W rzeczywistości z XQuery 1.0 możesz robić większość tych samych rzeczy, na które pozwala XSLT 2.0. XQuery różni się jednak tym od XSLT 2.0, że daje również możliwość bezpośredniego kwerendowania baz danych w opozycji do możliwości kwerendowania jedynie dokumentów tekstowych.
Rozdział 14.
Rozszerzanie XSLT XSLT jest językiem XML, którego celem jest przekształcanie danego dokumentu źródłowego XML w inny dokument, np. dokument HTML lub nowy dokument XML. XSLT 1.0 stało się oficjalną rekomendacją W3C w roku 1999 i natychmiast zostało przyjęte przez społeczność XML. Za tym przyszedł określony odzew, pojawiła się krytyka i ostatecznie doszło do utworzenia nowej grupy roboczej W3C, której celem było sprawdzenie i poprawienie XSLT. Do podstawowych założeń podjętych działań można zaliczyć: poprawę łatwości zastosowania,
Rozszerzanie XSLT
wsparcie dla różnych dokumentów wynikowych, umożliwienie tworzenia funkcji definiowanych przez użytkownika, wsparcie dla wykorzystania XML Schema, uproszczenie grupowania zawartości, zachowanie wstecznej kompatybilności. Ostatni z wymienionych celów, czyli zachowanie wstecznej kompatybilności, był istotny ze względu na ułatwienie użytkownikom przyjęcia tej nowej rekomendacji. Dzięki zachowaniu zgodności z poprzednimi wersjami możliwe jest wykorzystanie procesora XML 2.0 z istniejącymi arkuszami stylów XSLT 1.0, przy niewielkiej lub zerowej modyfikacji. Wtedy można dla wygody zacząć korzystać z cech i funkcji XSLT 2.0 (rysunek 14.1). Chociaż rekomendacja XSLT 2.0 nie uległa zasadniczej zmianie od czasu opublikowania w roku 2003 projektu roboczego, wersja 1.0 jest nadal szeroko wykorzystywana i obsługiwana. W rzeczywistości żadna z głównych przeglądarek nie obsługuje jeszcze wersji 2.0. Z tego względu w celu podejrzenia przykładów XSLT zamieszczonych w tym rozdziale będziesz musiał skorzystać z procesora obsługującego wersję 2.0. Jeśli do tej pory z takiego nie korzystałeś, wskazówki znajdziesz w dodatku A.
202
Rysunek 14.1. Ten arkusz stylów XSLT będzie przetwarzany z zastosowaniem specyfikacji XSLT 2.0, ponieważ atrybut version elementu xsl:stylesheet ma wartość "2.0". Uwaga! Jest to skrócona wersja dokumentu głównego XSLT 1.0, używanego we wcześniejszych rozdziałach tej książki. Zwróć uwagę, że w tym arkuszu stylów nic, oprócz atrybutu version, nie zostało zmienione
XSLT 2.0
Tworzenie uproszczonego arkusza stylów Jednym z celów XSLT 2.0 było poprawienie łatwości jego zastosowania w porównaniu z XSLT 1.0. Przykład tego ułatwienia można dostrzec w arkuszach stylów, które posiadają jedynie regułę szablonu dla węzła głównego () i nie mają żadnych innych reguł szablonów, tak jak na rysunku 14.1. W takich przypadkach możesz uprościć swój arkusz stylów XSLT, łącząc w znaczniku otwierającym elementy xsl:stylesheet i xsl:template oraz usuwając całkowicie elementy xsl:stylesheet, xsl:output i xsl:template.
Aby utworzyć uproszczony arkusz stylów:
Rysunek 14.2. Oto uproszczony arkusz stylów oparty na arkuszu stylów przedstawionym na rysunku 14.1
2. Wpisz
nazw XSLT i jej prefiksu. 4. Dalej wpisz xsl:version="2.0">, aby wskazać, że ten dokument będzie korzystał z wersji 2.0 przestrzeni nazw XSLT. 5. Wprowadź instrukcje dla swojego arkusza stylów. 6. Wpisz znacznik zamykający , aby zakończyć element html z punktu 2., a tym samym zakończyć uproszczony arkusz stylów (rysunek 14.2).
Wskazówki Atrybut version (wersja) w otwierającym znaczniku html różni się od standardowego atrybutu version. W uproszczonym arkuszu stylów atrybut ten musi posiadać prefiks xsl:, który wskazuje, że należy on do przestrzeni nazw XSLT. W uproszczonym arkuszu stylów nie mogą znajdować się elementy xsl:apply-template.
203
Tworzenie uproszczonego
1. Wpisz , aby wskazać, że ten arkusz stylów XSLT jest dokumentem XML.
Rozdział 14.
Generowanie dokumentów wynikowych XHTML XHTML jest bardziej ustrukturyzowaną formą HTML-a, będącą zasadniczo mariażem HTML-a i XML-a. Format XHTML otrzymał rekomendację W3C w styczniu 2000 r. i został szeroko zaadaptowany do tworzenia stron WWW.
Generowanie dokumentów wynikowych XHTML
W XSLT 1.0 nie ma bezpośredniego wsparcia dla generowania dokumentów wynikowych zgodnych z XHTML-em. Funkcja ta została dodana w XSLT 2.0.
Rysunek 14.3. W tym przykładzie zastosowałem instrukcję xsl:output, aby wskazać procesorowi XSLT, że wygenerowany plik wynikowy ma być zgodny z formatem XHTML
Aby wygenerować plik wynikowy zgodny z XHTML-em: 1. W obrębie deklaracji xsl:stylesheet wpisz xmlns="http://www.w3.org/1999/xhtml", aby zadeklarować przestrzeń nazw XHTML. 2. Bezpośrednio po deklaracji xsl:stylesheet wpisz , aby ustawić metodę wynikową jako XHTML i zamknąć instrukcję wynikową (rysunek 14.3).
Inny sposób generowania dokumentów wynikowych zgodnych z XHTML-em: 1. W obrębie xsl:stylesheet wpisz xmlns="http://www.w3.org/1999/xhtml",
aby zadeklarować przestrzeń nazw XHTML. 2. Bezpośrednio po szablonie dla węzła głównego () wpisz , aby ustawić metodę wynikową jako XHTML. 4. Wreszcie bezpośrednio przed zamykającym znacznikiem szablonu węzła głównego wpisz , aby zamknąć instrukcję wynikową (rysunek 14.4).
Wskazówka Dla obu tych instrukcji wynikowych istnieją też inne atrybuty, w tym atrybuty kontrolujące kodowanie znaków, akapity itd.
204
Rysunek 14.4. W tym przykładzie zastosowałem instrukcję xsl:result-document, aby wskazać procesorowi XSLT, że wygenerowany plik wynikowy ma być zgodny z formatem XHTML. Zwróć uwagę, że instrukcja xsl:result-document zamyka plik wynikowy i instrukcje w obrębie szablonu głównego
XSLT 2.0
Generowanie wielu dokumentów wynikowych W XSLT 1.0 podczas przetwarzania arkusza stylów XSLT generowany jest tylko jeden dokument wynikowy. Jeśli chcesz utworzyć kilka dokumentów ze swojej zawartości XML, musisz uruchomić procesor XSLT dla każdego z tych dokumentów osobno.
Aby wygenerować kilka dokumentów wynikowych: 1. Dla każdego dokumentu wynikowego określ instrukcje XSLT, które będą generować pożądany plik. 2. Przed pierwszą instrukcją z punku 1. wpisz , gdzie wynik.uri określa lokalizację dokumentu, w której zapisany będzie plik wynikowy dla danych instrukcji XSLT. 4. Wreszcie po ostatniej instrukcji XSLT z punktu 1. wpisz , aby zakończyć instrukcję wynikową (rysunek 14.5).
Wskazówki Rysunek 14.6. W dalszej części dokumentu XSLT przedstawionego na rysunku 14.5 dopasowałem znaczniki kotwicy, które odsyłają do sekcji historii dla każdego cudu. Każdy znacznik kotwicy stanowi teraz hiperłącze do odpowiedniego miejsca w nowym dokumencie historia.html
W swoim arkuszu stylów XSLT możesz użyć tylu instrukcji xsl:result-document, ilu chcesz. Możesz zdecydować o tym, by Twój plik wynikowy był zgodny z formatem XHTML, wykorzystując atrybut method w sposób opisany w podrozdziale „Generowanie dokumentów wynikowych XHTML”. Plik wynikowy transformacji XSLT zwany jest finalnym drzewem wynikowym (ang. final result tree). Dla wszelkich instrukcji XSLT niezawartych w elemencie result-document finalne drzewo wynikowe jest tworzone automatycznie.
205
Generowanie wielu dokumentów wynikowych
Rysunek 14.5. Ten fragment arkusza stylów XSLT wygeneruje dla sekcji Historia dokument wynikowy o nazwie historia.html. Drugi dokument wynikowy jest tworzony automatycznie i zawiera wszystkie pozostałe dane wynikowe XSLT, w tym listę wszystkich cudów, z których każdy odsyła do odpowiedniego fragmentu w nowym dokumencie wynikowym dotyczącym historii (patrz rysunek 14.6)
Jednak w przypadku XSLT 2.0 możesz wygenerować kilka dokumentów wynikowych przy jednorazowym uruchomieniu procesora. Ponadto instrukcje tworzenia każdego z dokumentów wynikowych możesz również zawrzeć w pojedynczym dokumencie XSLT.
Rozdział 14.
Tworzenie funkcji definiowanych przez użytkownika W XSLT 2.0 funkcje definiowane przez użytkownika (ang. User Defined Functions — UDF) działają jak funkcje w innych językach programowania. Deklarujesz nazwę UDF, parametry wejściowe, czynności, które mają być wykonane z danymi wejściowymi, oraz parametry wyjściowe.
Tworzenie funkcji definiowanych
Aby utworzyć funkcję definiowaną przez użytkownika: 1. Rozpocznij swoją funkcję UDF, wpisując , gdzie nazwa_UDF jest nazwą Twojej funkcji. 3. Opcjonalnie (aby rozpocząć identyfikowanie dowolnych parametrów wejścia UDF) wpisz , gdzie nazwa_parametru jest nazwą, którą będziesz wykorzystywał, odwołując się do tego parametru w ramach swojej funkcji UDF. 4. Powtórz krok 3. dla tylu parametrów wejściowych, ile chcesz zadeklarować. Możesz również zdecydować, że nie będzie żadnych parametrów wejściowych, i całkowicie pominąć krok 3.
Rysunek 14.7. Arkusz stylów w tym przykładzie deklaruje funkcję UDF o nazwie witajSwiecie, która jest częścią przestrzeni nazw khg:. Zwraca ona bezpośredni ciąg znaków „Witaj, świecie, dnia”, po którym wyświetlana jest data i godzina. Zwróć uwagę na zastosowanie w elemencie głównym atrybutu exclude-result-prefixes, powodującego wyłączenie przestrzeni nazw khg z dokumentu wynikowego
5. Wpisz dla swojej funkcji instrukcje XSLT 2.0 i XPath, które będą generować wartość zwrotną UDF. 6. Wpisz , aby zakończyć tworzenie funkcji UDF (rysunek 14.7).
Aby utworzyć przestrzeń nazw dla funkcji UDF: 1. W obrębie znacznika otwierającego elementu głównego wpisz xmlns:prefiks, gdzie prefiks jest prefiksem przestrzeni nazw dla Twojej funkcji UDF.
Rysunek 14.8. Wyświetlony w przeglądarce efekt wykonania arkusza stylów XSLT 2.0 z rysunku 14.7
2. Następnie wpisz ="URI", gdzie URI jest przestrzenią nazw, do której będzie się odwoływał prefiks.
Wskazówki Twoja funkcja UDF musi być częścią swojej własnej przestrzeni nazw, aby wyeliminować potencjalne konflikty nazw z funkcjami w domyślnej przestrzeni nazw.
206
Opcjonalnie użyj instrukcji exclude-result-prefixes, aby przestrzeń nazw Twojej funkcji UDF nie była częścią dokumentu wynikowego (patrz rysunek 14.7).
XSLT 2.0
Wywoływanie funkcji definiowanych przez użytkownika Oczywiście samo utworzenie funkcji UDF to nie wszystko (rysunek 14.9). Musisz jeszcze wywołać tę funkcję w arkuszu stylów. Aby użyć funkcjonalności oferowanej przez funkcję UDF, należy wywołać ją z dowolnego miejsca, gdzie przewidywane jest wyrażenie XPath.
Aby wywołać funkcję zdefiniowaną przez użytkownika: 1. W dowolnym miejscu, w którym przewidywane jest wyrażenie XPath, wpisz prefiks:, gdzie prefiks odpowiada prefiksowi użytemu w punkcie 1. drugiej z procedur opisanych w podrozdziale „Tworzenie funkcji definiowanych przez użytkownika”. (Jest to prefiks przestrzeni nazw, który zdefiniowałeś dla swojej funkcji UDF). 2. Następnie wpisz nazwa_UDF(, gdzie nazwa_UDF odpowiada nazwie użytej w punkcie 2. pierwszej z procedur opisanych w podrozdziale „Tworzenie funkcji definiowanych przez użytkownika” (i jest nazwą, którą nadałeś swojej funkcji). 3. Dalej wpisz wartość (lub wartości) parametrów wejściowych zdefiniowanych w punkcie 3. pierwszej z procedur opisanych w podrozdziale „Tworzenie funkcji definiowanych przez użytkownika”. Wpisywane wartości należy rozdzielać przecinkiem. Jeśli nie zostały zadeklarowane żadne parametry wejściowe, ten etap jest pomijany. 4. Wreszcie wpisz ), aby zakończyć wywoływanie swojej funkcji UDF (rysunek 14.10).
Wskazówki Rysunek 14.10. Mamy tutaj dwa miejsca, w których wywoływana jest funkcja khg:jedna_trzecia(). Wykorzystuję tę funkcję UDF do podzielenia przez 3 wartości atrybutów szer i wys elementu obrazek_glowny. Powoduje to zmniejszenie rozmiarów wyświetlanego obrazka do jednej trzeciej wartości oryginalnej
Deklaracja xsl:function może pojawiać się w dowolnym miejscu Twojego arkusza stylów XSLT, pod warunkiem że jest ona elementem najwyższego poziomu. Inaczej niż w wielu innych językach programowania proceduralnego, opcjonalne parametry wejściowe nie są dozwolone w funkcjach UDF. Jak w wielu innych językach programowania proceduralnego, funkcje UDF mogą wywoływać same siebie, tworząc w ten sposób funkcje rekurencyjne. W XSLT 1.0 zaawansowani użytkownicy tworzyli funkcjonalności zbliżone do UDF, oszukując procesor tak, aby używał nazwanych szablonów, lub pisząc funkcje w innych językach, poza samym arkuszem stylów.
207
Wywoływanie funkcji definiowanych
Rysunek 14.9. Ta funkcja UDF, o nazwie khg:jedna_trzecia, pobiera pojedynczy parametr wejściowy o nazwie wymiar. Jego wartość jest dzielona przez 3, a następnie za pomocą funkcji ceiling() zaokrąglana w górę do najbliższej liczby całkowitej. Potem funkcja UDF zwraca wartość końcową do instrukcji wywołującej
Rozdział 14.
Grupowanie danych wynikowych na podstawie wspólnych wartości Grupowanie zbioru elementów na podstawie wspólnej zawartości (np. elementów o tej samej nazwie lub wartości atrybutu) jest w XSLT 1.0 niezwykle trudne i dla przeciętnego użytkownika niełatwe do osiągnięcia. Na szczęście w XSLT 2.0 grupowanie jest dużo prostsze i obsługiwane przez zestaw wbudowanych funkcji.
Aby pogrupować na podstawie wspólnej wartości:
Grupowanie danych wynikowych
1. Wpisz
Rysunek 14.11. Aby wygenerować zestawienie elementów zrodlo pogrupowanych według ich atrybutów id_gazety, ustawiłem dla elementu xsl:for-each-group //zrodlo jako wartość atrybutu select oraz @id_gazety jako wartość atrybutu group-by. Komponent current-group() zwraca wszystkie wartości id_sekcji dla każdej grupy. Bez niego plik wynikowy pokazywałby jedynie bieżącą wartość id_sekcji dla id_gazety, a nie wszystkie wartości id_sekcji w danej grupie
4. Określ, jakie przetwarzanie ma być zastosowane. 5. Wpisz , aby zakończyć grupowanie (rysunek 14.11).
Wskazówki Zarówno zbiór_węzłów z punktu 2., jak i klucz_grupowania z punktu 3. muszą być wyrażeniami XPath. Właściwie to muszą być wyrażeniami XPath 2.0, ponieważ element xsl:for-each-group jest elementem XSLT 2.0. Specyfikacja XPath 2.0 została omówiona w rozdziale 15. Kiedy przetwarzana jest instrukcja xsl:for-each-group, możesz użyć funkcji o nazwie current-group() (bieżąca grupa). Jest to zbiór wszystkich tych pozycji z danej populacji, które są przydzielone do przetwarzanej grupy (patrz rysunek 14.11). W obrębie instrukcji xsl:for-each-group możesz również użyć instrukcji xsl:sort, aby posortować zawartość wynikową.
208
Rysunek 14.12. Arkusz stylów XSLT z rysunku 4.11 generuje powyższe zestawienie. Zwróć uwagę, że dla ID gazety o wartościach 21 i 19 mamy podwójne wartości ID sekcji. Bez zastosowania komponentu current-group() plik wynikowy pokazałby jedynie bieżącą wartość ID sekcji dla ID gazety, a nie wszystkie wartości
XSLT 2.0
Walidacja plików wynikowych XSLT Poza przekształcaniem dokumentów XML w pliki (X)HTML do wyświetlania, XSLT jest często wykorzystywane do przekształcania dokumentów XML w inne dokumenty XML. Te nowe dokumenty XML mogą być następnie wykorzystane do innych celów niż dokumenty oryginalne.
Aby przeprowadzić walidację pliku wynikowego XSLT: Rysunek 14.13. Zamiast generowania tabeli HTML dla elementów zrodlo za pomocą XSLT (rysunek 4.11), tutaj wygenerowałem tę informację w postaci dokumentu XML. Walidację danego dokumentu XML przeprowadziłem, zanim powstał plik wynikowy, i wykorzystałem w tym celu zaimportowany schemat 14-13.xsd
1. W dowolnym miejscu na najwyższym poziomie arkusza stylów (poza regułą szablonu głównego) wpisz , gdzie schemat.uri określa lokalizację dokumentu XML Schema, który chcesz wykorzystać do walidacji. 3. Dodatkowo, w arkuszu stylów XSLT, w obrębie elementu głównego pliku wynikowego przeznaczonego do walidacji, wpisz xsl:validation="strict" (rysunek 14.13).
Wskazówki Korzystając z tego samego modelu, możesz przeprowadzać walidację różnych części danych wynikowych XSLT za pomocą różnych importowanych definicji XML Schema.
Rysunek 14.14. Oto fragment pliku wynikowego XML po walidacji, wygenerowanego za pomocą arkusza stylów XSLT przedstawionego na rysunku 14.13
Zamiast określania lokalizacji schematu w elemencie xsl:import-schema, możesz załączyć reguły swojego XML Schema w samym arkuszu stylów XSLT. Zastosowanie takiego wplecionego schematu oznacza, że nie będziesz mógł go łatwo użyć w innym arkuszu stylów XSLT. Zapewnia on jednak szybki dostęp zarówno do arkusza stylów, jak i do schematu w pojedynczym pliku.
209
Walidacja plików wynikowych XSLT
XSLT 1.0 nie może jednak przeprowadzić walidacji własnego pliku wynikowego względem dokumentu XML Schema. W rezultacie ich walidacja musi się odbywać jako osobna czynność, aby zapewnić odpowiednią strukturę dokumentów XML wygenerowanych w procesie transformacji XSLT. Zostało to poprawione w specyfikacji XSLT 2.0 poprzez wprowadzenie możliwości walidacji względem XML Schema pliku wynikowego transformacji XSLT w ramach tej samej transformacji XSLT.
Rozdział 14.
210
XPath 2.0
15
Rozdział 15. XPath 2.0[RS1] XPath (ang. XML Path Language, czyli język ścieżek XML) jest językiem służącym do wybierania i przetwarzania części dokumentu XML. Specyfikacja XPath 2.0 jest częścią ośmiu rekomendacji organizacji W3C opublikowanych zbiorczo w lipcu 2007 r. i zawiera istotne zmiany w stosunku do oryginalnej wersji z roku 1999. Jedna z zasadniczych zmian dotyczy modelu danych wykorzystywanego przez XPath. W wersji 1.0 stosowany model danych jest oparty na zbiorach węzłów (patrz rozdział 3., „Wzorce i wyrażenia XPath”). Z kolei w wersji 2.0 model danych oparty jest na sekwencjach. Sekwencja jest zbiorem pozycji (węzłów i/lub wartości), podczas gdy zbiór węzłów jest jedynie zestawem węzłów. To rozróżnienie, choć subtelne, jest w specyfikacji 2.0 istotnym ulepszeniem, które zostanie w tym rozdziale szczegółowo omówione.
Zgodnie z projektem, aktualizacja do XPath 2.0 powinna być stosunkowo łatwa, ponieważ wszystko, co wiesz o XPath 1.0, ma również zastosowanie do wersji 2.0. Ponadto wiele zmian z wersji 2.0 jest opartych na dobrze znanych konstrukcjach programistycznych, z którymi być może jesteś już zaznajomiony. Podobnie jak XPath 1.0, wersja 2.0 nie jest językiem samodzielnym, ponieważ została zaprojektowana w ramach „języka gospodarza”, takiego jak np. XSLT 2.0. W przykładach zamieszczonych w tym rozdziale do przedstawienia funkcjonalności XPath 2.0 wykorzystany został język XSLT 2.0. Jeśli potrzebujesz, przejrzyj materiały na temat XSLT 1.0 i XPath 1.0 zamieszczone w części II tej książki, a także zapoznaj się z rozdziałem 14., „XSLT 2.0”.
211
XPath 2.0
Poza nowym modelem danych, XPath 2.0 posiada obszerniejszy zestaw funkcji. Obsługuje wyrażenia warunkowe (instrukcje if-then-else) oraz pętle i zmienne (wcześniej dostępne jedynie w XSLT).
Rozdział 15.
XPath 1.0 i XPath 2.0 XPath 2.0 jest rozszerzeniem XPath 1.0. Innymi słowy, wszystko, czego nauczyłeś się o XPath 1.0 (patrz rozdziały 3. i 4.), ma również zastosowanie do XPath 2.0.
Podstawy XPath
XPath 1.0 i XPath 2.0
XPath służy dwóm podstawowym celom. Pierwszym jest znalezienie i zwrócenie określonych części dokumentu XML. W tym celu XPath konwertuje dokument XML na drzewo węzłów XML. Drzewo węzłów XML jest hierarchiczną reprezentacją dokumentu XML. Następnie na podstawie ścieżki lokalizacji, którą definiujesz, XPath wykorzystuje drzewo węzłów XML, aby znaleźć i zwrócić żądane przez Ciebie informacje. Ścieżka lokalizacji jest sposobem opisania pozycji w dokumencie XML żądanej zawartości względem pewnego kontekstu bieżącego (rysunek 15.1). Drugim podstawowym celem XPath jest przeprowadzenie operacji na tych wybranych fragmentach. XPath ma wbudowane funkcje umożliwiające przeprowadzenie podstawowych działań arytmetycznych na danych zwróconych przez ścieżkę lokalizacji lub zmianę formatu tych danych (rysunek 15.3).
Rysunek 15.1. Ta ścieżka lokalizacji żąda węzłów nazwa, dla których atrybut jezyk równa się 'polski'. Węzły te są dziećmi węzłów cud, które są dziećmi węzła cuda_starozytnosci
Rysunek 15.2. Wynik zastosowania ścieżki lokalizacji z rysunku 15.1 w obrębie arkusza stylów pliku HTML
Model danych XPath 2.0 Nowy model danych obsługiwany przez wersję 2.0 języka XPath zwany jest XDM (ang. XQuery/XPath Data Model). Jest to rozszerzenie XML Infoset, czyli modelu danych dla XPath 1.0. Istotną kwestią, o której należy pamiętać podczas korzystania z modelu XDM, jest wprowadzona obsługa dla typów XML Schema (patrz część IV), co czyni z XPath 2.0 język silnie typizowany. Oznacza to, że stosowanie wartości jest ściśle uzależnione od typu każdej wartości. Przykładowo próba wykonania działań matematycznych na ciągu znaków „2008” spowoduje zwrócenie błędu, co nie miałoby miejsca w XPath 1.0 (patrz rysunek 15.25). Obsługa XML Schema umożliwia również połączenie arkuszy stylów XSLT 2.0 (które działają tylko z językiem XPath 2.0) ze schematem dokumentu XML. Wtedy podczas transformacji dokumentu jesteś powiadamiany o błędach w pisowni, niewłaściwych ścieżkach i błędach typów, zgodnie z danym schematem. Jesteś również powiadamiany o wszelkich wymaganych w Twoim dokumencie zmianach wymuszonych przez zmiany w XML Schema.
212
Rysunek 15.3. Zastosowanie dzielenia oraz funkcji format-number do przekonwertowania wysokości na stopy
Rysunek 15.4. Wyświetlanie wysokości każdego z cudów sformatowanej w sposób opisany w arkuszu stylów XSLT z rysunku 15.3
XPath 2.0 Sekwencje XPath 2.0 Rysunek 15.5. W XPath 2.0 wszystko jest przetwarzane jako sekwencja. Sekwencja jest uporządkowaną listą pozycji będących różnymi typami. Aby zdefiniować sekwencję, napisz wymagane wartości ujęte w parę nawiasów i rozdzielone przecinkami (spacja po przecinku nie jest wymagana, ale zwiększa czytelność)
Rysunek 15.6. Sekwencje nie mogą być zagnieżdżane w innych sekwencjach. Oznacza to, że górny fragment w tym przykładzie będzie automatycznie przekonwertowany do postaci dolnego fragmentu kodu. Zwróć również uwagę, że sekwencje pozwalają na duplikowanie pozycji
Aby obsłużyć tę różnicę, wartością zwrotną wyrażeń w XPath 2.0 jest sekwencja (rysunek 15.5). (Ponadto, jak zauważysz w trakcie lektury całego rozdziału, dodatkowa funkcjonalność związana z sekwencjami jest istotna). Sekwencja jest uporządkowaną listą rozdzielonych przecinkami pozycji, gdzie pozycja jest zdefiniowana jako węzeł lub wartość niepodzielna (ang. atomic value). Wartość niepodzielna to zasadniczo każda wartość, a konkretniej jest to typ prosty lub typ niestandardowy wyprowadzony za pomocą restrykcji (patrz rozdziały 10. i 11.). Do innych cech sekwencji należy to, że mogą one posiadać zduplikowane pozycje (zbiory węzłów w XPath 1.0 mieć ich nie mogą). Są one również strukturami płaskimi. Innymi słowy, nie można zawrzeć jednej sekwencji w obrębie innej sekwencji (rysunek 15.6). Podobnie jak zbiory węzłów w XPath 1.0, sekwencje mogą zawierać operatory (rysunek 15.7), mogą być obiektami funkcji (rysunek 15.8) oraz przyjmować predykaty (będące „filtrami” zapisanymi w nawiasach kwadratowych). Sekwencje mogą być także stosowane w pętlach, w sposób zbliżony do elementu xsl:for-each w XSLT (patrz rozdział 2., „XSLT”, podrozdział „Zapętlanie węzłów”).
Wskazówka Ponieważ XPath 2.0 jest rozszerzeniem wersji 1.0, wszystko, czego nauczyłeś się o XPath 1.0 (patrz rozdziały 3. i 4.), ma zastosowanie do wersji 2.0. Możesz nawet używać XPath 2.0 ze swoimi istniejącymi już arkuszami stylów. Nieliczne wyjątki od tej reguły zostały opisane na stronie www.w3.org/TR/xpath20/#id-backwards-compatibility.
Rysunek 15.8. Jak zobaczysz w pozostałej części tego rozdziału, funkcje mogą wykonywać działania na sekwencjach i zwracać sekwencje. W tym przykładzie funkcja reverse odwraca kolejność pozycji z górnej sekwencji, aby wygenerować dolną sekwencję
213
XPath 1.0 i XPath 2.0
Rysunek 15.7. Sekwencje mogą być konstruowane z wykorzystaniem operatora „to” (do), który zwraca liczby całkowite w kolejności od najmniejszej do największej. Pierwszy z fragmentów kodu jest automatycznie konwertowany do postaci drugiego fragmentu kodu
XPath 1.0 nie jest językiem silnie typizowanym. Wyrażenia w XPath 1.0 zwracają tylko jeden z czterech różnych typów: zbiory węzłów, ciągi znaków, liczby oraz wartości logiczne. Z kolei XPath 2.0 jest językiem silnie typizowanym, a jego wyrażenia mogą zwracać znacznie więcej różnych typów.
Rozdział 15.
Uśrednianie wartości w sekwencji W XPath 1.0 dostępne są funkcje umożliwiające liczenie węzłów oraz sumowanie ich wartości w zbiorze węzłów (rysunek 15.9). XPath 2.0 oferuje te same funkcje dla sekwencji, a ponadto zostały jeszcze dodane trzy kolejne podobne funkcje: avg(), min() oraz max(). Jedna z tych nowych funkcji umożliwia uśrednianie wszystkich wartości w sekwencji.
Aby uśrednić wartości w sekwencji: 1. Wpisz avg(. 2. Następnie wpisz sekwencję lub ścieżkę lokalizacji do sekwencji, której pozycje mają zostać uśrednione.
Rysunek 15.9. Ten fragment kodu XPath 1.0 oblicza za pomocą funkcji sum() sumę wysokości wszystkich cudów starożytności, a następnie dzieli tę sumę przez liczbę (funkcja count()) tych cudów, których wysokość jest różna od zera (pamiętaj, że w naszym dokumencie XML wysokość wiszących ogrodów Semiramidy wynosi 0)
3. Wpisz ), aby zakończyć funkcję (rysunek 15.10).
Uśrednianie wartości w sekwencji
Wskazówka Wynik tej funkcji, jak również wynik pozostałych dwóch funkcji omówionych w podrozdziale „Wyznaczanie wartości minimalnej lub maksymalnej”, mógłby być wygenerowany w XPath 1.0. Jednak — szczególnie w przypadku funkcji min() i max() — trzeba by nieco więcej niż tylko jednej linii kodu XSLT i XPath.
Rysunek 15.10. Tutaj zastosowałem funkcję avg() języka XPath 2.0, aby zrobić to samo, co zostało przedstawione na rysunku 15.9. Ten sam wynik osiągamy za pomocą mniejszej liczby wierszy kodu
Rysunek 15.11. Wyświetlony w przeglądarce Internet Explorer 8 plik wynikowy z kodu XSLT 2.0/XPath 2.0 z rysunku 15.10. (Kod XSLT 1.0/XPath 1.0 z rysunku 15.9 generuje dokładnie taki sam plik HTML)
214
XPath 2.0
Wyznaczanie wartości minimalnej lub maksymalnej Poza uśrednianiem wartości w sekwencji, XPath 2.0 oferuje również funkcje umożliwiające wyznaczanie wartości minimalnych i maksymalnych w sekwencji (rysunek 15.12). Rysunek 15.12. Wykorzystując obydwie funkcje, min() i max(), dodałem do finalnego pliku wynikowego informację o zakresie wysokości cudów starożytnego świata. Choć można to było uzyskać również za pomocą XPath 1.0, to funkcje min() i max() wymagają znacznie mniejszej ilości kodu dla zwrócenia odpowiedniego wyniku
Aby zwrócić wartość minimalną liczb z sekwencji: 1. Wpisz min(. 2. Następnie wpisz sekwencję lub ścieżkę lokalizacji do sekwencji, której najmniejsza wartość ma być zwrócona. 3. Wpisz ), aby zakończyć funkcję.
Aby zwrócić wartość maksymalną liczb z sekwencji: 2. Następnie wpisz sekwencję lub ścieżkę lokalizacji do sekwencji, której największa wartość ma być zwrócona. 3. Wpisz ), aby zakończyć funkcję. Rysunek 15.13. Plik wynikowy HTML wygenerowany z wykorzystaniem nowych instrukcji przedstawionych na rysunku 15.12
Wskazówki Funkcje te zwane są „funkcjami agregującymi”, ponieważ zwracają pojedynczą wartość na podstawie wartości z sekwencji. Są to funkcje avg(), min(), max(), sum() oraz count(). Dwie ostatnie dostępne są w XPath 1.0. W przypadku wszystkich funkcji agregujących, z wyjątkiem funkcji count(), sekwencja musi składać się z wartości o podobnym typie. Wszystkie te wartości muszą być liczbami lub typem pojedynczym (takim jak typy daty).
215
Wyznaczanie wartości
1. Wpisz max(.
Rozdział 15.
Formatowanie ciągów znaków W XPath 2.0 dostępnych jest kilka nowych funkcji dla formatowania ciągów znaków. Dwie z tych funkcji umożliwiają zmianę wielkości znaków w ciągu na wielkie lub małe. Chociaż w XPath 1.0 również możesz konwertować wielkość znaków (rysunek 15.14), to w XPath 2.0 jest to znacznie łatwiejsze (rysunek 15.15).
Aby przekonwertować ciąg znaków na wielkie litery: 1. Wpisz upper-case(.
Rysunek 15.14. Ten fragment kodu XPath 1.0 wykorzystuje funkcję translate do przekonwertowania polskiej nazwy każdego z cudów na zapis wielkimi literami
2. Następnie wpisz wyrażenie, które zawiera ciąg znaków przeznaczony do przekonwertowania na wielkie litery.
Formatowanie ciągów znaków
3. Wpisz ), aby zakończyć funkcję.
Aby przekonwertować ciąg znaków na małe litery: 1. Wpisz lower-case(. 2. Następnie wpisz wyrażenie, które zawiera ciąg znaków przeznaczony do przekonwertowania na małe litery.
Rysunek 15.15. Tutaj wykorzystałem funkcję uppercase() języka XPath 2.0, aby uzyskać ten sam efekt, który daje kod z rysunku 15.14. Nie tylko zmniejsza to liczbę wierszy kodu w tym przykładzie, ale także kod jest bardziej czytelny i łatwiejszy do zrozumienia
3. Wpisz ), aby zakończyć funkcję.
Wskazówki Konwersja wielkości znaków nie wpływa na liczby ani na interpunkcję. Wykorzystywana w XPath 1.0 funkcja translate() jest nadal dostępna w XPath 2.0. Funkcja ta może być wykorzystana do zastąpienia określonych znaków w ciągu innymi znakami lub całkowitego usunięcia wybranych znaków z ciągu.
Rysunek 15.16. Jak można się było spodziewać, przy zastosowaniu nowej funkcji XPath 2.0 plik wynikowy HTML pozostaje taki sam jak poprzednio
216
XPath 2.0
Testowanie warunków W XPath 1.0 wybieranie jednej z dwóch rzeczy do pliku wynikowego lub decydowanie, czy plik wynikowy ma w ogóle zawierać cokolwiek, odbywa się za pomocą instrukcji xsl:if lub xsl:choose (rysunek 15.17). XPath 2.0 umożliwia testowanie warunków w ramach samego wyrażenia XPath. Ponadto warunek testowy może być dowolnym wyrażeniem, którego wynikiem jest wartość logiczna (prawda lub fałsz), a nie tylko wyrażeniem wykorzystującym węzły.
Aby przetestować warunek: 1. W dowolnym miejscu, w którym możesz wstawić wyrażenie XPath, wpisz if (. 2. Określ wyrażenie logiczne, które chcesz przetestować.
4. Dalej wpisz then (. 5. Określ wyrażenie, którego wartość będzie zwracana, jeśli wyrażenie logiczne z punktu 2. będzie prawdziwe. 6. Wpisz ), aby zakończyć wyrażenie then. 7. Następnie wpisz else (. 8. Określ wyrażenie, którego wartość będzie zwracana, jeśli wyrażenie logiczne z punktu 2. będzie fałszywe. 9. Wpisz ), aby zakończyć wyrażenie else oraz test warunkowy (rysunek 15.18).
Wskazówki
Rysunek 15.18. Kod zapisany za pomocą wyrażeń warunkowych XPath 2.0. Jest on dużo krótszy i bardziej czytelny
Możesz użyć wyrażenia „if-then-else” jako wyrażenia w klauzuli „then” lub „else”. W ten sposób tworzona jest tzw. zagnieżdżona struktura „if-then-else” (patrz rysunek 15.18). Nawiasy zamykające wyrażenia then i else są opcjonalne. Zalecam jednak używanie nawiasów w celu zapewnienia większej przejrzystości w XPath. Z kolei nawiasy wokół wyrażenia testowego nie są już opcjonalne.
217
Testowanie warunków
Rysunek 15.17. Ten fragment kodu XPath 1.0 wykorzystuje warunkową strukturę „choose-when-otherwise”. Formuła ta oblicza liczbę lat przetrwanych przez każdy cud do momentu zniszczenia, biorąc przy tym pod uwagę zmianę ery z p.n.e. na n.e. oraz fakt, że piramida Cheopsa stoi do dzisiaj. Jest to sporo kodu do napisania i przeczytania
3. Następnie wpisz ), aby zakończyć wyrażenie testowe (ang. test expression).
Rozdział 15.
Kwantyfikacja warunku Może się zdarzyć, że będziesz chciał wiedzieć, czy każda z pozycji w sekwencji (lub niektóre z tych pozycji) spełniają określony warunek. Przykładowo, czy każdy z medali Michaela Phelpsa na Olimpiadzie w 2008 r. był złoty? Prawda. Czy niektóre z meczów Misty May-Treanor i Kerri Walsh na Olimpiadzie w 2008 r. zakończyły się przegraną? Fałsz.
Aby sprawdzić, czy każda pozycja w sekwencji spełnia pewien warunek: 1. W dowolnym miejscu, w którym możesz wstawić wyrażenie XPath (zazwyczaj jako wyrażenie testowe), wpisz every. 2. Następnie wpisz $nazwa_zmiennej, gdzie nazwa_zmiennej będzie odwoływać się do wartości wyrażenia z punktu 4. tej procedury.
Kwantyfikacja warunku
3. Dalej wpisz in (. 4. Określ wyrażenie będące sekwencją pozycji, które mają być przetestowane przez wyrażenie z punktu 7. tej procedury. 5. Następnie wpisz ), aby zakończyć to wyrażenie, czasem zwane sekwencją wiązania (ang. binding sequence).
Rysunek 15.19. Wykorzystałem tutaj obydwa warunki, every i some, aby sprawdzić, czy zniszczone zostały wszystkie cuda starożytności, niektóre z nich, czy też żaden. Zwróć uwagę na zastosowanie zagnieżdżonej struktury „if-then-else”, tak jak zostało to opisane w podrozdziale „Testowanie waruków”. Zwróć również uwagę na zastosowanie funkcji exists() języka XPath, która zwraca wartość logiczną na podstawie tego, czy jej argument istnieje, czy nie
6. Wpisz satisfies (. 7. Wykorzystując frazę $nazwa_zmiennej z punktu 2., określ wyrażenie testowe, które ma reprezentować pozycje z wyrażenia z punku 4. 8. Wreszcie wpisz ), aby zakończyć wyrażenie testowe oraz test warunkowy (rysunek 15.19).
Wskazówki Możesz również testować, czy niektóre z pozycji w sekwencji spełniają pewien warunek. W tym celu zastąp w punkcie 1. słowo every (każdy) słowem some (niektóre). Taka konstrukcja zwana jest wyrażeniem kwantyfikowanym (ang. quantified expression), a jej wynikiem jest wyrażenie logiczne. Nawiasy wokół sekwencji wiązania oraz wyrażenia testowego są opcjonalne. Zalecam jednak używanie nawiasów w celu zapewnienia większej przejrzystości w XPath.
218
Rysunek 15.20. Jak już pewnie wiesz, tylko niektóre z cudów starożytności zostały zniszczone
XPath 2.0
Usuwanie zduplikowanych pozycji Jedną z różnic pomiędzy zbiorami węzłów a sekwencjami jest to, że sekwencje mogą posiadać zduplikowane pozycje. Jest to istotne zwiększenie funkcjonalności wersji 2.0 w stosunku do wersji 1.0. Zdarzyć się może jednak, że będziesz chciał mieć sekwencję, w której każda pozycja reprezentowana jest tylko raz.
Aby usunąć zduplikowane pozycje z sekwencji: 1. Wpisz distinct-values(. 2. Następnie wpisz wyrażenie zawierające sekwencję, która ma zostać przetworzona. 3. Wpisz ), aby zakończyć funkcję (rysunek 15.21).
Wskazówka Kolejność pozycji zwracanych przez funkcję distinct-values() może się różnić w zależności od zastosowanego procesora XSLT. Jeśli potrzebujesz, aby Twoja sekwencja miała określony porządek, możesz użyć instrukcji xsl:sort, aby posortować sekwencję wynikową w wymagany sposób (rysunek 15.22).
Rysunek 15.22. Kod z rysunku 15.21 zwraca sekwencję państw, na terenie których wybudowano niegdyś cuda starożytności. Zwróć uwagę, że zastosowałem również element xsl:sort, aby uporządkować sekwencję alfabetycznie przed jej wyświetleniem
219
Usuwanie zduplikowanych pozycji
Rysunek 15.21. Ten przykład kodu XSLT 2.0/XPath 2.0 wykorzystuje funkcję distinct-values() do usunięcia z sekwencji zduplikowanych pozycji. Sekwencja ta jest generowana za pomocą funkcji substring-after(), która zwraca tylko nazwę kraju dla elementu lokalizacja
Rozdział 15.
Zapętlanie sekwencji Jedną z najbardziej potężnych nowych funkcji w XPath 2.0 jest możliwość zapętlania sekwencji. Choć jest to zbliżone do funkcjonalności instrukcji xsl:for-each w XPath 1.0, rezultatem pętli XPath 2.0 jest sekwencja. Ponadto taka sekwencja może być przetworzona jak każda inna, umożliwiając bardziej złożone transformacje danych niż te możliwe przy wykorzystaniu XSLT 1.0 z XPath 1.0.
Aby zapętlić sekwencję: 1. W dowolnym miejscu, w którym może występować wyrażenie XPath (choć zazwyczaj w obszarze danych wynikowych), wpisz for. 2. Następnie wpisz $zmienna_zakresowa, gdzie zmienna_zakresowa będzie przyjmowała wartość wszystkich pozycji z wyrażenia zdefiniowanego w punkcie 4. tej procedury.
Zapętlanie sekwencji
3. Wpisz in (. 4. Określ wyrażenie będące sekwencją pozycji użytych do ustawienia zmiennej zakresowej z punktu 2. tej procedury.
Rysunek 15.23. Tutaj wykorzystuję obliczenia pokazane na rysunku 15.18 w ramach wyrażenia for. Zwraca ono sekwencję lat istnienia wszystkich cudów. Zmienna zakresowa $i odwołuje się do bieżącego cudu w wyrażeniu for
5. Następnie wpisz ), aby zakończyć dane wyrażenie, zwane czasem sekwencją wiązania. 6. Dalej wpisz return (. 7. Określ wyrażenie zwrotne. To wyrażenie jest ewaluowane raz, z wykorzystaniem zmiennej $zmienna_zakresowa z punktu 2., w celu reprezentowania każdej pozycji z wyrażenia z punku 4. 8. Wpisz ), aby zakończyć wyrażenie zwrotne (ang. return expression) (rysunek 15.23).
Wskazówki Taka konstrukcja zwana jest wyrażeniem for. Wartością zwrotną wyrażenia for jest sekwencja. Nawiasy wokół sekwencji wiązania i wyrażenia zwrotnego są opcjonalne. Zalecam jednak używanie nawiasów w celu zapewnienia większej przejrzystości w XPath.
220
Rysunek 15.24. Wyrażenie for języka XPath 2.0 zwraca sekwencję. Ta sekwencja może być następnie wykorzystana w innym miejscu tego dokumentu XSLT. W końcowym fragmencie kodu przedstawionego na rysunku 15.23 użyłem na przykład na tej sekwencji funkcji min() i max(). Funkcje te zostały opisane w podrozdziale „Wyznaczenie wartości minimalnej lub maksymalnej”
XPath 2.0
Używanie bieżącej daty i czasu Język XPath 2.0 oferuje znacznie większy zestaw funkcji niż XPath 1.0. Niektóre z funkcji agregujących zostały omówione w podrozdziałach „Uśrednianie wartości w sekwencji” i „Wyznaczanie wartości minimalnej i maksymalnej”, a niektóre z funkcji ciągów zostały opisane w podrozdziale „Formatowanie ciągów”. Dodatkowo istnieją jeszcze w XPath 2.0 trzy nowe funkcje, które zwracają bieżącą datę i czas. Rysunek 15.25. W tym fragmencie kodu wykorzystałem funkcję format-date() w celu przekonwertowania wartości zwróconej z funkcji current-date() na czterocyfrowy format roku ([Y0001]). Chociaż funkcja current-date() zwraca bieżący rok, to jest on zwracany w postaci ciągu znaków. Ponieważ XPath 2.0 jest językiem silnie typizowanym, działanie arytmetyczne „rok_wybudowania + $biez_rok - 1” generuje błąd przetwarzania XSLT (ponieważ nie można wykonywać działań arytmetycznych na ciągu znaków)
Aby zwrócić bieżącą datę: Wpisz current-date() (rysunek 15.25).
Aby zwrócić bieżący czas: Wpisz current-time().
Aby zwrócić bieżące datę i czas: Wskazówki Każda z tych nowych funkcji zwraca typ prosty XML Schema. Są to typy, odpowiednio: xs:date, xs:time oraz xs:dateTime. Każda z tych nowych funkcji może być formatowana za pomocą nowych funkcji XSLT 2.0. Są to funkcje, odpowiednio: format-date(), format-time() oraz format-dateTime() (patrz rysunek 15.25).
Rysunek 15.26. Aby usunąć błąd przetwarzania z rysunku 15.25, muszę zamienić ciąg znaków '2008' na liczbę całkowitą = 2008. W tym celu w elemencie xsl:stylesheet zadeklarowałem przestrzeń nazw XML Schema i zastosowałem operator cast (rzutowanie), aby zmienić typ danych zmiennej $cur_year na xs:integer (liczbę całkowitą)
Aby modyfikować wartości będące typami xs:date, xs:time, xs:dateTime lub dowolnymi innymi typami daty XML Schema, musisz zadeklarować daną przestrzeń nazw w elemencie xsl:stylesheet (rysunek 15.26).
221
Używanie bieżącej daty i czasu
Wpisz current-dateTime().
Rozdział 15.
Pisanie komentarzy Możliwość opatrywania komentarzem kodu XPath jest niezwykle przydatna. Pozwala to objaśnić znaczenie konkretnej instrukcji lub określonego zbioru instrukcji. Co ciekawe, opcja ta nie była dostępna w XPath 1.0, ale jest częścią specyfikacji XPath 2.0.
Aby napisać komentarz: 1. Wpisz (:. 2. Napisz swój komentarz. 3. Wpisz :), aby zakończyć komentarz (rysunek 15.27).
Wskazówki
Pisanie komentarzy
Komentarze XPath mogą pojawiać się tylko tam, gdzie przewidywane są wyrażenia XPath. Komentarze XPath mogą obejmować kilka wierszy i zawierać dowolne znaki, w tym spacje, tekst, elementy oraz znaki nowej linii. W rzeczywistości mogą nawet zawierać dwukropek oraz nawias zamykający (chyba że te znaki występują razem, wtedy oznaczają zamknięcie komentarza). Podobnie jak w przypadku komentarzy XML, możesz używać komentarzy XPath w celu ukrywania zestawów instrukcji w trakcie przygotowywania kodu. Jest to określane mianem „wykomentowywania” sekcji. W obrębie wykomentowanej sekcji elementy, wraz z ewentualnymi błędami, nie będą przetwarzane przez procesor XPath. Jednak inaczej niż ma to miejsce w przypadku komentarzy XML, komentarze XPath mogą być zagnieżdżane w innych komentarzach XPath. Pozwala to wykomentować grupy instrukcji XPath, które same w sobie zawierają komentarze.
222
Rysunek 15.27. Te obliczenia aktualnie mogą być dla mnie jasne. Jeśli jednak wróciłbym do tego kodu za miesiąc, za pół roku lub za rok, bez komentarzy XPath byłoby dość trudno go zrozumieć
XPath 2.0
Przetwarzanie danych wejściowych typu nie-XML Chociaż technicznie możliwe było stosowanie danych wejściowych typu nie-XML w XSLT 1.0 i XSLT 2.0, nie było to łatwe zadanie i nastręczało wiele ograniczeń. Jednak w XSLT 2.0 i XPath 2.0 istnieje kilka nowych funkcji, które znacznie ułatwiają przetwarzanie danych wejściowych typu nie-XML (rysunek 15.28). Jest to już dość zaawansowany temat, ale wymieniłem poniżej kilka ważnych i stosownych funkcji.
Odczytywanie danych wejściowych typu nie-XML Funkcja unparsed-text(href) zwraca w postaci ciągu zawartość pliku odnalezionego za pomocą odnośnika href.
Rysunek 15.28. Ten przykład zwraca plik HTML ze wszystkimi liniami dialogów z aktu III dramatu „Juliusz Cezar”, które zawierają słowo „Cezar”. Funkcja unparsed-text() ustawia wartość zmiennej tekst_wejsciowy tak, aby była ona równa tekstowi z pliku juliusz_cezar-akt-iii.txt. Funkcja replace() zamienia w zmiennej tekst_wejsciowy wszystkie znaki nowego wiersza i powroty karetki na spacje, a następnie zapisuje rezultat w zmiennej kwestie_wejsciowe. Funkcja tokenize() dzieli kwestie_wejsciowe na sekwencję ciągów znaków i zapisuje ją w zmiennej bez_mowcy. Znacznikiem rozdzielającym jest wielka litera, po której następuje kropka (\b[A-Z ]+\.). Te znaczniki to imiona mówców w tekście. Funkcja analyze-string() i jej funkcja towarzysząca matching-substring() zwracają te ciągi znaków ze zmiennej bez_mowcy, które zawierają słowo „Cezar”. Można to było również osiągnąć za pomocą funkcji contains()
Funkcja tokenize(dane_wejściowe, wzorzec_regex) zwraca sekwencję ciągów z ciągu dane_wejściowe, wykorzystując wzorzec_regex, aby podzielić ciąg wejściowy na poszczególne fragmenty. Funkcja replace(dane_wejściowe, wzorzec_regex, podmiana) zwraca zaktualizowany ciąg dane_wejściowe, gdzie każde wystąpienie elementu wzorzec_regex w ciągu danych wejściowych jest zastępowane ciągiem podmiana. Funkcja match(dane_wejściowe, wzorzec_regex) zwraca określoną wartość logiczną (prawda lub fałsz) w zależności od tego, czy ciąg dane_wejściowe odpowiada wzorcowi wzorzec_regex, czy nie. Funkcja analyze-string(select="wyrażenie" regex="wzorzec") zwraca sekwencję wszystkich ciągów, dla których wybrane wyrażenie odpowiada wzorcowi wyrażenia regularnego wzorzec. Po tym pojawia się jedna z następujących instrukcji lub obydwie: lub (i) . Każda z tych instrukcji przetwarza właściwe podciągi z instrukcji analyze-string.
223
Przetwarzanie danych wejściowych
Parsowanie danych wejściowych z wykorzystaniem wyrażeń regularnych
Rozdział 15.
224
XQuery 1.0
16
Rozdział 16. XQuery 1.0[RS1] XQuery 1.0 (ang. XML Query Language, czyli język zapytań XML) jest trzecim głównym językiem wynikającym z ośmiu rekomendacji organizacji W3C opublikowanych zbiorczo w styczniu 2007 r. Podobnie jak XSLT 2.0 (rozdział 14.), język XQuery jest wykorzystywany do selekcji zawartości z danych źródłowych XML, przekształcania tej zawartości według określonych wskazówek, a następnie zwracania nowej zawartości w postaci pliku XML, HTML lub w jakimś innym formacie. XQuery, tak jak XSLT 2.0, stosuje język XPath 2.0 (rozdział 15.) do wybierania zawartości źródłowej XML oraz do modyfikacji tej zawartości w razie potrzeby. W rzeczywistości większość zadań wykonywanych za pomocą XSLT 2.0 możesz również zrealizować, wykorzystując do tego celu XQuery 1.0.
Podobnie jak to miało miejsce w przypadku XSLT 2.0 i XPath 2.0, będziesz potrzebował odpowiedniego procesora XQuery, aby sprawdzić, jak działają przykłady zamieszczone w tej książce, lub samemu pisać dokumenty XQuery. Jeśli nie posiadasz jeszcze takiego procesora, zapoznaj się z listą dostępnych opcji zamieszczoną w dodatku A, „Narzędzia XML”. Więcej informacji na temat XQuery znajdziesz na stronie grupy roboczej XQuery organizacji W3C: http://www.w3.org/XML/Query.
225
XQuery 1.0
XQuery 1.0 różni się od XSLT 2.0 w kilku istotnych kwestiach, z których najbardziej zauważalne jest to, że XQuery nie wykorzystuje składni XML. To sprawia, że język ten jest bardziej zwięzły i łatwiejszy do opanowania, szczególnie dla początkujących użytkowników XML-a lub osób z wcześniejszym doświadczeniem w programowaniu. Co ciekawe, jedna z pozostałych ośmiu opublikowanych rekomendacji dotyczy języka zwanego XQueryX, który wykorzystuje składnię XML dla zapytań (kwerend) XQuery. Jest to jednak język rozwlekły oraz niepraktyczny i jest faktycznie użyteczny jedynie dla narzędzi programowych XML, a nie dla samych użytkowników.
Rozdział 16.
XQuery 1.0 a XSLT 2.0 Zarówno język XQuery 1.0, jak i XSLT 2.0 może być używany do kwerendowania danych źródłowych XML. Obydwa te języki są zbudowane na wyrażeniach XPath 2.0 i wykorzystują ten sam model danych, XDM. W obu językach możesz tworzyć funkcje definiowane przez użytkownika oraz używać XML Schema do walidacji zawartości źródłowej XML i zawartości plików wynikowych XML.
XQuery 1.0 a XSLT 2.0
Biorąc to pod uwagę, na poziomie zasadniczym wybór pomiędzy XQuery 1.0 a XSLT 2.0 jest kwestią gustu i doświadczenia. XSLT 2.0 wykorzystuje składnię XML i jest rozszerzeniem XSLT 1.0, w którym możesz mieć już pewne doświadczenie. Z drugiej strony, XQuery nie wykorzystuje składni XML i ma bardziej zbliżoną strukturę do SQL-a (ang. Structured Query Language — strukturalny język zapytań), kolejnego języka, z którym możesz być zaznajomiony.
Rysunek 16.1. Ten fragment kodu XSLT wykorzystuje XPath do pobrania sekwencji nazw cudów, dla których atrybut jezyk równa się 'polski'. Następnie wykorzystywana jest konstrukcja xsl:for-each do zapętlenia tych wszystkich nazw i wyświetlenia ich w pliku HTML w postaci listy wypunktowanej
Jeśli chodzi o podstawowe rodzaje zapytań i transformacji, obydwa języki są równie właściwe (rysunki 16.1 i 16.2). Jednak powszechnie znane badania wykazały, że przy braku wcześniejszej wiedzy XQuery jest łatwiejszy do opanowania niż XSLT 2.0. Z kolei jeśli weźmiemy pod uwagę bardziej złożone wymagania odnośnie do przekształceń, lepszym wyborem staje się XSLT 2.0. Język ten udostępnia lepszą obsługę dla grupowania danych, formatowania liczb i dat oraz walidacji względem schematów. Mimo to język XQuery charakteryzuje się istotnie zwiększającą się dynamiką. Jednym z głównych tego powodów jest to, że został on zaprojektowany z założeniem bezpośredniego kwerendowania baz danych. Przy tym główni dostawcy baz danych, jak IBM, Microsoft i Oracle, oferują mechanizmy umożliwiające przeglądanie ich baz danych za pomocą XQuery, w sposób podobny jak to ma miejsce w przypadku wszelkich innych źródeł XML. Najistotniejsze jest to, że wybór pomiędzy XQuery 1.0 a XSLT 2.0 może być subiektywny. Dla bardziej złożonych zapytań sugerowałbym zastosowanie XQuery, natomiast dla złożonych transformacji polecałbym XSLT 2.0. Co więcej, znaczna część infrastruktury przetwarzania XML pozwala mieszać języki, więc prawdopodobnie najlepiej zostaniesz obsłużony przez obydwa języki, przy czym każdy z nich zostanie zastosowany w najbardziej odpowiednim obszarze.
226
Rysunek 16.2. Ten fragment kodu XQuery generuje dokładnie taki sam plik HTML co kod XSLT przedstawiony na rysunku 16.1. Tutaj pętla tworzona jest, kiedy XPath zwraca każdy z węzłów cud, dla którego atrybut jezyk równa się 'polski', oraz ustawia zmienną $x. Następnie za każdym razem przy wykonywaniu pętli wartość zmiennej $x jest przesyłana do pliku wynikowego HTML w postaci wypunktowanej listy
XQuery 1.0
Redagowanie dokumentu XQuery
Rysunek 16.3. W powyższym dokumencie XQuery zadeklarowałem, że korzystam z wersji 1.0 tej specyfikacji. Następnie wpisałem literalny ciąg znaków, który po przetworzeniu tego dokumentu zostanie wyświetlony w przedstawiony sposób
Dokument XQuery jest plikiem wyłącznie tekstowym i rozpoczyna się od deklaracji wersji (rysunek 16.3). Nie rozpoczyna się standardową deklaracją XML, ponieważ nie jest dokumentem XML. Dokument XQuery jest zapisywany z rozszerzeniem .xquery lub .xq. W tym rozdziale będę używał tego drugiego rozszerzenia.
Aby utworzyć dokument XQuery: 1. Na początku dokumentu wpisz xquery. 2. Następnie wpisz version "1.0". 3. Dalej wpisz ; (średnik). 4. Wpisz wyrażenie XQuery lub wiele wyrażeń XQuery rozdzielonych przecinkami.
Wskazówki
Rysunek 16.5. W tym przykładzie tworzę element XML o nazwie odliczanie. Zwróć uwagę na zastosowanie nawiasów klamrowych, które ograniczają wyrażenie zamknięte. Wyrażenie to jest następnie ewaluowane i zastępowane w pliku wynikowym jego wartością
Komentarze w XQuery wykorzystują tę samą składnię co komentarze w XPath 2.0. Początek komentarza wskazują znaki (:, a jego koniec znaki :). Ponadto, podobnie jak w XPath 2.0, komentarze mogą być zagnieżdżane. Podczas korzystania z konstruktorów elementów (rysunek 16.5) nawiasy klamrowe ({}) są stosowane do odróżnienia wyrażeń od literalnego tekstu. Takie wyrażenia zamknięte (ang. enclosed expressions) są ewaluowane, zanim zostaną przesłane jako dane wyjściowe. Chociaż język XQuery nie wykorzystuje składni XML, to istotna jest wielkość liter, a wszystkie instrukcje XQuery zapisywane są małymi literami.
227
Redagowanie dokumentu XQuery
Rysunek 16.4. W tym przykładzie trzy wyrażenia XQuery zostały rozdzielone przecinkami. Drugie wyrażenie konstruuje sekwencję, która jest następnie odwracana za pomocą wbudowanej funkcji reverse()
Wyrażenie XQuery może być literalną wartością liczbową lub literalnym ciągiem znaków (rysunek 16.3), konstruktorem sekwencji (rysunek 16.4), konstruktorem elementu (rysunek 16.5), funkcją wbudowaną lub zdefiniowaną przez użytkownika (patrz podrozdział „Tworzenie i wywoływanie funkcji definiowanych przez użytkownika”), jednym z wbudowanych wyrażeń, takich jak wyrażenie warunkowe (patrz podrozdział „Testowanie za pomocą wyrażeń warunkowych”) lub wyrażeniem FLWOR (patrz podrozdział „Pisanie wyrażeń FLWOR”).
Rozdział 16.
Identyfikowanie dokumentu źródłowego XML Aby przetworzyć dokumenty źródłowe za pomocą którejś z wersji XSLT, należy zastosować dyrektywę przetwarzania XML: xml-stylesheet. Ta dyrektywa umożliwia identyfikację ścieżki do źródłowego dokumentu XML. W przypadku XQuery nie istnieje jednak taka dyrektywa przetwarzania XML. Aby określić źródło XML dla dokumentu XQuery, możesz zastosować funkcję doc().
Aby określić dokument źródłowy XML: 1. Wpisz doc(.
Identyfikowanie dokumentu źródłowego XML
2. Następnie wpisz uri_dokumentu, gdzie uri_dokumentu jest ścieżką do źródłowego dokumentu XML. 3. Wpisz ), aby zakończyć funkcję (rysunek 16.6).
Wskazówki Niektóre procesory XQuery wymagają wskazania dokumentu źródłowego podczas przetwarzania dokumentu XQuery (a nie w samym kodzie XQuery). W takim przypadku będziesz musiał zastąpić uri_dokumentu w funkcji doc() znakiem kropki. Reprezentuje ona bieżący kontekst, którego będziesz musiał użyć zamiast URI. Bez względu na to, z jakiego procesora XQuery będziesz korzystał, dokument XQuery może w rzeczywistości korzystać z więcej niż jednego dokumentu źródłowego XML (patrz podrozdział „Łączenie dwóch powiązanych źródeł danych”).
228
Rysunek 16.6. W tym przykładzie XQuery określiłem dokument źródłowy XML jako plik wonders-master.xml, z którym już pewnie się zapoznałeś. Funkcja doc() zwraca jako sekwencję drzewo węzłów bieżącego kontekstu
XQuery 1.0
Używanie wyrażeń ścieżkowych Do selekcji zawartości z danych źródłowych XML XQuery wykorzystuje składnię języka XPath (rysunek 16.7). Dokument źródłowy XML jest najpierw konwertowany na drzewo węzłów XML. Następnie na podstawie dostarczonej przez Ciebie ścieżki lokalizacji drzewo XML jest przeszukiwane w celu odnalezienia żądanych informacji. Jak zostało to omówione w rozdziale 3., ścieżka lokalizacji opisuje pozycję żądanej zawartości względem pozycji bieżącego kontekstu.
Aby użyć wyrażenia ścieżkowego: Rysunek 16.7. W tym przykładzie wykorzystałem funkcję doc() w celu pobrania węzła dokumentu z dokumentu źródłowego wonders-master.xml. Następnie użyłem ścieżki lokalizacji /cuda_starozytnosci/cud/lokalizacja do pobrania elementu lokalizacja każdego cudu
1. Najpierw określ dokument źródłowy XML za pomocą funkcji doc() opisanej w podrozdziale „Identyfikowanie dokumentu źródłowego XML”. 2. Następnie wpisz dowolne poprawne wyrażenie XPath. To wyrażenie będzie wykorzystane dla drzewa węzłów wygenerowanego ze źródłowego dokumentu XML, który został pobrany za pomocą funkcji doc() z punktu 1.
Niektóre procesory XQuery wymagają wskazania dokumentu źródłowego podczas przetwarzania dokumentu XQuery. W takim przypadku będziesz musiał zastąpić uri_dokumentu w funkcji doc() znakiem kropki, która reprezentuje bieżący kontekst. Rysunek 16.8. W tym fragmencie kodu dodałem predykat, aby wybrać tylko te elementy lokalizacja, które zawierają ciąg „Turcja”
Podobnie jak wszystkie wyrażenia XPath, wyrażenia użyte w XQuery mogą przyjmować predykaty, a predykaty XQuery mogą również wykorzystywać funkcje (rysunki 16.8 i 16.9).
Rysunek 16.9. Tutaj zmieniłem wyrażenie ścieżkowe i predykat tak, aby zwracane były elementy nazwa, które posiadają element lokalizacja zawierający ciąg „Turcja”
229
Używanie wyrażeń ścieżkowych
Wskazówki
Rozdział 16.
Pisanie wyrażeń FLWOR Wyrażenie FLWOR jest unikatowe dla XQuery (rysunek 16.10). Jest ono zbliżone do instrukcji xsl:for-each języka XSLT i jest rozszerzeniem wyrażenia for języka XPath 2.0. Ponadto wyrażenie FLWOR jest luźno oparte na poleceniu SELECT języka SQL. Nazwa tego wyrażenia jest skrótowcem utworzonym z pięciu słów w języku angielskim: for (dla), let (niech), where (gdzie), order (kolejność) oraz return (zwróć).
Aby napisać podstawowe wyrażenie FLWOR: 1. Wpisz for. 2. Następnie wpisz $zmienna_zakresowa, gdzie zmienna zakresowa będzie przyjmować wartość każdej pozycji zwróconej w wyrażeniu z punktu 4. tej procedury.
Pisanie wyrażeń FLWOR
3. Dalej wpisz in. 4. Określ wyrażenie, które jest sekwencją pozycji użytych do ustawienia zmiennej zakresowej z punktu 2. tej procedury. Wyrażenie to określane jest czasem sekwencją wiązania (ang. binding sequence).
Rysunek 16.10. Powyższe wyrażenie FLWOR ustawia dla zmiennej zakresowej $cudstar każdy z elementów cud z pliku źródłowego XML o nazwie wonders-master.xml. Następnie klauzula where filtruje sekwencję zmiennych $cudstar tak, aby pozostawić tylko te, których element lokalizacja zawiera ciąg „Turcja”. Dalej klauzula return przesyła do pliku wynikowego każdy z tych elementów nazwa. Analizując ten plik wynikowy, zobaczysz, że wyrażenie FLWOR generuje dokładnie taki sam rezultat jak przykład z rysunku 16.9
5. Następnie wpisz where. 6. Określ wyrażenie, które przefiltruje zbiór zmiennych zakresowych (z punktu 2.) na podstawie sekwencji wiązania (z punktu 4.). Wyrażenie to jest zazwyczaj określane klauzulą where. 7. Wpisz return. 8. Na koniec określ klauzulę return. To wyrażenie jest ewaluowane raz dla każdego zestawu zmiennych zakresowych na podstawie sekwencji wiązania, a następnie filtrowane przez klauzulę where (punkty, odpowiednio: 2., 4. i 6.).
Wskazówka W wyrażeniu FLWOR klauzula where z punktów 5. i 6. jest opcjonalna. Kolejną opcjonalną klauzulą w wyrażeniu FLWOR jest order by. Klauzula ta sortuje finalną sekwencję pozycji, zanim zostanie ona przesłana do pliku wynikowego za pomocą klauzuli return (rysunek 16.12).
230
Rysunek 16.11. W tym przykładzie dodałem do klauzuli return predykat, który powoduje wysłanie do pliku wynikowego tylko tych elementów nazwa, dla których atrybut jezyk równa się 'polski'
XQuery 1.0 Aby załączyć klauzulę order by: 1. Bezpośrednio przed klauzulą return z punktów 7. i 8. poprzedniej procedury z tego podrozdziału wpisz order by. 2. Określ wyrażenie, które uporządkuje finalną sekwencję pozycji przeznaczoną do zwrócenia przez klauzulę return.
Rysunek 16.12. Tutaj użyłem klauzuli order by, aby posortować finalną sekwencję według polskiej nazwy każdego cudu
Ostatnią klauzulą w wyrażeniu FLWOR jest let (niech) (rysunek 16.13). Generuje ona uporządkowaną sekwencję pozycji, podobnie jak klauzula for. Różnica pomiędzy nimi jest taka, że dla każdej pozycji w sekwencji wygenerowanej przez klauzulę for tylko jedna pozycja jest tworzona dla zmiennej w klauzuli let, nawet jeśli ta zmienna jest sama ustawiona jako sekwencja.
Aby załączyć klauzulę let: 1. Przed klauzulą return oraz przed klauzulami opcjonalnymi where i order by (jeśli takie zostały załączone) wpisz let.
3. Dalej wpisz := (dwukropek i znak równości). 4. Na koniec określ wyrażenie, które ustawi zmienną instancyjną z punku 2. tej procedury. Wyrażenie to zwane jest czasem sekwencją wiązania.
Wskazówki
Rysunek 16.13. Klauzula let ustawia dla zmiennej $zrdl element (lub elementy) zrodlo dla każdego cudu w klauzuli for (również filtrowanej przez klauzulę where). Te elementy zrodlo są przesyłane do pliku wynikowego z zapisanym w języku polskim elementem nazwa każdego cudu. Nawiasy i separator w postaci przecinka w klauzuli return tworzą pojedynczą sekwencję z dwóch przedstawionych wyrażeń. Zostało to użyte, ponieważ klauzule return mogą przesyłać do pliku wynikowego tylko pojedyncze wyrażenie
Możesz zdefiniować dowolną liczbę klauzul for i let, ale musisz mieć przynajmniej po jednej z nich, aby wyrażenie FLWOR było poprawne. Czasem zbiór zmiennych w klauzuli for jest wykorzystywany w wyrażeniu klauzuli let. Tworzy to coś podobnego do klauzuli join (złączenia) w SQL, co zostało omówione w podrozdziale „Łączenie dwóch powiązanych źródeł danych”.
231
Pisanie wyrażeń FLWOR
2. Następnie wpisz $zmienna_instancyjna, gdzie zmienna_instancyjna zostanie ustawiona jako wynik wyrażenia z punktu 4. tej procedury.
Rozdział 16.
Testowanie za pomocą wyrażeń warunkowych Wyrażenia warunkowe w XQuery 1.0 wykorzystują tę samą składnię if-then-else co wyrażenia warunkowe w XPath 2.0. Wyrażenia te (rysunek 16.14) zapewniają możliwość testowania warunku i przesyłania do pliku wynikowego różnych rezultatów na podstawie wartości logicznej (prawda lub fałsz) danego warunku.
Aby przeprowadzić test za pomocą wyrażenia warunkowego: 1. Wpisz if(.
Testowanie za pomocą wyrażeń warunkowych
2. Określ wyrażenie logiczne będące warunkiem, który chcesz przetestować. 3. Następnie wpisz ), aby zakończyć wyrażenie testowe. 4. Dalej wpisz then. 5. Określ wyrażenie, którego wartość będzie zwracana, jeśli wyrażenie logiczne z punktu 2. tej procedury będzie prawdziwe. Wyrażenie to jest nazywane wyrażeniem then. 6. Wpisz else. 7. Na koniec określ wyrażenie, którego wartość będzie zwracana, jeśli wyrażenie logiczne z punktu 2. będzie fałszywe. Wyrażenie to jest nazywane wyrażeniem else.
Wskazówki Dla wyrażeń then i else możesz używać dowolnego poprawnego wyrażenia. W rzeczywistości wyrażenia te mogą nawet być nowymi wyrażeniami if-then-else (rysunek 16.14). W ten sposób tworzona jest tzw. zagnieżdżona struktura if-then-else. Wyrażenie testowe musi być ujęte w nawiasy. W przypadku wyrażeń then i else zastosowanie nawiasów jest opcjonalne. Nawet jeśli nie potrzebujesz wyrażenia else, musisz je zastosować. Użyj po prostu formy else(), która zwraca pustą sekwencję (rysunek 16.4). Zwróć uwagę, że w tym przypadku nawiasy są wymagane.
232
Rysunek 16.14. W tym przykładzie XQuery wyrażenie warunkowe testuje, w jaki sposób każdy cud został zniszczony, a następnie zwraca nowy element ( lub ) z polską nazwą danego cudu. Pamiętaj, że wyrażenia zamknięte umieszczone w nawiasach klamrowych są ewaluowane przed wysłaniem do pliku wynikowego
XQuery 1.0
Łączenie dwóch powiązanych źródeł danych Często informacje, z którymi pracujesz, są zawarte w kilku źródłach danych XML. Język XQuery pozwala Ci za pomocą wyrażenia FLWOR kwerendować informacje z kilku plików jednocześnie.
Rysunek 16.15. Utworzyłem plik XML zawierający informacje (całkowicie fikcyjne) na temat trzęsień ziemi, które miały miejsce w XIV w. i na początku XV w. Plik ten nazywa się earthquake_data.xml
Aby połączyć dwa powiązane źródła danych: 1. Napisz klauzulę for, która odwołuje się do pierwszego źródła danych. 2. Następnie napisz drugą klauzulę for odwołującą się do drugiego źródła danych. Relacja pomiędzy obydwoma źródłami danych zostanie zdefiniowana w punkcie 3. tej procedury.
Rysunek 16.16. W tym przykładzie pierwszym źródłem danych jest plik wonders-master.xml, a drugim plik earthquake_data.xml. Klauzula where łączy te dwa źródła danych, dopasowując element dotkniete_miasta/miasto do elementów lokalizacja dla każdego cudu. W wyniku otrzymujemy listę cudów, które zostały dotknięte trzęsieniem ziemi w XIV i XV w. oraz daty każdego z trzęsień ziemi
3. W klauzuli where wyrażenia FLWOR użyj zmiennych zakresowych z klauzul for z punktów 2. i 3., aby zdefiniować relację pomiędzy źródłami danych (rysunek 16.16).
Wskazówka W rzeczywistości istnieje wiele różnych sposobów łączenia powiązanych źródeł danych. Zamiast jednej z klauzul for (lub zamiast obydwu tych klauzul) mógłbyś użyć klauzul let. Mógłbyś też napisać drugie wyrażenie FLWOR jako klauzulę return dla pierwszego wyrażenia FLWOR albo użyć predykatów zamiast klauzuli where itd. Idea pozostaje taka sama. Połączenie dwóch powiązanych źródeł danych wymaga w pierwszym źródle danych pozycji, które odnoszą się do pozycji (i często są im równe) w drugim źródle danych.
233
Łączenie dwóch powiązanych źródeł danych
Przykładowo sklep odzieżowy może operować dwoma plikami XML. Jeden obejmuje listę produktów zawierającą identyfikator produktu, nazwę, cenę oraz opis. Drugi plik zawiera informacje o zamówieniach, takie jak identyfikator zamówienia, identyfikator produktu, ilość zakupionego towaru oraz informacje o kliencie. Wykorzystując identyfikator produktu jako podstawową relację pomiędzy tymi dwoma plikami, możesz użyć wyrażenia FLWOR języka XQuery do obliczenia całkowitego kosztu zamówienia. W tym celu należy pomnożyć ilość każdego zakupionego produktu (w pliku zamówień) przez cenę samego produktu (w pliku produktów).
Rozdział 16.
Tworzenie i wywoływanie funkcji definiowanych przez użytkownika Funkcja definiowana przez użytkownika (ang. User Defined Function — UDF) w języku XQuery działa tak samo jak funkcja wbudowana w XQuery. Różnica polega na Rysunek 16.17. Ten plik XML o nazwie tym, że sam definiujesz jej nazwę, parametry wejściowe, richter_scale.xml zawiera informacje dotyczące czynności wykonywane na parametrach wejściowych energii uwalnianej przez trzęsienia ziemi o różnych oraz parametry wyjściowe. magnitudach skali Richtera
Aby utworzyć funkcję definiowaną przez użytkownika: 1. Bezpośrednio po deklaracji wersji (patrz podrozdział „Redagowanie dokumentu XQuery”) wpisz declare function.
Tworzenie i wywoływanie funkcji
2. Następnie wpisz local:nazwa_UDF(, gdzie nazwa_UDF jest nazwą Twojej funkcji. 3. Dalej, aby określić wybrane parametry wejściowe, wpisz $nazwa_parametru, gdzie nazwa_parametru odnosi się do tego parametru w ramach Twojej funkcji UDF. 4. Powtórz punkt 3. dla każdego kolejnego parametru, który chcesz zdefiniować. Parametry rozdzielaj przecinkami, a listę parametrów zamknij nawiasem ). Możesz również nie definiować żadnych parametrów wejściowych i pominąć punkt 3. 5. Wpisz {. 6. Następnie napisz swoje wyrażenie XQuery. Jeśli w punktach 3. i 4. zdefiniowałeś jakieś parametry wejściowe, użyj ich w tym wyrażeniu. 7. Wpisz };, aby zakończyć funkcję.
Aby wywołać funkcję zdefiniowaną przez użytkownika: 1. W dowolnym miejscu, w którym przewidywana jest funkcja XQuery, wpisz local:nazwa_UDF(, gdzie nazwa_UDF odpowiada nazwie użytej w punkcie 2. pierwszej z procedur opisanych w tym podrozdziale. 2. Wpisz wartość (lub wartości) wybranych parametrów wejściowych zdefiniowanych w punkcie 3. pierwszej z procedur opisanych w tym podrozdziale. Wartości rozdzielaj przecinkami. Jeśli nie zadeklarowałeś żadnych parametrów wejściowych, pomiń ten punkt. 3. Wpisz ), aby zakończyć wywołanie swojej funkcji UDF.
234
Rysunek 16.18. Funkcja UDF o nazwie richter ma parametr wejściowy o nazwie $mag. Funkcja ta zaokrągla parametr $mag do najbliższego przyrostu o wartości 0,5 i zwraca wartość energii uwolnionej przez trzęsienie ziemi o danej magnitudzie oraz przykład działania takiej energii w innym kontekście. Wyrażenie wywołujące local:richter(...) jest częścią klauzuli return z klauzuli FLWOR przedstawionej na rysunku 16.16
Wskazówka Język XQuery zapewnia przestrzeń nazw (local:), aby zapobiec konfliktom pomiędzy nazwami UDF a nazwami funkcji w domyślnej przestrzeni nazw. Możesz również zadeklarować i zastosować inne przestrzenie nazw dla swoich funkcji UDF.
XQuery 1.0
XQuery i bazy danych Język XQuery został specjalnie zaprojektowany w taki sposób, aby umożliwiał kwerendowanie szerokiego wachlarza źródeł danych XML. W tym celu przed przetworzeniem zapytania wszystkie źródła danych są konwertowane na drzewo węzłów XML. Dla języka XQuery nie ma znaczenia, czy źródłem danych jest jakiś przypadkowy plik, dokument XML, czy relacyjna baza danych.
Rysunek 16.19. Jest to fragment tabeli z bazy danych zawierającej liczby medali zdobytych przez poszczególne kraje podczas XXIX Letnich Igrzysk Olimpijskich w 2008 r. Nazwa tabeli to medals (medale), a nazwa bazy danych to olympics (igrzyska). Nazwy kolumn: kraj, złoto, srebro i brąz
Od momentu powstania języka XQuery deweloperzy baz danych pisali rozszerzenia dla dwukierunkowej wymiany danych pomiędzy ich bazami danych a dokumentami XML. Dzięki temu te bazy danych były w stanie eksportować dane w formacie XML, a także konwertować (lub fragmentować) dane XML na format relacyjnej bazy danych. Jednak używanie bazy danych z obsługą XML-a sprawdza się dobrze tylko wówczas, jeśli dane XML można łatwo przekonwertować na strukturę „wierszy i kolumn” relacyjnej bazy danych. Ponadto fragmentowanie danych XML w celu przechowywania w bazie danych, a następnie ponowne łączenie ich do postaci XML jest często nieefektywnym i kosztownym procesem.
Rysunek 16.20. W tym przykładzie funkcja collection() została wykorzystana do ustawienia dla zmiennej $medale_pnst sekwencji wierszy z tabeli medals z bazy danych olympics. Choć technicznie jest to wyrażenie FLWOR, w tym dokumencie XQuery nie ma klauzuli for. Jeśli w pierwszej linii kodu zamiast klauzuli let mielibyśmy klauzulę for, obliczenia funkcji sum() odbywały się tylko na bazie wierszy, a nie na całym drzewie węzłów
Specyfikacja XQuery nie opisuje jednak sposobu nawiązywania połączenia z bazą danych. Większość procesorów XQuery wykorzystuje funkcję collection(). Podobnie do funkcji doc(), funkcja collection() przyjmuje argument URI i zwraca sekwencję węzłów (rysunek 16.20). Mimo to różne procesory odmiennie interpretują dany adres URI, więc powinieneś zapoznać się z dokumentacją swojego procesora, aby znaleźć szczegółowe informacje na ten temat. Poza stroną grupy roboczej XQuery, dostępną pod adresem http://www.w3.org/XML/Query, dobrym (choć już nieco nieaktualnym) źródłem informacji na temat XML-a i baz danych jest strona http://www.rpbourret.com/xml/.
235
XQuery i bazy danych
Aby rozwiązać te problemy, opracowano nowy typ bazy danych. Został on zaprojektowany tak, aby mógł obsługiwać standardowe funkcje baz danych, ale przechowywał swoje dane w natywnym formacie XML. Choć wielu użytkowników nie jest zainteresowanych (lub nie ma w tym zakresie uprawnień) zmianą aplikacji bazodanowej, wielu innych zaczęło korzystać z natywnych baz danych XML.
Rozdział 16.
236
XML w praktyce
VII
Część VII XML w praktyce
Rozdział 17. Ajax, RSS, SOAP i inne zastosowania języka XML
239
237
Rozdział x.
238
Ajax, RSS, SOAP i inne zastosowania języka XML
17
Rozdział 17. Ajax, RSS, SOAP i inne zastosowania języka XML Mam nadzieję, że podczas lektury tej książki zrozumiałeś, że XML nie jest sam w sobie językiem znaczników. Jest on raczej specyfikacją do tworzenia języków znaczników i stąd jego naturalna rozszerzalność.
Przykłady z tego rozdziału nie są nawet w przybliżeniu tak obszerne jak te, które możesz znaleźć w pozostałej części książki. Jest tak dlatego, że założeniem tego rozdziału nie jest opisywanie sposobów rozwijania oprogramowania dla każdego z zastosowań XML-a, którym można by poświęcić osobne rozdziały. Przedstawione przykłady mają raczej za zadanie ogólne zobrazowanie określonych implementacji oraz ukazanie, w jaki sposób XML jest wykorzystywany w praktyce. W lutym 1998 r. XML stał się oficjalną rekomendacją W3C. Członkowie tej grupy roboczej z pewnością zdawali sobie sprawę, że mieli świetny pomysł, ale nie sądzę, żeby mogli przewidzieć, czym stanie się XML. Ten rozdział poświęcony jest właśnie temu, czym stał się XML. Uwaga! Jeśli chcesz dokładniej prześledzić przykłady zamieszczone w tym rozdziale, zapoznaj się ze wskazówkami z ostatniego podrozdziału, „Narzędzia dla XML-a w praktyce”.
239
Ajax, RSS, SOAP i inne zastosowania języka XML
W tym rozdziale postaram się wskazać i przeanalizować niektóre z szeroko rozpowszechnionych zastosowań XML-a. W jednym przypadku XML jest po prostu wykorzystywany jako kontener danych. W innym przypadku utworzony język znaczników niestandardowych został rozszerzony przez korzystających z niego użytkowników. W jeszcze innym przypadku mamy do czynienia z dwoma standardami XML walczącymi o pozycję tego jedynego właściwego standardu. Ponadto w wielu przykładach XML jest integralną częścią procesu tworzenia nowej technologii.
Rozdział 17.
Podstawy technologii Ajax
Podstawy technologii Ajax
Ajax (również zapisywane jako AJAX, ang. Asynchronous JavaScript and XML) oznacza asynchroniczny JavaScript i XML. Jest to oparta na sieci WWW technika, dzięki której doświadczenie użytkownika, kiedy strona WWW jest aktualizowana na podstawie wprowadzanych przez tego użytkownika danych, staje się bardziej „płynne”. Przykładowo strona, która nie używa techniki Ajax (rysunek 17.1), będzie przyjmować dane wprowadzane przez użytkownika i przekazywać je do przetwarzania Rysunek 17.1. Bez zastosowania techniki Ajax dane do skryptu na serwerze WWW. Najczęściej dzieje się są przesyłane do serwera WWW, przetwarzane, tak, kiedy użytkownik klika przycisk „zatwierdź” lub a następnie zwracana jest nowa strona wybiera jakąś opcję z rozwijanego menu. Wprowadzone przez użytkownika dane są wtedy przetwarzane przez serwer, a następnie tworzona jest nowa strona HTML. Ta nowa strona jest przesyłana do przeglądarki, która odświeża wyświetlaną w danym momencie stronę. Strona WWW wykorzystująca technikę Ajax (rysunek 17.2) również przyjmuje dane wprowadzane przez użytkownika i przesyła je do skryptu na serwerze WWW. Uruchamiane jest to tak samo w poprzednim przypadku, jednak dane wprowadzane przez użytkownika są wysyłane do serwera WWW w inny sposób (zostanie to omówione bardziej szczegółowo nieco później). Dane od użytkownika są następnie przetwarzane przez serwer, ale zamiast tworzenia nowej strony HTML, tworzone są tylko nowe dane. Te nowe dane są zwracane do przeglądarki (ponownie z wykorzystaniem innego mechanizmu niż w przypadku niekorzystania z techniki Ajax). Następnie, zamiast odświeżania strony, odbywa się po prostu aktualizacja istniejącej strony (zostają wprowadzone nowe dane).
Rysunek 17.2. Tutaj dane są zatwierdzane przez serwer WWW i przez ten serwer zwracane. Jednak dzięki zastosowaniu techniki Ajax zawartość jest aktualizowana bez konieczności ładowania przez przeglądarkę nowej strony
Technologia wykorzystywana przez Ajax Ajax nie jest językiem. Jest to konkretny sposób wykorzystywania istniejących języków do tworzenia bardziej interaktywnego doświadczenia WWW. Jest to kombinacja HTML-a (używanego do wyświetlania stron WWW), XML-a (używanego do wymiany danych pomiędzy skryptem po stronie serwera a stroną WWW) oraz języka JavaScript (wykorzystywanego do aktualizacji stron HTML oraz organizacji całego procesu). Fundamentalnym komponentem techniki Ajax jest obiekt XMLHttpRequest. Ułatwia on wymianę danych pomiędzy stroną WWW a skryptem na serwerze. Obiekt XMLHttpRequest jest obsługiwany przez większość aktualnych przeglądarek, a w przypadku przeglądarek starszych można użyć w jego miejsce innych obiektów (rysunek 17.3).
240
Rysunek 17.3. Ta funkcja języka JavaScript zwraca obiekt XMLHttpRequest używany w technice Ajax. Obsługuje on najbardziej aktualne przeglądarki, w tym IE 5 i 6
Ajax, RSS, SOAP i inne zastosowania języka XML Obiekt XMLHttpRequest wymienia dane pomiędzy stroną WWW a skryptem po stronie serwera w sposób asynchroniczny. Oznacza to, że przeglądarka nie jest wstrzymywana w trakcie oczekiwania na zwrócenie przez serwer zaktualizowanych danych. W konsekwencji wymiana danych odbywa się bez zakłócania wyświetlania lub innych funkcjonalności istniejącej strony. Po utworzeniu obiektu XMLHttpRequest wymagane są trzy kroki, aby mogła się odbyć wymiana danych (rysunek 17.4). Najpierw należy utworzyć „funkcję pobierania” (ang. retrieving function), która będzie wywoływana, kiedy serwer WWW będzie gotowy do wysłania zaktualizowanych danych. W tym celu wykorzystywana jest właściwość onreadystatechange. Rysunek 17.4. Ta funkcja języka JavaScript wykorzystuje obiekt XMLHttpRequest, aby zdefiniować strukturę dla komunikacji asynchronicznej. Kiedy serwer WWW jest gotowy, funkcja ProcessAjax jest wywoływana ze zaktualizowanymi danymi serwera WWW (xmlHttp.responseXML)
Po zadeklarowaniu funkcji pobierania, następnym krokiem jest określenie adresu URL skryptu po stronie serwera, co odbywa się za pomocą właściwości open. Finalną czynnością jest wysłanie do serwera żądania za pomocą właściwości send, która może posiadać zawartość, zmienne lub być pusta (null).
Użycie techniki Ajax
Rysunek 17.5. Funkcja SelectWonder() jest wywoływana, kiedy wybrany zostaje jakiś cud. Przesyła ona do funkcji RequestAjax() adres URL skryptu po stronie serwera z wartością (ang. value) opcji (ang. option) wybranego cudu
Rysunek 17.6. Funkcja ProcessAjax() jest wywoływana, kiedy dane są zwracane z serwera. Parsuje ona zwrócony dokument XML i wyświetla go na stronie według wskazówek
Strona HTML będzie również potrzebować funkcji ProcessAjax(), która jest wywoływana, kiedy dane są zwracane z serwera (rysunek 17.6). Parsuje ona dane XML zwrócone przez serwer i do wyświetlenia ich w wymagany sposób na stronie WWW wykorzystuje język JavaScript.
Wskazówki Nazwy przedstawionych w tym podrozdziale funkcji i parametrów zostały utworzone przez autora. Nie są to nazwy wymagane. Jedynym wyjątkiem jest funkcja XMLHttpRequest(). Zarówno sama funkcja, jak i jej właściwości muszą posiadać przedstawione nazwy. Zamieszczone tu przykłady można zobaczyć w działaniu na stronie autora: http://www.kehogo.com/ examples/wonders-ajax.html.
241
Podstawy technologii Ajax
Aby użyć tej podstawy techniki Ajax, strona HTML musi wywołać funkcję RequestAjax() przedstawioną na rysunku 17.4. To wywołanie musi zawierać adres URL skryptu po stronie serwera oraz dane, które mają być przetworzone (rysunek 17.5).
Rozdział 17.
Przykłady zastosowania techniki Ajax Technika Ajax wcale nie jest nowa. W rzeczywistości jej podstawowa koncepcja sięga roku 1996 (co w dobie internetu oznacza dawno temu). Termin „Ajax” został użyty po raz pierwszy w 2005 r. w eseju, którego autorem był Jesse James Garrett. Esej ten, wraz z wersją beta narzędzia proponowania słów kluczowych Google (ang. Google Suggest) wydaną przez Laboratoria Google, uważane są za czynniki, które spowodowały rozpowszechnienie się koncepcji Ajax. Poniżej przedstawiłem kilka przykładów zastosowania techniki Ajax w działaniu.
Przykłady zastosowania techniki Ajax
Narzędzie proponowania słów kluczowych Google
Rysunek 17.7. Po wpisaniu w pole wyszukiwania „visual q” Google podpowiada zestaw fraz do wyszukania
Koncepcją narzędzia proponowania słów kluczowych Google (które z czasem stało się wbudowaną funkcją standardowej usługi wyszukiwania Google) było wykorzystanie techniki Ajax do oferowania sugestii wyszukiwania na podstawie wpisywanych fragmentów fraz. Przy zastosowaniu techniki Ajax każdy wpisany w polu wyszukiwania znak jest przesyłany do serwera Google, a zwracane dane to (zazwyczaj) najbardziej popularne frazy wyszukiwania, wybrane na podstawie dotychczas wpisanego ciągu znaków (rysunek 17.7).
Filmweb: przyznawanie gwiazdek Choć nie jest to pierwsza strona wykorzystująca technikę Ajax do przekazywania danych, Filmweb (baza filmów) oferuje interfejs rankingu gwiazdkowego, który zdobył uznanie społeczności internetowej. Jeżeli jesteś zarejestrowanym użytkownikiem serwisu Filmweb, masz możliwość oceniania każdego filmu. Zanim jeszcze dokonasz swojej oceny, serwis wyświetla średnią ocenę użytkowników. Ocena ta jest wyświetlana za pomocą gwiazdek koloru czerwonego: im więcej gwiazdek, tym wyższa ocena (rysunek 17.8).
242
Rysunek 17.8. Osiem na dziesięć gwiazdek to średnia ocena tego filmu
Ajax, RSS, SOAP i inne zastosowania języka XML Najeżdżając wskaźnikiem myszy na skalę z gwiazdek, możesz wyświetlić opis, który informuje, co oznacza dana liczba gwiazdek (trzy gwiazdki: „Słaby”, siedem gwiazdek: „Dobry” itd.). Następnie, klikając konkretną gwiazdkę na skali, wydajesz własną ocenę danego filmu. Po kliknięciu gwiazdki informacja jest wysyłana do serwera Netflix za pomocą techniki Ajax, a poziom oceny jest aktualizowany. Wszystko to odbywa się bez konieczności odświeżania strony (rysunek 17.9).
Yahoo! Finance W poprzednim przykładzie wymiana danych za pomocą techniki Ajax była inicjowana przez użytkownika. Nie zawsze jest to jednak konieczne.
Kiedy podczas obrotu akcjami zmieniają się jakieś raportowane dane dotyczące danego notowania (cena, ruch cen, wolumen obrotu), informacje na stronie są aktualizowane. Ponownie, z uwagi na zastosowanie techniki Ajax, zmiana ta odbywa się bez konieczności odświeżania tej strony. Rysunek 17.9. Najechanie wskaźnikiem myszy na skalę gwiazdek powoduje wyświetlenie informacji o tym, co oznacza wskazana liczba gwiazdek. Dałem dziewięć gwiazdek, co oznacza, że uznałem film za rewelacyjny
Rysunek 17.10. Śledzenie notowań akcji firmy Apple Inc. na stronie notowań giełdowych Yahoo! Finance
243
Przykłady zastosowania techniki Ajax
W przypadku serwisu notowań giełdowych Yahoo! Finance (rysunek 17.10) oraz stron z notowaniami w wielu innych serwisach finansowych wymiana Ajax jest tylko jednokierunkowa, czyli od serwera do przeglądarki. Zdarzeniem inicjującym jest zakończenie transakcji dla obserwowanych notowań danej spółki giełdowej. (W niektórych przypadkach opóźnienie danych wynosi 20 minut, a w innym wszystko odbywa się w czasie rzeczywistym. Za każdym razem funkcjonalność jest jednak taka sama).
Rozdział 17. Na stronach serwisu Yahoo! Finance nowe dane podświetlane są migającym kolorowym tłem w celu wskazania zmiany notowań. Kolor zielony oznacza wzrost notowań, a kolor czerwony ich spadek (rysunek 17.11). Ma to zastosowanie do wszystkich danych na tej stronie, w tym także do głównych indeksów giełdowych, takich jak Dow Jones czy NASDAQ (rysunek 17.12).
Przykłady zastosowania techniki Ajax
Wskazówka Warto zauważyć, że Ajax stał się bardziej koncepcją niż konkretnym wykorzystaniem języków JavaScript i XML. Innymi słowy, deweloperzy stron WWW tworzą te same, wyglądające jak przy zastosowaniu techniki Ajax, doświadczenia po stronie użytkownika, bez wykorzystania samych technologii składających się na Ajax. W niektórych przypadkach język JavaScript został dla funkcjonalności po stronie klienta zastąpiony przez VBScript. Innym razem do wysyłania i odbierania danych asynchronicznie pomiędzy przeglądarką a serwerem wykorzystywane są ramki iFrame (serwis Google Mapy początkowo wykorzystywał ramki iFrame). Z kolei jeszcze w innych przypadkach dane przesyłane z serwera mogą mieć dowolną formę, od HTML-a po zwykły tekst, z całkowitym pominięciem XML-a.
Rysunek 17.11. W czasie rzeczywistym (o godz. 9:47 czasu wschodniego) cena akcji firmy Apple spadła do 485,14 dolarów za akcję, co daje w ujęciu dziennym spadek o 0,81%
Rysunek 17.12. Notowania indeksu NASDAQ wzrosły w ujęciu dziennym o 0,07%
244
Ajax, RSS, SOAP i inne zastosowania języka XML
Podstawy RSS RSS (ang. Really Simple Syndication) jest formatem plików, który umożliwia stronom WWW łatwe udostępnianie swoich zawartości czytelnikom. Dana zawartość jest pakowana w tzw. źródło RSS (ang. RSS feed) lub kanał RSS (ang. RSS channel) (rysunek 17.13). Aby przeglądać tę zawartość, należy subskrybować kanał RSS. Wtedy możesz przeglądać kanał RSS za pomocą czytnika kanałów RSS (ang. RSS Reader) albo agregatora kanałów RSS (ang. RSS Aggregator). Rysunek 17.13. To jest strona subskrypcji kanałów RSS w serwisie ekologicznej organizacji WWF. Kliknięcie linku klimat pokazuje zawartość tego źródła RSS i daje użytkownikowi opcję jego subskrypcji
Czytniki kanałów RSS również są powszechnie dostępne. Poza wieloma czytnikami, które możesz kupić lub pobrać bezpłatnie, zarówno Google, jak i Yahoo! oferują własne darmowe czytniki kanałów RSS. Nawet główne przeglądarki internetowe posiadają teraz wbudowane czytniki RSS, czyniąc subskrybowanie i przeglądanie kanałów RSS wygodniejszym niż kiedykolwiek wcześniej (rysunek 17.15). Po zasubskrybowaniu danego kanału RSS nie musisz już odwiedzać strony WWW oferującej ten kanał. Wystarczy po prostu otworzyć czytnik RSS i przeglądać najbardziej aktualną zawartość z tej strony, bazując na kanale, który subskrybujesz. Specyfikacja RSS ma ponad dziesięcioletnią historię obfitującą w różne wersje, w tym RSS 0.91, RSS 1.0 oraz RSS 2.0. Obecny trend skłania się ku RSS 2.0 i na tej wersji skupimy się w tej części rozdziału.
Wskazówka Wersję 2.0 specyfikacji RSS możesz znaleźć na stronie http://cyber.law.harvard.edu/rss/rss.html.
Rysunek 17.15. Podgląd źródła „WWF-Aktualności” w czytniku RSS przeglądarki Internet Explorer 8
245
Podstawy RSS
Rysunek 17.14. Subskrybując źródło RSS „WWFAktualności”, mogę skorzystać z własnego czytnika kanałów RSS lub skorzystać z czytnika wbudowanego w większość aktualnych przeglądarek internetowych
Format RSS i symbolizująca go pomarańczowa ikona stały się wszechobecne i pojawiają się wszędzie, od espn.com i nytimes.com, aż po praktycznie każdy prywatny blog. RSS umożliwia subskrypcję artykułów prasowych (rysunek 17.14), wydarzeń kalendarzowych, wpisów na blogach, podcastów, a nawet nowo załadowanych zdjęć, zwanych strumieniami zdjęć (ang. photostreams).
Rozdział 17.
Schematy RSS Format RSS 2.0 jest określony za pomocą XML-a. Oznacza to, że przy pisaniu dokumentu RSS mają zastosowanie wszystkie zasady dotyczące pisania dokumentów XML (patrz rozdział 1., „Pisanie dokumentów XML”). Elementem głównym pliku RSS jest rss (rss zapisane małymi literami, ponieważ w XML-u wielkość liter ma znaczenie). Posiada on atrybut version (wersja), a skoro chcemy użyć specyfikacji 2.0, wartość tego atrybutu musi wynosić „2.0” (rysunek 17.16).
Rysunek 17.16. Pliki RSS pisane są w XML-u. Elementem głównym pliku jest element rss, który posiada pojedynczy atrybut version
Element rss posiada jeden element-dziecko o nazwie channel (kanał). Jest to wymagany element, który zawiera
Schematy RSS
informacje opisujące źródło RSS. Posiada on trzy wymagane elementy-dzieci: title (tytuł), link (łącze) oraz description (opis) (rysunek 17.17). Ponadto posiada kilka opcjonalnych elementów-dzieci, w tym category (kategoria; element używany przez czytniki RSS do grupowania zawartości źródła) oraz image (obrazek; element zawierający adres URL obrazka wyświetlanego podczas prezentacji źródła RSS). Najbardziej istotnym elementem-dzieckiem elementu channel jest element item (pozycja). Choć jest on technicznie opcjonalny, to jeśli nie ma żadnych elementów item, nie ma żadnej zawartości w źródle. Element item, podobnie jak element channel, posiada trzy wymagane elementy-dzieci: title, link oraz description, które opisują zawartość danej pozycji (rysunek 17.18). Ponadto element ten posiada również opcjonalne elementy dzieci, w tym element enclosure (załącznik; element wskazujący powiązany z daną pozycją plik multimedialny, taki jak plik wideo lub audio).
Rysunek 17.17. Element rss ma jeden element-dziecko o nazwie channel, który z kolei posiada trzy elementydzieci (title, link i description) oraz inne opcjonalne elementy-dzieci. Element channel posiada zawartość dotyczącą samego źródła RSS
Wskazówka Nie istnieje żadna oficjalna przestrzeń nazw dla RSS 2.0. Ma to na celu zapewnienie wstecznej kompatybilności, tak aby pliki w wersjach 0.91 i 0.92 mogły być także poprawnymi plikami 2.0. Niektórzy użytkownicy piszą jednak własne schematy na podstawie tej specyfikacji. Przykłady możesz znaleźć na stronie http://www.thearchitect.co.uk/schemas/rss-2_0.xsd. Rysunek 17.18. Faktyczną zawartością źródła RSS jest element item, który jest elementem-dzieckiem elementu channel. Posiada on, podobnie jak element channel, trzy elementy-dzieci (title, link oraz description), a także inne opcjonalne elementy-dzieci
246
Ajax, RSS, SOAP i inne zastosowania języka XML
Rozszerzanie RSS Ponieważ RSS jest formatem XML, to ze swojej natury jest rozszerzalny. Wykorzystując tę rozszerzalność, przygotowano dodatkowe schematy XML, zwane modułami RSS. Rozszerzenia te, deklarowane za pomocą przestrzeni nazw XML, dodają do RSS różne funkcjonalności, bez modyfikowania jego podstawowej struktury. Nie wystarczy jednak rozszerzyć RSS. Czytnik kanałów RSS musi być świadomy tych rozszerzeń i wiedzieć, jak używać tych dodatkowych informacji. I chociaż można tworzyć nowe moduły, to tylko te, które zostaną uznane za interesujące lub istotne, skłonią deweloperów do aktualizacji ich czytników RSS. Poniżej przedstawiam trzy z szeroko stosowanych rozszerzeń RSS.
Moduł Media RSS Yahoo! Search opracowało moduł RSS zwany Media RSS. Moduł ten oferuje dodatkowe elementy i atrybuty dla lepszej obsługi plików multimedialnych w źródłach RSS (rysunek 17.19). Deklaracja przestrzeni nazw dla modułu Media RSS jest zdefiniowana jako xmlns:media="http://search.yahoo.com/mrss/".
Pod tym adresem można również znaleźć dokumentację dotyczącą tego modułu. Element media:content (zawartość) jest podstawowym elementem wprowadzonym przez ten moduł i jest zazwyczaj elementem-dzieckiem elementu item w RSS. Element ten posiada wiele opcjonalnych atrybutów, takich jak: url (adres url), type (typ), height (wysokość), width (szerokość), medium (rodzaj mediów), framerate (liczba klatek na sekundę) oraz duration (czas trwania).
Rysunek 17.20. Wyświetlone w przeglądarce źródło RSS strumienia zdjęć z rysunku 17.19
Moduł oferuje dodatkowe elementy opcjonalne, które zazwyczaj są również elementami-dziećmi elementu item. Niektóre z nich to media:title (tytuł), media:description (opis), media:keywords (słowa kluczowe), media:credit (informacje o twórcach), media:category (kategoria) oraz media:copyright (prawa autorskie). Ponadto niektóre z tych elementów posiadają również własne atrybuty.
247
Rozszerzanie RSS
Rysunek 17.19. Ten fragment kodu pochodzi ze źródła RSS dla zdjęć (strumienia zdjęć) z serwisu udostępniania zdjęć flickr.com. Plik RSS wykorzystuje moduł Media RSS w celu załączenia dodatkowych informacji na temat danego zdjęcia, takich jak autor zdjęcia oraz kilka kategorii, które są tagami serwisu flickr
Rozdział 17. Moduł blogChannel RSS Pierwszym dostępnym modułem RSS umożliwiającym rozszerzanie RSS 2.0 był moduł napisany przez Dave’a Winera, jednego z pionierów RSS. Moduł blogChannel RSS dodaje do RSS nowe elementy, oferując dodatkowe funkcjonalności blogerom i ich czytelnikom. Deklaracja przestrzeni nazw dla modułu blogChannel RSS jest zdefiniowana jako xmlns:blogChannel="http://backend.userland. com/blogChannelModule". Pod tym adresem
można również znaleźć dokumentację dotyczącą tego modułu. Cztery nowe elementy wprowadzone przez ten moduł są elementami-dziećmi elementu channel w RSS. Są to elementy: blogChannel:blogRoll, blogChannel:mySubscriptions, blogChannel:blink oraz blogChannel:changes.
Rysunek 17.21. Fragment źródła podcastowego RSS ze strony nature.com
Rozszerzanie RSS
Podcasting oraz iTunes Podcast, jak każde inne źródło RSS, jest stowarzyszoną grupą plików dostępnych do pobrania lub subskrypcji (rysunek 17.21). Dla źródła podcastowego możesz stosować standardowe czytniki RSS (rysunek 17.22), ale większość użytkowników korzysta z klientów podcastowych, z których najbardziej popularnym jest iTunes firmy Apple (rysunek 17.23). Poza standardem RSS istnieje przestrzeń nazw iTunes Podcasting, która lepiej obsługuje listy i pozycjonowanie w interfejsie iTunes. Deklaracja przestrzeni nazw iTunes Podcasting jest zdefiniowana jako
Rysunek 17.22. Wyświetlenie w czytniku RSS przeglądarki IE strumienia podcastu RSS z rysunku 17.21
xmlns:itunes="http://www.itunes.com/dtds/ podcast-1.0.dtd". Dokumentację na temat tej
przestrzeni nazw możesz znaleźć na stronie http://www.apple.com/itunes/whatson/podcasts/ specs.html. Nowe elementy często mogą być elementami-dziećmi elementów channel i item. Niektóre z tych nowych elementów to: itunes:author (autor), itunes:block (blok), itunes:duration (czas trwania), itunes:explicit, itunes:category (kategoria), itunes:subtitle (podpisy) oraz itunes:summary (podsumowanie).
248
Rysunek 17.23. Wyświetlenie w iTunes tego samego strumienia podcastu RSS, do którego odwołuje się rysunek 17.22
Ajax, RSS, SOAP i inne zastosowania języka XML
SOAP i usługi internetowe
Rysunek 17.24. Wrapper (czy też koperta) SOAP to w rzeczywistości dwa elementy: Envelope (koperta) i Body (treść główna). Zwróć uwagę, że element Envelope jest kwalifikowany za pomocą prefiksu soap12: przestrzeni nazw SOAP
Określenie SOAP (ang. Simple Object Access Protocol) oznacza protokół uzyskiwania szybkiego dostępu do obiektów. (Technicznie rzecz biorąc, przy wersji 1.2 ta definicja została zarzucona, jednak wiele osób wciąż jej używa). W każdym razie SOAP jest opartym na XML-u frameworkiem wymiany komunikatów. W taki sam sposób, w jaki użytkownik może żądać z serwera informacji o cenie akcji pewnej spółki lub stanie magazynowym jakiegoś produktu, SOAP obsługuje komunikację typu serwer-serwer. W szczególności umożliwia niezależną od platformy i języka programowania komunikację pomiędzy różnymi aplikacjami, działającymi zazwyczaj na innych serwerach. Wsparcie oferowane przez SOAP dla tego typu interoperacyjności uczyniło z tego frameworku część czegoś, co W3C nazywa usługą internetową (ang. Web Service). Usługa internetowa jest zbiorem funkcji dostępnych i możliwych do wykonania przez sieć. Choć definicja mówi o tym dość ogólnie, pojęcie usługi internetowej zazwyczaj odnosi się do wymiany komunikatów XML za pomocą frameworku SOAP.
Wymiana komunikatów SOAP najczęściej odbywa się przez internet za pośrednictwem protokołu HTTP. Aplikacja kliencka wysyła komunikat SOAP jako żądanie HTTP, a serwer odsyła swój komunikat SOAP jako odpowiedź HTTP. Ponieważ proces wymiany komunikatów SOAP wykorzystuje HTTP, umożliwia to łatwiejszą, niż to wcześniej było możliwe, komunikację pomiędzy komputerami znajdującymi się w różnych sieciach. Jest to jedna z największych przewag SOAP nad innymi frameworkami komunikacji zdalnej.
Wskazówka Specyfikację SOAP w wersji 1.2 możesz znaleźć na stronie http://www.w3.org/TR/soap12.
249
SOAP i usługi internetowe
Podstawową funkcją SOAP jest wsparcie dla tego typu wymiany komunikatów XML dla różnych aplikacji. SOAP jest lekkim protokołem, ponieważ w przeważającej części komunikat SOAP jest w zasadzie plikiem XML w opakowaniu SOAP. Opakowanie to (ang. wrapper), określane jako koperta SOAP (ang. SOAP envelope) (rysunek 17.24), dodaje niewielkie obciążenie do procesu przesyłania komunikatów.
Rozdział 17.
Schemat komunikatu SOAP Framework SOAP jest oparty na języku XML, co oznacza, że wszystkie zasady dotyczące pisania dokumentów XML mają zastosowanie do komunikatów SOAP. Elementem głównym komunikatu SOAP jest element Envelope (pisane wielką literą). Musi on deklarować przestrzeń nazw SOAP, która definiuje elementy i atrybuty komunikatu SOAP. Nie istnieje żaden standardowy prefiks dla tej przestrzeni nazw, więc zastosowałem prefiks soap12: (patrz rysunek 17.24).
Schemat komunikatu SOAP
Komunikat SOAP zawiera opcjonalny element Header (nagłówek), który — jeśli jest obecny — musi być pierwszym elementem-dzieckiem elementu Envelope. Umożliwia on charakterystyczną dla aplikacji komunikację pomiędzy klientem a serwerem, poza faktycznym komunikatem SOAP jako takim.
Rysunek 17.25. Ten komunikat żądania SOAP wywołuje procedurę sayHello i przekazuje parametr name z wartością „Kevin”
Element Body (treść główna) jest wymaganym elementem-dzieckiem elementu Envelope i mieści faktyczną zawartość komunikatu SOAP. W komunikacie żądania elementy-dzieci elementu Body odpowiadają wywoływanej operacji, a elementy-wnuki parametrom tej operacji (rysunek 17.25). W komunikacie odpowiedzi słowo „Response” jest zazwyczaj dodawane do elementów-dzieci elementu Body (elementów operacji), a jego elementy-wnuki są wartościami wynikowymi danej operacji (rysunek 17.26). Element Body musi być pierwszym lub drugim elementem-dzieckiem elementu Envelope – w zależności od tego, czy element Header będzie obecny.
Wskazówki Zwróć uwagę, że na rysunkach 17.25 i 17.26 elementy potomne elementu Body są kwalifikowane przestrzenią nazw za pomocą URI www.kehogo.com/ns/hello. Tak będzie z reguły, ponieważ elementy Twojej usługi internetowej prawdopodobnie nie będą należeć do przestrzeni nazw SOAP. Pokazane w tych przykładach usługi internetowe oparte na protokole SOAP możesz znaleźć na stronie internetowej autora: http://www.kehogo.com/examples/hello_world.asmx .
250
Rysunek 17.26. Ten komunikat SOAP jest odpowiedzią na komunikat żądania z rysunku 17.25. Zwraca on wynik procedury sayHello, wykorzystując element sayHelloResponse
Ajax, RSS, SOAP i inne zastosowania języka XML
WSDL
Rysunek 17.27. Element główny pliku WSDL zawiera deklaracje przestrzeni nazw dla WSDL i dla wiązania z SOAP. Przestrzeń nazw WSDL, jako domyślna przestrzeń nazw, nie wymaga stosowania prefiksu
Rysunek 17.28. W tym fragmencie kodu element portType definiuje operację sayHelloRequest tej usługi internetowej. Operacja ta przewiduje komunikat wejściowy o treści hello_in, a w odpowiedzi zwróci komunikat o treści hello_out. Obydwa te komunikaty zdefiniowane zostały w kolejnym przykładzie
WSDL (ang. Web Services Description Language), czyli język opisu usług internetowych, jest językiem XML, który służy do opisywania sposobu łączenia się z usługami internetowymi. Tam, gdzie SOAP zapewnia framework wymiany komunikatów dla usługi internetowej, WSDL dokumentuje komunikaty, które mogą być wysyłane. WSDL nie jest wymagany przy wymianie komunikatów usług internetowych — proces ten może odbywać się wyłącznie z wykorzystaniem SOAP. Jednak przy zastosowaniu WSDL aplikacje wysyłające żądania otrzymują techniczne informacje na temat danej usługi internetowej, dzięki czemu wymiana komunikatów jest łatwiejsza, bardziej zautomatyzowana i mniej podatna na błędy.
Schemat WSDL WSDL jest dokumentem XML, a jego elementem głównym jest definitions (definicje; pisane małymi literami). Musisz zadeklarować przestrzeń nazw WSDL oraz jego wiążącą przestrzeń nazw dla SOAP. Konieczne może być również zadeklarowanie przestrzeni nazw XML Schema oraz przestrzeni nazw, w której zdefiniowałeś elementy dla swojej usługi internetowej (rysunek 17.27).
Elementy types i message ściśle ze sobą współpracują (rysunek 17.29). Element message określa, jakich komunikatów wymaga każda operacja oraz jakie parametry będzie zawierał każdy komunikat. Parametry te odwołują się do elementów zdefiniowanych dla Twojej usługi internetowej, a ich definicje można znaleźć w elemencie types. Rysunek 17.29. Elementy types definiują elementy sayHelloRequest i sayHelloResponse (niepokazany) wykorzystywane przez daną usługę internetową. Te elementy XML są parametrami w komunikatach, odpowiednio: hello_in i hello_out
251
WSDL
Elementy definitions posiadają pięć głównych elementów-dzieci (w sekwencji): types (typy), message (komunikat), portType (typ portu), binding (wiązanie) oraz service (usługa). Centralnym punktem wśród tych elementów jest portType. Opisuje on dostępne operacje oraz komunikaty przewidywane dla każdej operacji (rysunek 17.28). Element ten jest równoważny z opisem biblioteki aplikacji, a każda operacja zawiera ekwiwalent listy wywołań określonych funkcji.
Rozdział 17. Element binding definiuje protokół transportowy dla wymiany komunikatów SOAP (co zazwyczaj odbywa się za pomocą protokołu HTTP, ale można również wykorzystać SMTP, FTP lub inne protokoły transportowe). Następnie dla każdej nazwanej operacji definiujesz, w jaki sposób komunikat ma pojawiać się w elemencie body SOAP. Zastosowanie na przykład instrukcji use="literal" oznacza konieczność użycia zdefiniowanych w schemacie elementów z elementu types WSDL (rysunek 17.30). Wreszcie element service zbiera w całość poszczególne fragmenty usługi internetowej, łącząc element portType (zdefiniowany na rysunku 17.28) z elementem binding (zdefiniowanym na rysunku 17.30). Ponadto definiuje też publiczne URI samej usługi internetowej (rysunek 17.31).
UDDI Ostatnim elementem czegoś, co uznawane jest za trzy standardy usługi internetowej, jest UDDI (ang. Universal Description, Discovery, and Integration). UDDI zostało napisane jako oparty na XML-u rejestr opartych na protokole SOAP usług internetowych. Rejestr ten zapewnia wysyłającym żądania aplikacjom informacje dotyczące plików WSDL, odpowiadających konkretnym usługom.
Rysunek 17.30. Ten element binding wskazuje na zastosowanie w wymianie komunikatów SOAP protokołu HTTP. Ponadto wskazuje, że element body SOAP będzie zawierał zdefiniowane w XML Schema elementy pochodzące z elementu types WSDL
WSDL
Rejestr publiczny, zwany rejestrem biznesowym UDDI (ang. UDDI Business Registry — UBR), został opublikowany w 2000 r. Został on stworzony jako dowód koncepcji, z intencją ulepszenia specyfikacji UDDI oraz aplikacji wykorzystujących tę specyfikację. W styczniu 2006 r. główni zwolennicy UBR ogłosili, że Rysunek 17.31. Element service łączy elementy nie będą dłużej publikować w tym rejestrze. Pozostając portType i binding, definiując publiczne przy oferowaniu usług internetowych wewnętrznie oraz wykorzystanie danej usługi internetowej swoim klientom, organizacje te uznały, że rejestr UBR spełnił swoje zadanie. Od tego czasu rejestr się zdezaktualizował.
Wskazówki Plik WSDL z tych przykładów (i odpowiadające mu usługi SOAP) możesz znaleźć na stronie internetowej autora: http://www.kehogo.com/examples/hello_world.wsdl. W tym podrozdziale wykorzystano język WSDL w wersji 1.1. Jego specyfikacja dostępna jest na stronie http://www.w3.org/TR/wsdl, a jego XML Schema na stronie http://schemas.xmlsoap.org/wsdl/. W czerwcu 2007 r. organizacja W3C opublikowała wersje 2.0, ale na jej pozytywne przyjęcie trzeba jeszcze poczekać.
252
Ajax, RSS, SOAP i inne zastosowania języka XML
Podstawy KML
Rysunek 17.32. Zbliżenie w interfejsie Google Earth na obszar Morza Śródziemnego
Anotacja map z wykorzystaniem pliku KML (jak pliku XML) może być wykonywana ręcznie w edytorze XML. Bardziej prawdopodobne jest jednak, że będziesz generował pliki KML za pomocą jednego z narzędzi kartograficznych KML. W takim przypadku najpierw anotuje się mapę w aplikacji Google Earth lub za pomocą aplikacji online Google Mapy: http://maps.google.com/ (rysunek 17.33). Następnie wygenerowany przez dane narzędzie plik KML jest kopiowany do edytora tekstowego i zapisywany z rozszerzeniem .kml. Jeśli chcesz, możesz edytować ten plik, aby uzyskać jeszcze większą kontrolę nad elementami anotacji, które zostały wygenerowane przez użyte narzędzie. Istnieją też inne aplikacje wykorzystujące KML. Możesz na przykład geoznakować (dodawać do czegoś informacje geograficzne) swoje zdjęcia w serwisie udostępniania zdjęć flickr.com. Następnie możesz udostępniać te zdjęcia za pomocą KML. Kiedy taki plik KLM jest przeglądany, każde geoznakowane zdjęcie jest umieszczane w danej lokalizacji na mapie (rysunek 17.34).
Wskazówki Aplikację Google Earth możesz pobrać ze strony http://earth.google.com/. KML w wersji 2.2 jest oficjalnym standardem OGC (ang. Open Geospatial Consortium), międzynarodowej organizacji standaryzacyjnej podobnej do W3C. Na stronie http://www.opengeospatial.org/standards/kml możesz znaleźć więcej informacji na temat tej wersji i pobrać jej specyfikację.
Rysunek 17.34. Geoznakowane zdjęcie z serwisu flickr.com
253
Podstawy KML
Rysunek 17.33. Znacznik miejsca oraz wielokątny obrys posągu Zeusa w Olimpii zrobiony za pomocą Google Maps
KML (ang. Keyhole Markup Language) jest językiem znaczników XML służącym do anotacji map za pomocą oznaczeń miejsc, wielokątnych obrysów, ścieżek, opisów itp. Został on początkowo opracowany do zastosowania z aplikacją Google Earth (aplikacją często używaną na komputerach osobistych) (rysunek 17.32). Od tego czasu został on zaadoptowany do wykorzystania przez wiele innych aplikacji związanych z mapami.
Rozdział 17.
Prosty plik KML Głównym elementem pliku KML jest element kml (zapisany małymi literami). W ramach tego elementu głównego deklarowana jest przestrzeń nazw kml i zazwyczaj odbywa się to bez prefiksu kml:.
Oznaczenia miejsc Najbardziej typową anotacją używaną w plikach KML jest znacznik miejsca (ang. placemark). Jest on najczęściej prezentowany graficznie za pomocą pinezki wyznaczającej lokalizację. Użyty w ten sposób element Placemark często będzie posiadał elementy-dzieci: name (nazwa) i Point (punkt; element ten określa długość i szerokość geograficzną oraz wysokość nad powierzchnią w danym punkcie na mapie) (rysunek 17.35).
Prosty plik KML
Znaczniki miejsc mogą również być stylizowane za pomocą elementu styleURL, który może odwoływać się do adresu URL dokumentu stylów klm lub wplecionego w kod stylu zdefiniowanego za pomocą elementu Style. W obydwu przypadkach element Style będzie dla każdego stylizowanego obiektu posiadał elementy-dzieci, takie jak IconStyle lub PolyStyle (użyte w przykładzie 17.37). W ramach każdego stylu obiektu mogą występować elementy-dzieci, takie jak color (kolor), scale (skala), icon (ikona) i inne. Poza symbolem pinezki, znacznikami miejsc mogą być linie, obrysy wielokątne, a nawet obiekty 3D. Element obrysu wielokątnego (Polygon) musi posiadać element-dziecko wyznaczający zewnętrzne granice obrysu (outerBoundaryIs), który zawiera długość i szerokość geograficzną oraz wysokość co najmniej czterech punktów, tworząc tym samym zamknięty kształt. Ponadto, jak już wyżej wspomniano, obrysy wielokątne mogą być stylizowane za pomocą elementu PolyStyle (rysunek 17.37).
Rysunek 17.35. Plik KML z elementem Placemark
Rysunek 17.36. Plik wynikowy KLM z przykładu 17.35 wyświetlony za pomocą aplikacji Google Earth
Rysunek 17.37. Ten fragment kodu dodaje do znacznika miejsca style purpurowego wieloboku dla piramidy i zielonej strzałki zamiast domyślnej żółtej pinezki
Wskazówki XML Schema dla języka KLM możesz znaleźć na stronie http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd. Szczegółowy plik KLM dla wszystkich cudów starożytności możesz znaleźć na stronie http://www.kehogo.com/examples/wonders.kml. Możesz przeglądać ten plik w aplikacji Mapy Google lub wpisać wskazany adres URL bezpośrednio w pole wyszukiwania tej aplikacji.
254
Rysunek 17.38. Plik wynikowy KML z przykładu 17.36 wyświetlony za pomocą aplikacji Google Earth
Ajax, RSS, SOAP i inne zastosowania języka XML
ODF i OOXML Zarówno ODF (ang. Open Document format), jak i OOXML (ang. Office Open XML) są formatami plików dla dokumentów biurowych, takich jak arkusze kalkulacyjne, prezentacje, pliki tekstowe itd. Oba formaty powstały w dużych korporacjach i od tej pory są publikowane jako otwarte standardy przez organizacje takie jak W3C. Oba standardy tworzą podział pomiędzy zawartością a prezentacją i przechowują te elementy w osobnych plikach. W konsekwencji pojedynczy dokument wygenerowany przez któryś z tych formatów jest w rzeczywistości skompresowany i zawiera kilka plików oraz folderów. Poza danymi binarnymi, takimi jak obrazki i dźwięk, formatem dla tych plików jest XML. Fakt, że aplikacje biurowe mogą przechowywać swoje dane w formacie XML, ma przełomowe znaczenie. Zamiast formatów komercyjnych, używanych jeszcze kilka lat temu. takie dane są teraz przechowywane w otwartym, niezależnym platformowo formacie. Zapewnia to większą dostępność do bazowych danych i otwiera możliwości tworzenia innych uzupełniających narzędzi i aplikacji.
ODF
Rysunek 17.39. Plik content.xml z paczki ODF. Ten plik, razem z innymi plikami XML z paczki, tworzy dokument tekstowy, którego zawartością jest tekst „Witaj, świecie!”
ODF pakuje swoje pliki i foldery, wykorzystując do tego celu format plików JAR. Poza plikami danych, informacje z każdego dokumentu są przechowywane w jednym z kilku plików XML, a plik content.xml mieści faktyczną zawartość (rysunek 17.39). Istnieje wiele aplikacji obsługujących standard ODF. Oczywiście ODF jest domyślnym formatem dla pakietu OpenOffice.org. Ponadto szerokie wsparcie dla tego standardu zapewniają takie aplikacje jak Lotus Symphony, WordPerfect oraz Dokumenty Google.
255
ODF i OOXML
W roku 2002 firma Sun Microsystems rozpoczęła współpracę z OASIS (międzynarodową organizacją standaryzacyjną) w celu stworzenia otwartego standardu opartego na formacie XML wykorzystywanym przez OpenOffice.org (pakiet biurowy na licencji open source). W roku 2005 ODF zostało zatwierdzone jako standard organizacji OASIS, a w roku 2006 stało się standardem ISO (ang. International Organization for Standardization), czyli Międzynarodowej Organizacji Normalizacyjnej.
Rozdział 17. OOXML W roku 2005 firma Microsoft ogłosiła, że rozpocznie współpracę z Ecma International (organizacją standaryzacyjną) w celu stworzenia otwartego standardu opartego na formacie XML użytym w pakiecie Office 2003. W roku 2006 OOXML zostało zatwierdzone jako standard Ecma (ponad 6 tysięcy stron specyfikacji!), a w roku 2008 stało się standardem ISO. OOXML pakuje swoje pliki i foldery, wykorzystując w tym celu format plików ZIP. W przeciwieństwie do ODF, informacje z każdego dokumentu są przechowywane w różnie nazwanych plikach XML, na podstawie niestandardowego języka znaczników, w którym zostały zapisane, np. WordProcessingML (rysunek 17.40), SpreadsheetML, PresentationML i innych. Na rynku dostępnych jest wiele aplikacji obsługujących OOXML. Oczywiście OOXML jest domyślnym formatem pakietu Office 2007. WordPerfect oferuje szerokie wsparcie dla OOXML, a pakiet iWork firmy Apple oferuje wsparcie umożliwiające jedynie odczyt plików w tym formacie. Dostępny jest również OpenXML Writer, czyli edytor tekstowy na licencji open source, stworzony specjalnie do współpracy z OOXML.
ODF i OOXML
Porównanie standardów i związane z nimi kontrowersje Powstały pewne kontrowersje dotyczące procesu, w którym OOXML stało się standardem ISO. W internecie znaleźć możesz różne opinie zwolenników każdego z tych dwóch standardów. Możesz również znaleźć tam informacje na temat tego, który standard „zwycięży” (lub czy w ogóle zostanie wyłoniony zwycięzca). Wiele osób uważa, że skoro OOXML jest silnie powiązane z pakietem Microsoft Office, ODF ma twardy orzech do zgryzienia. Inni twierdzą, że specyfikacja OOXML jest tak rozdęta (prawie osiem razy dłuższa niż specyfikacja ODF), że tworzenie zgodnych z nią aplikacji i narzędzi jest po prostu niewygodne. Bez względu na to, co się stanie, zmiana bazowego modelu danych na XML z pewnością spowoduje istotne zmiany w rozwoju aplikacji biurowych.
256
Rysunek 17.40. Dokument document.xml z paczki OOXML. Podobnie jak w przykładzie 17.39, plik ten, wraz z innymi plikami XML z tej paczki, tworzy dokument tekstowy, którego zawartością jest tekst „Witaj, świecie!”. Chociaż możliwe, że będziesz w stanie zrozumieć oba te pliki, to jednak nie zalecam podejmowania prób ich ręcznego tworzenia
Ajax, RSS, SOAP i inne zastosowania języka XML
eBook, ePub itp. Rysunek 17.41. Zawartość pliku mimetype. Ten plik nigdy się nie zmienia i zawsze musi być pierwszym plikiem w skompresowanym pliku ePub
Rysunek 17.42. To jest plik container.xml. Element rootfile określa ścieżkę do pliku, który opisuje strukturę eBooka. Choć możesz zmienić zawartość tego pliku (co nie jest możliwe w przypadku pliku mimetype), właściwie nie w tym żadnego celu, chyba że zdecydujesz się przeorganizować pozostałe pliki
W roku 1971 Michael Hart zaczął udostępniać bezpłatnie elektroniczne wersje książek należących do powszechnego dziedzictwa, w tym Biblii oraz dzieł Szekspira i Marka Twaina. Od tego czasu dzięki wizji Harta (Projekt Gutenberg) zgromadzono ponad 25 000 bezpłatnych książek elektronicznych. Książki elektroniczne (zwane też ebookami lub eBookami) to książki w postaci plików elektronicznych w miejsce tradycyjnej formy papierowej. EBooki można czytać na komputerach osobistych lub za pomocą specjalnych czytników eBooków, oferujących funkcje takie jak „zaginanie” rogów stron, podświetlanie zawartości książki czy wyszukiwanie pojęć w dołączonym słowniku. I choć rynku eBooków nie można porównać z rynkiem książek drukowanych na papierze, przemysł ten rośnie gwałtownie.
ePub
Skompresowany plik ePub zawiera kilka wymaganych plików i jeden wymagany folder. Pierwszy z wymaganych plików musi mieć nazwę mimetype i zawierać dokładnie jeden wiersz tekstu (pokazany na rysunku 17.41), opisujący typ MIME danego pliku ePub. Musi on być dosłownie pierwszym plikiem skompresowanego pliku ePub. Inaczej dany plik ePub nie zostanie uznany za poprawny. Jeden wymagany folder nosi nazwę META-INF i musi zawierać plik XML o nazwie container.xml (rysunek 17.42). Jego zadaniem jest wskazanie czytnikowi eBooków, gdzie znajduje się plik opisujący strukturę danego eBooka. Informacja ta znajduje się w atrybucie full-path elementu rootfile.
257
eBook, ePub itp.
Poza zwykłym tekstem, eBooki mogą być publikowane w wielu różnych formatach i z pewnością rozpoczęła się już wojna na formaty. Jednym z formatów, który uzyskał szerokie wsparcie w przemyśle publikacji elektronicznych, jest ePub. Jego specyfikacja jest otwartym standardem działającej na tym rynku organizacji standaryzacyjnej IDPF. ePub, jako format oparty na XML-u, wykorzystuje dla zawartości książek XHTML-a, a dla struktury książek XML-a. Ponadto, podobnie jak w przypadku pakietów biurowych, pliki ePub są kompresowane za pomocą formatu ZIP i w takiej postaci są dostarczane odbiorcom.
Rozdział 17. Plik container.xml, folder META-INF oraz plik mimetype są utworzone zgodnie z jedną z trzech podspecyfikacji formatu ePub. Jest to podspecyfikacja OCF (ang. OEBPS Container Format), która jest wywiedziona z formatu Open eBook. Plik, do którego odwołuje się container.xml opisujący strukturę eBooka, jest często nazywany content.opf. Jest on tworzony zgodnie z kolejną z trzech podspecyfikacji ePub, OPF (ang. Open Package Format). Ten plik .opf jest wymagany i zawiera następujące elementy: metadata (element zawierający metadane na temat eBooka), manifest (element zawierający listę wszystkich plików skompresowanego pliku ePub) oraz spine (element określający kolejność, w jakiej pliki mają być prezentowane) (rysunek 17.43).
eBook, ePub itp.
W większości przypadków istnieje również plik .ncx, który zawiera spis treści. Odwołania do tego pliku znajdują się w atrybucie toc elementów manifest i spine. Plik ten zawiera elementy związane z tytułem i autorem oraz element navMap, który opisuje kolejność odtwarzania (rysunek 17.44). Ostatnim z wymaganych plików jest zawartość samego eBooka, która jest zorganizowana według trzeciej podspecyfikacji, OPS (ang. Open Publication Structure). Można to zrobić na dwa sposoby: w postaci pojedynczego pliku z zakładkami zawierającymi poszczególne rozdziały albo każdy rozdział może być osobnym plikiem. Zawartość jest zazwyczaj napisana w XHTML-u w wersji 1.1 (bez formularzy, map obrazów po stronie serwera, zdarzeń i skryptów) i może korzystać z podzbioru CSS 2.1.
Rysunek 17.43. Plik content.opf opisuje strukturę eBooka oraz pliki, które on zawiera
Wskazówka Format ePub jest otwartym standardem, na który składają się trzy inne standardy IDPF. Informacje na temat wszystkich trzech standardów możesz znaleźć na stronie http://www.idpf.org/2007/ops/OPS_2.0_final_spec.html.
Rysunek 17.44. Ten plik .ncx to zasadniczo niektóre metadane eBooka oraz oraz spis treści, który może wykorzystywać hiperłącza
258
Ajax, RSS, SOAP i inne zastosowania języka XML
Narzędzia dla XML-a w praktyce Poza edytorem XML i przeglądarką istnieje jeszcze kilka innych narzędzi, które będą użyteczne podczas pracy nad przykładami zamieszczonymi w tym rozdziale. Uwaga! Jeśli będziesz chciał tworzyć własne przykłady, ta lista jest nieadekwatna. Więc jeśli nie jesteś majsterkowiczem, zalecam poszukanie odpowiedniej książki lub przewodnika online.
Ajax Aby zobaczyć technikę Ajax w akcji, zapoznaj się z przykładami zamieszczonymi w tej książce lub znajdującymi się na mojej stronie internetowej. Jeśli chcesz edytować te przykłady lub tworzyć własne, będziesz potrzebował edytora HTML/JavaScript. Będziesz również potrzebował serwera WWW, na którym uruchomisz utworzone przez siebie pliki HTML i JavaScript. Korzystanie z języka skryptowego (takiego jak .asp) nie jest wymagane, ale zazwyczaj w ten sposób tworzy się skrypty po stronie serwera.
RSS
Jeśli chcesz tworzyć własne źródła RSS, będziesz potrzebował na początek edytora XML. Będziesz również potrzebował serwera WWW, na którym uruchomisz swoje źródło RSS. Jako punkt wyjścia prawdopodobnie będziesz chciał wykorzystać jeden z przykładów zamieszczonych w książce (lub dostępnych w internecie), a następnie go wyedytować. Kiedy uznasz, że jesteś gotowy, możesz przeprowadzić walidację swojego źródła na stronie http://aggregator.userland.com/validator.
SOAP i WSDL Aby zapoznać się w praktyce z SOAP lub WSDL, będziesz potrzebował aplikacji klienckiej. Niektóre z edytorów XML wymienionych w dodatku A obsługują SOAP i WSDL. Możesz również użyć bezpłatnego narzędzia online, takiego jak http://www.soapclient.com/soaptest.html. Wtedy będziesz mógł skorzystać z przykładów ze strony WWW autora.
259
Narzędzia dla XML-a w praktyce
Aby przyjrzeć się, jak działa RSS, możesz skorzystać z czytnika kanałów RSS wbudowanego w przeglądarkę (większość aktualnych przeglądarek posiada taki czytnik). Możesz również skorzystać ze spersonalizowanych stron głównych Yahoo! (http://my.yahoo.com/) lub Google (http://www.google.com/ig), albo po prostu pobrać z internetu jakiś czytnik kanałów RSS.
Rozdział 17. Aby stworzyć usługę internetową, skorzystałem z szablonu Microsoft .NET Web Service, a następnie zmodyfikowałem go za pomocą edytora. Szablony usług internetowych dostarczają również inne języki skryptowe.
KML Aby podejrzeć, jak działa plik KLM, pobierz aplikację Google Earth http://earth.google.com/. Następnie wykorzystaj przykłady z mojej strony WWW. Jeśli chcesz edytować moje przykłady lub tworzyć własne, skorzystaj z aplikacji Mapy Google, Google Earth lub edytuj bezpośrednio w edytorze XML.
ODF i OOXML
Narzędzia dla XML-a w praktyce
Aby sprawdzić, jak wewnętrznie funkcjonuje plik ODF i OOXML, będziesz musiał stworzyć własny dokument. W przypadku ODF jedną z opcji jest wykorzystanie pakietu biurowego, który możesz pobrać ze strony http://www.openoffice.org/. Opcje dostępne dla OOXML to pakiet Microsoft Office 2007 lub OpenXML Writer dostępny na stronie http://www.openxml.biz/OpenXMLWriter.html. Kiedy utworzysz już plik w jednym z tych formatów, zmień nazwę jego rozszerzenia na .zip. Następnie otwórz ten plik za pomocą aplikacji do otwierania plików ZIP. Po otwarciu zobaczysz, że zawiera on kilka plików XML opisanych w tym rozdziale i będziesz mógł wyodrębnić i przejrzeć je wszystkie.
ePub Aby odczytać książkę w pliku ePub, musisz pobrać eBooka w formacie ePub oraz czytnik eBooków, taki jak Mobipocket Reader dostępny na stronie http://www.mobipocket.com/en/DownloadSoft/ lub Adobe Digital Editions dostępny na stronie http://www.adobe.com/products/digitaleditions/. Aby zbadać wewnętrzne mechanizmy działania pliku ePub (podobnie jak w przypadku formatów ODF i OOXML), zmień nazwę jego rozszerzenia na .zip i otwórz go za pomocą odpowiedniej aplikacji do plików ZIP, aby zobaczyć jego zawartość. Możesz wyodrębnić i przejrzeć wszystkie jego pliki składowe. Możesz również wyedytować dowolny plik i zobaczyć zmiany w czytniku eBooków. W tym celu po wyedytowaniu ponownie skompresuj zawartość pliku ePub za pomocą aplikacji ZIP, a następnie zmień nazwę rozszerzenia na .ePub.
260
Dodatki
D
Dodatki
Dodatek A
Narzędzia XML
263
Dodatek B
Zestawy znaków i encje
269
261
Rozdział x.
262
Narzędzia XML
A
Dodatek A Narzędzia XML Kiedy przygotowane zostało pierwsze wydanie tej książki, wiele osób pisało dokumenty XML za pomocą prostych edytorów tekstu, takich jak Notatnik dla platformy Windows czy TextEdit dla Macintosha. Następnie w celu przeprowadzenia walidacji lub przekształcenia dokumentów XML używano wiersza poleceń lub aplikacji online, co niekonieczne było łatwe i wpisywało się zbyt dobrze w procedury biznesowe. Na szczęście wszystko się zmieniło. Przede wszystkim aktualne przeglądarki internetowe (w tym Mozilla Firefox, Internet Explorer, Opera i Safari) oferują wsparcie dla XML-a i XSLT. Masz również możliwość wyboru spośród dziesiątek edytorów XML, które możesz pobrać z internetu i od razu wykorzystać. Wiele z tych edytorów jest bezpłatnych, a niektóre z nich są naprawdę dobre. Większość obecnych edytorów XML może przeprowadzać walidację dokumentów XML względem DTD i XML Schema oraz przetwarzać XML za pomocą arkuszy stylów XSLT. Ponadto większość tych edytorów oferuje dodatkowe funkcje, w tym wsparcie dla XSLT 2.0/XPath 2.0, XSL-FO, XQuery itd.
263
Narzędzia XML
Ten dodatek nie stanowi wyczerpującej listy dostępnych obecnie edytorów XML i narzędzi. A ponieważ jest możliwe, że pominięto jakiś dobry edytor lub narzędzie, albo któreś z nich ukazało się dopiero niedawno, będę utrzymywał aktualizowaną listę edytorów i narzędzi na mojej stronie internetowej związanej z tą książką.
Dodatek A
Edytory XML Minimalne wymagania, jakie musi spełniać edytor XML, aby został umieszczony na tej liście, są następujące: możliwość sprawdzania, czy dokument XML jest poprawny składniowo, walidacja względem DTD i XML Schema, wykonywanie przekształceń XSLT oraz wsparcie dla zestawu znaków Unicode (dla fragmentów w przykładach zapisanych w języku greckim). Jeśli żaden z wymienionych tutaj edytorów nie spełnia Twoich wymagań, w podrozdziale „Dodatkowe edytory XML” znajdziesz jeszcze kilka innych doskonałych edytorów. Funkcja
XML Copy Editor EditiX XML Editor
Altova XMLSpy oXygen XML Editor
Windows
Tak
Tak
Tak
Macintosh
Tak
Tak
Nie
Tak
Unix/Linux
Tak
Tak
Nie
Tak
Wersja bezpłatna
Tak
Tak
Wersja komercyjna
Nie
Tak
2
Tak
Podgląd XSLT
Nie
Tak
3
Tak
3
Obsługiwane systemy operacyjne: 1
Obsługa XSL-FO
Nie
Tak
Obsługa XSLT 2.0/XPath 2.0
Nie
Tak
Tak
Nie
Nie 2
Tak Tak
Tak
Tak
Tak
Tak
Obsługa XQuery 1.0
Nie
Tak
Tak
Tak
Obsługa SOAP/WSDL
Nie
Nie
Tak
Tak
Automatyczne uzupełnianie
Tak
Tak
Tak
Tak
Formatowanie dokumentu
Tak
Tak
Tak
Tak
Zwijanie-rozszerzanie XML
Tak
Nie
Tak
Tak
Wyszukiwanie i podstawianie Podstawowe
Tak
Tak
Tak
Tak
Dla wielu dokumentów
Tak
Nie
Tak
Tak
Wewnątrz folderów
Edytory XML
Nie
Nie
Tak
Tak
Sprawdzanie pisowni
Tak
Nie
Tak
Tak
Podgląd zawartości w formie tabeli lub drzewa
Nie
Tak
Tak
Tak
Automatyczne tworzenie DTD
Nie
Tak
3
Tak
Tak
Automatyczne tworzenie XML Schema Nie
Tak
3
Tak
Tak
Konwersja DTD na XML Schema
Nie
Tak
Tak
Tak
Konwersja XML Schema na DTD
Nie
Nie
Tak
Nie
Generowanie próbek z DTD
Nie
Tak
2
Tak
Nie
Generowanie próbek z XML Schema
Nie
Tak
2
Tak
Tak
Szablony nowych plików
Tak
Tak
Tak
Tak
1. Aplikację należy skompilować z kodu źródłowego. 2. Komercyjna wersja jest dostępna na bezpłatny okres próbny. 3. Te funkcje są dostępne tylko w wersji komercyjnej.
264
2
Narzędzia XML XML Copy Editor
Altova XMLSpy
URL: http://xml-copy-editor.sourceforge.net
URL: http://www.altova.com/xmlspy.
Obsługiwane systemy operacyjne: Windows, Unix/Linux, Macintosh (należy skompilować z kodu źródłowego).
Obsługiwane systemy operacyjne: Windows.
Wersja: 1.2.0. Wersja bezpłatna: tak. Dodatkowe funkcje: Przetwarzanie plików o wielkości ponad 10 MB z odpowiednią szybkością. Import z programu Microsoft Word i eksport do programu Microsoft Word.
Wersja: 2008, wydanie 2. Wersja bezpłatna: nie (wersja komercyjna ma bezpłatną wersję próbną). Dodatkowe funkcje: Obsługa Open XML/Open Document. Porównywanie plików XML. Edytor WSDL oraz klient/debuger SOAP. Edytor/debuger/program profilujący XQuery.
Blokowanie znaczników XML.
Edytor/debuger/program profilujący XSLT 1.0/2.0.
Walidacja RELAX NG.
Walidacja RELAX NG.
Walidacja w tle.
Integracja z relacyjną bazą danych/bazą danych XML.
Więcej informacji znajdziesz na stronie: http://xml-copy-editor.sourceforge.net/ index.php?page=features.
Więcej informacji znajdziesz na stronie: http://www.altova.com/matrix_x.html.
EditiX XML Editor URL: http://www.editix.com. Obsługiwane systemy operacyjne: Windows, Unix/Linux, Macintosh. Wersja: 2008, Service Pack 5.
oXygen XML Editor URL: http://www.oxygenxml.com. Obsługiwane systemy operacyjne: Windows, Unix/Linux, Macintosh. Wersja: 9.3. Wersja bezpłatna: nie (wersja komercyjna ma bezpłatną wersję próbną).
Dodatkowe funkcje:
Dodatkowe funkcje:
Edytory XML
Wersja bezpłatna: tak (oraz wersja komercyjna).
Obsługa Open XML/Open Document.
Obsługa Open XML/Open Document.
Porównywanie plików XML.
Porównywanie plików XML.
Generator dokumentacji DTD/XML Schema.
Edytor WSDL oraz klient/debuger SOAP.
Konstruktor/edytor XPath.
Edytor/debuger/program profilujący XQuery.
Edytor/debuger XSLT.
Edytor/debuger/program profilujący XSLT 1.0/2.0.
Więcej informacji znajdziesz na stronie: http://www.editix.com/features.html.
Walidacja RELAX NG. Integracja z relacyjną bazą danych/bazą danych XML. 1. Więcej informacji znajdziesz na stronie: http://www.oxygenxml.com/feature_matrix.html.
265
Dodatek A
Dodatkowe edytory XML XMLwriter XML Editor URL: http://www.xmlwriter.net. Obsługiwane systemy operacyjne: Windows. Wersja: 2.7. Wersja bezpłatna: nie (wersja komercyjna ma bezpłatną wersję próbną). Dodatkowe funkcje: Więcej informacji znajdziesz na stronie: http://www.xmlwriter.net/xmlwriter/features.shtml.
Stylus Studio URL: http://www.stylusstudio.com. Obsługiwane systemy operacyjne: Windows. Wersja: wydanie 2. Wersja bezpłatna: nie (wersja komercyjna ma bezpłatną wersję próbną). Dodatkowe funkcje:
Dodatkowe edytory XML
Więcej informacji znajdziesz na stronie: http://www.stylusstudio.com/xml_feature_overview.html.
Liquid XML Studio URL: http://www.liquid-technologies.com. Obsługiwane systemy operacyjne: Windows. Wersja: 2008 (v6). Wersja bezpłatna: tak (oraz wersja komercyjna). Dodatkowe funkcje: Więcej informacji znajdziesz na stronie http://www.liquid-technologies.com/ Product_XmlStudio_Features.aspx.
266
WMHelp XMLPad URL: http://www.wmhelp.com/xmlpad3.htm. Obsługiwane systemy operacyjne: Windows. Wersja: 3.0.2a. Wersja bezpłatna: tak. Funkcje dodatkowe: Więcej informacji znajdziesz na stronie http://www.wmhelp.com/xmlpad32.htm.
XMLmind XML Editor URL: http://www.xmlmind.com/xmleditor. Obsługiwane systemy operacyjne: Windows, Unix/Linux, Macintosh. Wersja: 4.1. Wersja bezpłatna: tak (oraz wersja komercyjna). Dodatkowe funkcje: Więcej informacji znajdziesz na stronie http://www.xmlmind.com/xmleditor/features.html.
Narzędzia XML
Narzędzia i zasoby XML Ta lista narzędzi XML jest tylko próbką tego, co możesz znaleźć w internecie. Specyfikacje są zamieszczone w takiej kolejności, w jakiej pojawiają się w książce.
Narzędzia do konwersji i walidacji Walidator XML: http://www.stg.brown.edu/service/xmlvalid/. Walidator DTD: http://www.validome.org/grammar. Walidator XML Schema: http://www.w3.org/2001/03/webdata/xsv. Konwersja XML na DTD/XML Schema; konwersja DTD na XML Schema: http://www.hitsw.com/xml_utilities/.
Specyfikacje XML 1.0: http://www.w3.org/TR/xml/. XSLT 1.0: http://www.w3.org/TR/xslt. XPath 1.0: http://www.w3.org/TR/xpath. XSL-FO (to samo co XSL 1.1): http://www.w3.org/TR/xsl/.
XML Schema: http://www.w3.org/TR/xmlschema-0/. Przestrzenie nazw XML: http://www.w3.org/TR/xml-names/. XSLT 2.0: http://www.w3.org/TR/xslt20/. XPath 2.0: http://www.w3.org/TR/xpath20/. XQuery 1.0: http://www.w3.org/TR/xquery/.
267
Narzędzia i zasoby XML
DTD (w ramach specyfikacji XML): http://www.w3.org/TR/xml/.
Dodatek A
268
Zestawy znaków i encje
B
Dodatek B Zestawy znaków i encje [RS1] Dokument XML może zawierać dowolne znaki z całego zestawu znaków Unicode. Ten zestaw znaków (odpowiadający standardowi ISO/IEC 10646) jest uniwersalnym zestawem znaków (ang. universal character set — UCS) i reprezentuje niemal wszystkie znaki ze wszystkich znanych obecnie języków.
Metoda przechowywania znaków z danego zestawu znaków jest zwana kodowaniem znaków (ang. character encoding). Jeśli Twój dokument XML i aplikacja, której używasz do jego wyświetlenia, nie korzystają z tego samego kodowania znaków, wtedy to, co wpisujesz, może zostać inaczej wyświetlone. Aby tego uniknąć, możesz określić kodowanie znaków w swoim dokumencie. Wtedy, jeśli aplikacja służąca do wyświetlania dokumentu obsługuje to kodowanie, znaki zostaną wyświetlone w oczekiwany sposób.
Znaki nadal nie są wyświetlane poprawnie? Nawet po zdefiniowaniu kodowania znaków w dokumencie XML lub przy wprowadzaniu znaków za pomocą numerycznych odwołań znakowych, znaki nadal mogą nie być poprawnie wyświetlane. Przyczyną może być to, że Twój system operacyjny nie obsługuje Unicode lub — co bardziej prawdopodobne — czcionka, z której korzystasz, nie może wyświetlać tego konkretnego znaku Unicode.
Jeśli to nie zadziała, istnieją jeszcze dwa inne sposoby uzyskania poprawnej reprezentacji znaków. Jednym z nich jest zastosowanie numerycznych odwołań znakowych (ang. numeric character references — NCR), które są krótkimi sekwencjami cyfr reprezentującymi znaki Unicode. Przykładowo sekwencja Δ reprezentuje literę (delta) z alfabetu greckiego. Innym sposobem jest zastosowanie encji, które są unikatowymi „słowami” reprezentującymi znaki Unicode. W języku XML istnieje pięć predefiniowanych encji (patrz rozdział 1., podrozdział „Encje predefiniowane — pięć znaków specjalnych”), takich jak >, która tworzy > (znak większości). Poza tymi opcjami, encje można tworzyć za pomocą DTD (patrz rozdział 7., „Encje i notacje w dokumentach DTD”).
269
Zestawy znaków i encje
W większości przypadków możesz po prostu wpisać dany znak w dokumencie XML i zostanie on wyświetlony w oczekiwany sposób. Jeśli jednak chcesz użyć akcentów, znaków z języka obcego lub znaków specjalnych, może być nieco inaczej. Jest to spowodowane tym, że nie wszystkie aplikacje komputerowe przechowują informacje o znakach w ten sam sposób.
Dodatek B
Określanie sposobu kodowania znaków Chociaż wszystkie dokumenty XML korzystają z zestawu znaków Unicode, sposób kodowania znaków w dokumencie XML nie jest z góry ustalony.
Aby określić sposób kodowania znaków: 1. Po numerze wersji w deklaracji XML wpisz encoding=.
Określanie sposobu kodowania znaków
2. Następnie wpisz "kodowanie_znaków", gdzie kodowanie_znaków określa sposób kodowania znaków, jaki chcesz zastosować w swoim dokumencie XML (rysunek B.1).
Rodzaje kodowania znaków ASCII. W roku 1963 opublikowany został standard kodu ASCII (ang. American Standard Code for Information Interchange). Kod ten mapuje angielski alfabet, cyfry, znaki interpunkcyjne i inne symbole (w tym zestaw znaków niedrukowalnych) na wartości od 0 do 127. Umożliwia to przechowywanie kodowania ASCII w siedmiu bitach pamięci komputera. ANSI. Standard kodu instytutu ANSI (ang. American National Standards Institute) poszerzył ASCII o znaki z języków europejskich. Uwaga! Windows „ANSI” odwołuje się do zestawu znaków firmy Microsoft, a nie do standardu ANSI. ISO-8859-1. Międzynarodowa Organizacja Normalizacyjna (ang. International Organization for Standardization — ISO) wraz z Międzynarodową Komisją Elektrotechniczną (ang. International Electrotechnical Commission — IEC) również rozszerzyła standard ASCII o dodatkowe znaki. Powstały standard jest podzielony na kilka części reprezentujących różne grupy językowe, takich jak ISO-8859-1 (Latin-1/zachodnioeuropejski), ISO8859-5 (Latin/cyrylica), ISO-8859-8 (Latin/hebrajski) itd. UTF-8. Ośmiobitowy format transformacji (ang. Unicode Transformation Format) jest kodowaniem znaków, które może reprezentować znaki w zestawie Unicode, wykorzystując w tym celu od jednego do czterech bajtów. Uwaga! UTF-16 również reprezentuje dowolne znaki z zestawu Unicode, z tym wyjątkiem, że wykorzystuje w tym celu szesnastobitowe „słowa”.
270
Rysunek B.1. Określiłem tutaj, że sposobem kodowania znaków dla danego dokumentu XML jest UTF-8
Zestawy znaków i encje
Używanie numerycznych odwołań znakowych Zgodnie z projektem Unicode współdzieli swoje pierwsze 127 znaków z ASCII. Oznacza to, że każdy znak ASCII może być wpisany bezpośrednio w Twoim dokumencie XML z klawiatury działającej pod kontrolą dowolnego systemu. Każdy znak Unicode powyżej 128 może również być wpisany, ale możesz wtedy napotkać problemy z kodowaniem znaków. Zamiast tego możesz jednak użyć numerycznych odwołań znakowych, aby umieścić te znaki w swoim dokumencie.
Aby użyć (dziesiętnego) numerycznego odwołania znakowego: 1. Wpisz . 2. Następnie wpisz n;, gdzie n jest liczbą dziesiętną, która odpowiada wymaganemu znakowi Unicode (rysunek B.2). (Informacje na temat wszystkich znaków Unicode znajdziesz w punkcie „Wskazówki” w dalszej części tego podrozdziału).
Aby użyć (szesnastkowego) numerycznego odwołania znakowego: 1. Wpisz . (Zwróć uwagę na dodatkowy znak „x”). 2. Następnie wpisz h;, gdzie h jest liczbą szesnastkową, która odpowiada wymaganemu znakowi Unicode.
Wskazówki
Rysunek B.3. Znaki alfabetu greckiego wpisane w dokumencie XML nie wyświetlają się poprawnie z uwagi na konflikt pomiędzy kodowaniem znaków ISO-8859-1 a Unicode. Jednak grecka nazwa Kolosa Rodyjskiego, zapisana za pomocą numerycznych odwołań znakowych, jest wyświetlana zupełnie poprawnie
Numeryczne odwołania znakowe zostaną przetłumaczone na ich bazowe liczby Unicode (zwane również punktami kodu), bez względu na ustawienia dotyczące kodowania znaków dla danego dokumentu XML (rysunek B.3). Listę punktów kodu dla każdego znaku Unicode znajdziesz na stronie http://www.unicode.org/charts. W tabeli zamieszczonej na końcu tego dodatku znajdziesz listę znaków kodu Unicode odpowiadających najpopularniejszym spośród nietypowych liter języków europejskich oraz symboli. Aby przekonwertować dziesiętne numeryczne odwołania znakowe z powrotem na Unicode, możesz wpisać je w pole wyszukiwania Google.
271
Używanie numerycznych odwołań znakowych
Rysunek B.2. Zastąpiłem frazę odpowiednimi punktami kodu Unicode. Zwróć też uwagę, że zamiast UTF-8 lub UTF-16 określiłem kodowanie znaków ISO-8859-1. Zrobiłem to, aby udowodnić tezę z poprzedniego przykładu
Dodatek B
Korzystanie z referencji encji XML posiada pięć predefiniowanych encji dla znaków o szczególnym znaczeniu. Są to: & (dla znaku et: &), < (dla znaku mniejszości: <), > (dla znaku większości: >),
Rysunek B.4. Plik xhtml-symbol.ent, pobrany ze strony organizacji W3C, załączyłem do mojego dokumentu DTD
" (dla podwójnego cudzysłowu: "), ' (dla pojedynczego cudzysłowu lub apostrofu: ').
Korzystanie z referencji encji
Bez tych encji przeznaczenie każdego z tych znaków w dokumencie XML mogłoby być mylnie odczytane. Możesz również za pomocą DTD zadeklarować własne encje, tak jak zostało to omówione w rozdziale 7., „Encje i notacje w DTD”. Ponadto możesz skorzystać z zestawu encji zdefiniowanych dla HTML-a i XHTML-a, stosując publiczne referencje DTD lub pobierając te pliki ze strony www.w3.org/TR/xhtml1/#h-A2 i włączając je do swoich dokumentów DTD (rysunek B.4).
Aby użyć referencji encji: 1. Wpisz &. 2. Następnie wpisz nazwa_encji;, gdzie nazwa_encji jest nazwą encji odpowiadającej wymaganemu znakowi Unicode (rysunek B.5).
Rysunek B.5. W tym fragmencie kodu XML użyłem encji XHTML dla większości znaków w greckiej nazwie Kolosa Rodyjskiego. Nie ma jednak encji zdefiniowanej dla znaku (omikron z tonacją), więc zamiast tego użyłem numerycznego odwołania znakowego ό
Wskazówki Referencje encji zostaną przetłumaczone na ich bazowe punkty kodu Unicode, bez względu na ustawienia dotyczące kodowania znaków dla danego dokumentu XML (rysunek B.6). Publiczne referencje DTD nie są obsługiwane we wszystkich przeglądarkach. Chociaż zestaw encji HTML/XHTML jest obszerny, nie jest nawet w przybliżeniu na tyle duży, aby reprezentować cały zestaw znaków Unicode.
Rysunek B.6. W dokumencie XML z rysunku B.5 nie ma zdefiniowanego kodowania znaków. W takim przypadku procesor XML ustawia kodowanie znaków na podstawie własnej konfiguracji. Mimo wszystko referencje encji wyświetlają się prawidłowo
272
Zestawy znaków i encje
Znaki Unicode Poniżej przedstawiam niektóre ciekawe znaki Unicode wraz z ich numerycznymi odwołaniami znakowymi (NCR) oraz referencjami encji XHTML. Ta tabela przedstawia zaledwie fragment wszystkich referencji encji XHTML i mniej niż jedną tysięczną całego zestawu znaków Unicode. Zestaw tabel w formacie PDF obejmujących cały zestaw znaków Unicode możesz znaleźć na stronie http://www.unicode.org/charts/.
Znak NCR NCR Referencja Unicode (dziesiętne) (szesnastkowe) encji
Znak NCR NCR Referencja Unicode (dziesiętne) (szesnastkowe) encji
à
à
à
à
α
α
α
á
á
á
á
β
β
β
β
â
â
â
â
γ
γ
γ
γ
ã
ã
ã
ã
δ
δ
δ
δ
ä
ä
ä
ä
ε
ε
ε
ε
α
å
å
å
ζ
ζ
ζ
ζ
æ
æ
æ
η
η
η
η
ç
ç
ç
ç
θ
θ
θ
θ
è
è
è
è
ι
ι
ι
ι
é
é
é
é
κ
κ
κ
κ
ê
ê
ê
ê
λ
λ
λ
λ
ë
ë
ë
ë
μ
μ
μ
μ
ì
ì
ì
ì
ν
ν
ν
ν
í
í
í
í
ξ
ξ
ξ
ξ
î
î
î
î
ο
ο
ο
ο
ï
ï
ï
ï
π
π
π
π
ñ
ñ
ñ
ñ
ρ
ρ
ρ
ρ
ò
ò
ò
ò
σ
σ
σ
σ
ó
ó
ó
ó
τ
τ
τ
τ
ô
ô
ô
ô
υ
υ
υ
υ
õ
õ
õ
õ
φ
φ
φ
φ
ö
ö
ö
ö
χ
χ
χ
χ
ø
ø
ø
ø
ψ
ψ
ψ
ψ
ù
ù
ù
ù
ω
ω
ω
ω
ú
ú
ú
ú
™
™
™
™
û
û
û
û
©
©
©
©
ü
ü
ü
ü
¢
¢
¢
¢
œ
œ
œ
œ
£
£
£
£
§
§
§
§
¥
¥
¥
¥
273
Znaki Unicode
å æ
Dodatek B
274
Skorowidz
S
Spis treści
&, 32, 110 &apos, 32 &apost, 110 >, 32, 68, 110 <, 32, 68, 110 ", 32, 110
A
Skorowidz
absolute location path, 57 adnotacja, 136 Ajax, 15 jako koncepcja, 244 narzędzia, 259 podstawy technologii, 240 użycie, 241 wykorzystywana technologia, 240 zastosowanie, 242 Altova XMLSpy, 265 ancestor nodes, 56 anonimowy typ niestandardowy, 144 anotacja map, 253 znacznik miejsca, 254 ANSI, 270 anyType, 156 aplikacja biurowa przechowywanie danych w formacie XML, 255 aplikacja komputerowa przechowywanie znaków, 269 aplikacja XML, 21 argument default, 174 fixed, 174 n, 140 arkusz stylów XSLT inicjowanie, 40 kolejność przetwarzania, 58 odwołania, 38 szablon, 39 uproszczony, 203 załączenie reguł XML Schema, 209
ascending, 50 ASCII, 270 aspekt, 146 enumeracji, 148 maksimów, 147 minimów, 147 wzorca, 150 xs:enumeration, 148 xs:fractionDigits, 152 xs:length, 149 xs:list itemType, 153 xs:maxExclusive, 146 xs:maxInclusive, 146 xs:maxLength, 149 xs:minExclusive, 147 xs:minInclusive, 147 xs:minLength, 149 xs:pattern, 150 xs:totalDigits, 152 xs:union memberTypes, 154 Asynchronous JavaScript and XML, 15, 240 atomic value, 213 atrybut, 22, 24, 102 a przestrzenie nazw, 186 background, 85 border, 85 break-before, 87 column-count, 88 column-gap, 88 default, 143 definicja, 103 definiowanie, 172 dodawanie, 29 elementFormDefault, 193 elementu regionu, 88 elementu-rodzica dziedziczenie, 82 ENTITY, 116 exclude-result-prefixes, 206 extent, 85 fixed, 143
275
Skorowidz
Skorowidz atrybut font-size, 82 form, 193 grupy definiowanie, 175 odwołania, 176 height, 51 href, 51 ID, 106 instrukcje, 106 wartość, 106 IDREF, 107 IDREFS, 107 informacje o informacjach, 102 jezyk, 102 liczby całkowite, 73 margin, 85 master-name, 85 master-reference, 85 match, 58 zwracanie węzłów, 65 maxOccurs, 161, 163, 169 wartości, 162, 163 method, 205 format XML, 86 minOccurs, 161, 169 wartości, 162 mixed, 166 nazwa, 26, 29 NMTOKEN, 108 ograniczanie do nazw XML, 108 predefiniowanie zawartości, 174 przechowywanie danych, 96 referencje do encji nieparsowanej, 116 scale-to-fit, 83 select, 208 stosowanie szablonów, 53 węzeł bieżący, 58 zwracanie węzłów, 65 space-after, 82 span, 88 src, 51 statusy opcjonalne, 103 target, 51 targetNamespace, 194 toc, 258 typ prosty, 139 version, 203, 246 wartość, 23, 24, 29 domyślna, 104 generowanie z dokumentu, 51 początkowa, 174
276
węzła wybieranie, 62 width, 51 wskazywanie zawartości, 174 wyjściowy, 51 wykorzystanie, 102 wymaganie, 173 wymuszenie braku, 173 xmlns, 183 xsi:noNamespaceSchemaLocation, 135 z wartościami unikatowymi, 106 odwołania, 107 z wyborami, 105 zakres lokalny, 186 attribute axis, 62 autotekst, 32
B baza danych natywna, 235 z obsługą XML-a, 235 białe znaki, 24 atrybuty NMTOKEN, 108 binding sequence, 218 blok, 82 podział kolumnowy, 88 zawartości strony, 82 nadawanie stylu, 82 błędy duchy, 125 składniowe, 28, 30 body region, 81 boolean expressions, 63
C Castro Elizabeth, 43 CDATA typ atrybutu, 103 Character Data, 33 character encoding, 269 child elements, 22 child nodes, 56 complex type, 132, 155 container.xml, 257 content model, 160 content type, 158 content.opf, 258 context node, 57 CSS, 82 current node, 57
Skorowidz custom markup language, 21 czas Greenwich, 141 czcionka rozmiary, 82
D
Skorowidz
dane data i czas, 140 nieparsowane, 114 typy, 132 określanie, 138 wejściowe parsowanie z wykorzystaniem wyrażeń regularnych, 223 typu nie-XML, 223 znakowe, 103 default, 143 Definicja Schematu XML, 131 definicja typu dokumentu, 93 deklaracja typu dokumentu, 123 XML, 22, 25 xsl:function, 207 descendant nodes, 56 descending, 50 div, 70 Document Type Definition, 14 dodawanie, 70 wartości węzłów, 76 dokument DTD, 94 a przestrzenie nazw, 197 atrybuty ograniczenie, 108 encje ogólne, 111 zewnętrzne, 112 obsługa wielu dokumentów XML, 100 tworzenie, 121 wady i zalety, 128 wewnętrzny deklarowanie i tworzenie, 124 zewnętrzny deklarowanie, 123 publiczny, 126, 127 tworzenie, 122 dokument RSS, 246 dokument XML analiza zawartości, 37 atrybuty ID, 106
białe znaki, 24 deklaracja, 25 drzewo węzłów, 38 elementy kwalifikowane, 191 proste i złożone, 132 encje, 32 korzystanie, 111 encje nieparsowane wstawianie, 117 formatowanie, 37 dla celów wydruku, 37 hierarchiczna reprezentacja, 38 kodowanie znaków, 270 komentarz, 31 narzędzia, 21 podział danych na fragmenty, 28 poprawność, 23, 123 powiązany zbiór, 122 powiązanie z arkuszem stylów, 38 przekształcanie, 37 atrybuty wyjściowe, 51 za pomocą XSLT, 38 przestrzenie nazw, 189 przetwarzanie wyodrębnianie fragmentów, 74 przykład, 12, 22 reguły DTD, 94 spójność, 93 sprawdzenie zgodności narzędzia, 94 walidacja względem DTD, 125 wartość atrybutu, 23 wewnętrzne i zewnętrzne DTD, 124 wiązanie z dokumentem XML Schema, 135 wielkość liter, 23 wybieranie zbioru węzłów, 63 zasada pisania, 23 zestawy znaków i encji, 269 znaki specjalne, 32 dokument XML Schema, 133 dodawanie adnotacji, 136 przestrzenie nazw, 189, 195 i lokalizacji, 189 rozpoczynanie, 134 struktura, 196 wiązanie z dokumentem XML, 135 dokument XQuery, 227 źródło, 228
277
Skorowidz
Skorowidz dokument XSL-FO akapity i nagłówki, 82 dodawanie obrazków, 83 struktura, 80 szablon główny, 86 tworzenie, 81 za pomocą XSLT, 86 dokument XSLT łączenie z XSL-FO, 86 przekształcanie dokumentu XML, 38 dokumenty wynikowe generowanie, 204, 205 drzewo węzłów, 38, 56 reprezentacja, 38 XML, 212 DTD, 14, 93 atrybuty deklarowanie, 103 obsługujące wybory, 105 element instancje, 99 o dowolnej zawartości, 101 pusty, 96 zawierający element-dziecko, 97 zawierający kilka elementów-dzieci, 98 zawierający tekst, 95 encje, 109 parametryczne, 118 liczba wystąpień definiowanie, 99 referencje do encji nieparsowanych, 116 publiczne, 272 sprawdzanie formatów, 94 wady i zalety, 128 walidacja i używanie, 121 wewnętrzne, 121 deklaracje, 124 wybory, 100 zewnętrzne, 121 dtd.uri, 123 dyrektywa przetwarzania XML, 228 xml-stylesheet, 228 dzielenie, 70 z resztą, 70
E eBook, 257 struktura, 258 Ecma International, 256
278
EditiX XML Editor, 265 edytory XML, 21, 264 element, 24 all, 162 ATTLIST, 103, 116 bez prefiksu, 185 binding, 252 Body, 250 category, 246 channel, 246 definiowanie, 101 PCDATA, 95 wyborów, 100 definitions, 251 description, 246 długość dokładna, 149 maksymalna, 149 minimalna, 149 ograniczenie, 149 DOCTYPE, 123 domyślna przestrzeń nazw, 183 dziecko, 22 nazwa, 27 sekwencja, 98 tworzenie, 27 wartości stylu, 82 wcięcia, 28 ELEMENT, 95 enclosure, 246 ENTITY, 118 Envelope, 250 fo:block, 80, 81, 82 fo:external-graphic, 83 fo:flow, 80, 89 fo:layout-master-set, 80, 81, 84 fo:page-number, 87 fo:page-sequence, 80, 81, 85, 89 fo:region-after, 87 fo:region-before, 85 fo:region-body, 80, 81 fo:root, 80, 84 fo:simple-page-master, 80, 81, 89 fo:static-content, 85 globalny, 177 odwołanie, 168 główny, 22, 23 tworzenie, 26 Header, 250 hexBinary, 149 image, 246 informacje wyświetlane, 102
Skorowidz wartość adres URL, 117 wyizolowanie zasięgu, 177 wyjściowy atrybuty i wartości, 51 wykomentowana sekcja, 31 wyświetlanie jako tekst, 33 wzorzec określanie, 150 xs:all, 162 xs:annotation, 136 xs:attributeGroup, 175 xs:choice, 163 xs:complexContent, 157 xs:complexType, 158, 159 xs:documentation, 136 xs:element, 138 xs:extension, 164, 167 xs:group, 170 xs:import, 195 xs:include, 194, 195 xs:restriction, 164, 167 xs:schema, 134 xs:simpleContent, 157 xsl:apply-templates, 52, 53, 86, 203 xsl:attribute, 88 xsl:choose, 48 xsl:for-each, 46, 47 xsl:for-each-group, 208 xsl:import-schema, 209 xsl:sort, 50, 219 xsl:stylesheet, 86 xsl:text, 60 xsl:value-of, 44, 46 z zawartością mieszaną, 166 prostą, 156 złożoną, 156 zagnieżdżanie, 23, 28 zawierający tekst, 95 wyłącznie tekst, 164 złożony, 156 z typów prostych, 154 znaczniki, 24 em, 82 encja.uri, 112, 115 encje, 32, 109 &, 272 &apos, 272 >, 272
Skorowidz
item, 246 kml, 254 kwalifikowany, 191 limit cyfr, 152 link, 246 literalny, 39, 42 lokalny, 168, 177 dodawanie, 192 łączenie w grupy, 170 manifest, 258 margin, 80 media:content, 247 message, 251 metadata, 258 navMap, 258 nazwa, 26 nierezydujący, 183 NOTATION, 114 outerBoundaryIs, 254 page-height, 80 page-width, 80 Point, 254 Polygon, 254 PolyStyle, 254 położenie, 26, 27 portType, 251 predefiniowanie zawartości, 143 prefiks przestrzeni nazw, 184 oznaczanie, 185 przydzielanie typu danych, 132 pusty definiowanie, 96 stosowanie, 30 typ złożony, 165 znaczniki, 23 regionu, 80 rodzic, 26 definiowanie, 97 rss, 246 sekwencja definiowanie liczby wystąpień, 99 service, 252 spine, 258 Style, 254 styleURL, 254 title, 246 typ prosty, 132 definiowanie, 138 typ złożony, 132, 155 rodzaje, 132 types, 251
279
Skorowidz
Skorowidz encje <, 272 ", 272 nieparsowane, 114 definiowanie, 115 referencje, 116 wstawianie do dokumentu XML, 117 zawartość, 115 ogólne, 109 korzystanie, 111 tworzenie, 110 ogólne wewnętrzne, 110 ogólne zewnętrzne korzystanie, 113 tworzenie, 112 parametryczne, 109 a grupy atrybutów, 176 a nazwana grupa modelowa, 170 tworzenie i wykorzystanie, 118 zewnętrzne, 119 parsowane, 114 predefiniowane, 32, 272 referencja nazwy, 110 referencje, 272 reprezentacja tekstu, 110 znaków Unicode, 269 udostępnianie, 113 zawartość w pliku zewnętrznym, 112 zdefiniowane, 110 znormalizowana lista, 113 enclosed expressions, 227 enumeration, 148 ePub, 257 narzędzia, 260 podspecyfikacje, 258 etykieta, 138, 144 eXtensible Markup Language, 11 eXtensible Stylesheet Language, 14
F facets, 146 false, 77 Filmweb przyznawanie gwiazdek, 242 finalne drzewo wynikowe, 205 Fitzgerald Michael, 151 fixed, 143 formalny identyfikator publiczny, 126
280
format czasu, 140 czasu trwania, 140 daty, 140, 141 dnia, 141 ePub, 257 miesiąca, 141 pakietu Office 2007, 256 pliku dla dokumentów biurowych, 255 ZIP, 256 roku, 141 RSS, 245 ułamki sekund, 141 xs:gYearMonth, 141 formatowanie liczb, 72 FPI, 126 funkcja |, 77 agregująca, 215 analyze-string(), 223 avg(), 214 ceiling(), 73, 207 ciągów, 77 collection(), 235 contains(ciąg1, ciąg2), 77 count(), 71, 214, 215 current-date(), 221 current-dateTime(), 221 current-group(), 208 current-time(), 221 distinct-values(), 219 do modyfikacji ciągu znaków, 75 doc(), 228, 229 exists(), 218 floor(), 73 format-date(), 221 format-dateTime(), 221 format-number, 212 format-number(), 72 zaokrąglanie liczby, 73 formatowanie ciągu znaków, 216 liczb, 70 format-time(), 221 id(id_ciągu), 77 last(), 69 logiczna, 77 lower-case(), 216 match(), 223
Skorowidz
G general entities, 109 geoznakowanie, 253 ghost errors, 125 Google Earth, 253 Google Suggest, 15, 242 grafika.uri, 83 group value, 208 grupa modelowa, 160 nazwana definiowanie, 170 odwołanie, 171
wyboru, 163 xs:all, 162 xs:sequence, 161
H HTML, 11, 240 dokument, 22 element główny, 26 uniwersalność, 15 HyperText Markup Language, 11
I identyfikator notacji NDATA, 115 IEC, 270 iFrame, 244 in, 82 informacje identyfikujące, 106 instrukcja #FIXED, 104 #IMPLIED, 103 #REQUIRED, 103 (#PCDATA), 95 (dziecko), 97 (dziecko1, 98 *, 60 –//, 126 +//, 126 ANY, 101 elementy-dzieci, 101 attributeFormDefault, 192 declare function, 234 dwie kropki, 61 elementFormDefault, 192 EMPTY, 96 encoding, 270 exclude-result-prefixes, 206 form, 193 group-by, 208 href, 205 IDREF, 107 ISO//, 126 method, 204 nazwa_typu_niestandardowego, 145 NMTOKEN, 108 odwołanie do definicji typu dokumentu, 123 pojedyncza kropka, 59 PUBLIC, 127 ref, 168, 171
Skorowidz
matching-substring(), 223 max(), 215 min(), 215 name(), 77 name(zbiór_węzłów), 77 normalize-space(), 77 normalize-space(ciąg1), 77 not(wyrażenie), 77 pobierania, 241 position(), 69 ProcessAjax(), 241 replace(), 223 RequestAjax(), 241 reverse, 213 round(), 73 string-length(), 77 string-length(ciąg1), 77 substring(s,f,n), 74 substring-after(), 74, 219 substring-before(), 74 sum(), 76, 214, 215 tokenize(), 223 translate(), 75, 216 typograficzna XSL-FO, 88 unparsed-text(), 223 upper-case(), 216 węzłów, 77 wyznaczanie wartości minimalnej, 215 zaokrąglanie liczb, 73 funkcje UDF opcjonalne parametry wejściowe, 207 przestrzeń nazw, 206 rekurencyjne, 207 richter, 234 tworzenie, 206 w XQuery, 234 wywoływanie, 207
281
Skorowidz
Skorowidz instrukcja schemaLocation, 195 select, 45 standalone, 113, 117 SYSTEM, 112, 123 targetNamespace, 188 test, 48 type, 138 use, 173 value, 146 wynikowa, 204 xmlns, 191 xmlns:prefiks, 184, 190, 191, 198, 206 xmlns:xsi, 189 xsi:schemaLocation, 189 xsl:apply-templates, 58 xsl:attribute, 51 xsl:choose, 49 xsl:for-each, 226 xsl:for-each-group, 208 xsl:function, 206 xsl:if, 49 xsl:matching-substring, 223 xsl:non-matching-substring, 223 xsl:output, 42, 204 xsl:param, 206 xsl:result-document, 204, 205 xsl:sort, 208 xsl:validation, 209 xsl:version, 203 instrukcja przetwarzania, 23, 25 xml-stylesheet, 38 instrukcje_notacji, 114 integer, 132 internal general entities, 110 ISO, 126 ISO-8859-1, 270 iTunes, 248
J JavaScript, 240 jednolity identyfikator zasobu, 113 wskaźnik zasobu, 113 język opisu usług internetowych, 251 silnie typizowany, 212 składu, 79 ścieżek XML, 55
282
XML zasada opracowania, 102 wyrażeń regularnych, 150 znaczników niestandardowych, 21
K Keyhole Markup Language, 253 klauzula for, 231, 233 join, 231 let, 231 złączenie, 231 order by, 230 złączenie, 231 return, 230, 231 where, 230, 233 klucz_grupowania, 208 KML narzędzia, 260 plik, 254 podstawy, 253 wykorzystanie, 253 źródło, 253 kod językowy w standardzie ISO, 126 ukrycie fragmentu, 31 załączanie HTML i JavaScript, 33 kodowanie znaków, 269 rodzaje, 270 kolumna zawartość strony, 88 komentarz, 31, 136 w XPath 2.0, 222 w XQuery, 227 komponent XML Schema, 190 kwalifikowane, 192 podział na pliki, 194 przestrzeń nazw domyślna, 190 odwołania, 190 z prefiksem, 190 załączanie, 194 komunikacja asynchroniczna, 241 typu serwer-serwer, 249 komunikat odpowiedzi, 250 SOAP, 249, 250 protokół transportowy, 252 żądania, 250
Skorowidz konstruktor elementów, 227 kontener, 57 kontrola liczby wystąpień, 169 nad zawartością elementów i atrybutów, 107 wyświetlania funkcji matematycznych, 70 zawartości elementów, 151 konwencja typograficzna, 16 konwersja ciągu znaków, 216 książki elektroniczne, 257 kwantyfikator, 99 kwerenda, 225 kwerendowanie danych źródłowych, 226
L
M Markup Validation Service, 125 metadane, 24 metoda wynikowa, 42 HTML, 42 mixed content, 100 mniejsze lub równe, 68 niż, 68 mnożenie, 70 mod, 70
N nagłówek tworzenie struktury, 85 zawartość strony, 85 namespace, 134, 181 NaN, 142 narzędzia Ajax, 259 ePub, 260 KML, 260 ODF i OOXML, 260 pisanie dokumentów XML, 21 proponowanie słów kluczowych, 242 RSS, 259 SOAP i WSDL, 259 sugerowania witryn, 15 nawiasy okrągłe, 151 nazwa kwalifikowana, 187 rozszerzona, 187 uniwersalna, 187 nazwa_typu_złożonego, 159 nazwany typ niestandardowy, 144 nie równa się, 68 nieparsowane dane znakowe, 33 niestandardowy język znaczników, 13 w XML, 94 node tree, 38 notacja, 114 zawartości nieparsowanej, 114 numeryczne odwołania znakowe, 269 dziesiętne, 271 szesnastkowe, 271 używanie, 271
Skorowidz
liczba wystąpień maksymalna, 169 minimalna, 169 liczby formatowanie, 72 ujemne, 72 zaokrąglanie, 73 limit cyfr w liczbie, 152 Liquid XML Studio, 266 lista, 153 encji znormalizowana, 113 wyborów, 100, 105 literal elements, 39 litery zmiana wielkości, 75 location paths, 56
model danych, 201 XPath 2.0, 212 model groups, 160 model zawartości, 160
O OASIS, 255 obiekt XMLHttpRequest, 240, 241 OCF, 258 odejmowanie, 70 ODF, 255 a OOXML, 256 narzędzia, 260 wsparcie, 255
283
Skorowidz
Skorowidz odstęp_po, 82 OOXML, 255, 256 narzędzia, 260 wsparcie, 256 opakowanie, 249 OpenOffice.org, 255 OpenXML Writer, 256 operacje arytmetyczne, 70 operator and, 68 cast, 221 matematyczny, 70 OPF, 258 or, 68 to, 213 OPS, 258 oś atrybutu, 62 rodzaje, 62 ośmiobitowy format transformacji, 270 output method, 42 overall structure, 80 oXygen XML Editor, 265
P page content, 80 page master, 81 parameter entities, 109 parametr inherit, 82 n, 69 parent element, 26 parent node, 56 Parsed Character Data, 33 parsed entities, 114 parser analiza XML, 125 automatyczna wartość domyślna atrybutu, 104 encje, 114 encje nieparsowane, 117 formalny identyfikator publiczny, 127 komentarze, 136 prefiksy, 197 walidacja względem XML Schema, 135 parsowane dane znakowe, 33 pary nazwa-wartość, 29 PCDATA, 33 placemark, 254
284
plik JAR, 255 mimetype, 257 wyjściowy do wydruku, 80 dodanie tekstu HTML, 42 dokument XSL-FO, 86 HTML, 42 ogólna struktura, 80 okładka, 89 zawartość strony, 80 wyłącznie tekstowy, 122 wynikowy walidacja, 209 zewnętrzny zawierający DTD, 122 Podcast, 248 podciąg wyodrębianie, 74 podspecyfikacja OCF, 258 OPF, 258 OPS, 258 podszablony, 39 podwłaściwość, 84 podziały stron wstawianie, 87 populating the namespace, 188 porównywanie wartości, 68 powiązane źródła danych łączenie, 233 predefined entities, 32 predykat, 59, 63 zastosowanie, 63 prefiks atrybut, 186 nazwa przestrzeni nazw, 184 przestrzeni nazw XML Schema, 139 w elemencie, 184 xs, 134, 139 procesor kompatybilność wersji XSLT, 202 XQuery, 225 XSL-FO, 79 processing instructions, 25 projekt Gutenberg, 257 protokół uzyskiwania szybkiego dostępu do obiektów, 249 przekształcanie, 37 proces, 38
Skorowidz
Q QName, 187 quantified expression, 218
R ramka styl wizualny, 83 Really Simple Syndication, 15, 245 referencje encji, 272 znakowe, 111 regex, 150 rejestr publiczny, 252 relative location path, 56 restrykcja xs:sequence, 157 retrieving function, 241
return expression, 220 root element, 22 root template, 39 root type, 156 rozszerzalny język arkuszy stylów, 14 język znaczników, 12 rozszerzenie .dtd, 94, 122 .ent, 112 .fo, 81 .kml, 253 .ncx, 258 .xquery, 227 .xsd, 134, 194 .xsl, 39 RSS, 15 agregator kanałów, 245 czytnik kanałów, 245 kanał, 245 moduły, 247 blogChannel, 248 Media, 247 narzędzia, 259 podstawy, 245 przestrzeń nazw, 246 rozszerzanie, 247 schematy, 246 źródło, 245
Skorowidz
przestrzeń nazw, 134, 181 blogChannel RSS, 248 docelowa, 188 dodawanie atrybutów lokalnych, 192 elementów lokalnych, 192, 193 dokumenty DTD, 197 domyślna deklarowanie, 183 uchylanie, 183 funkcje UDF, 206 instancji XML Schema, 135 iTunes Podcasting, 248 język XQuery, 234 komponenty zdefiniowane lokalnie, 192 Media RSS, 247 nazwa, 181 deklarowanie prefiksu, 184 łączenie z nazwą elementu, 187 projektowanie, 182 prefiksowana, 183 relacja między XML Schema a XML, 189 schemat schematów, 196 SOAP, 250 walidacja dokumentów XML, 191 wpływ na atrybuty, 186 WSDL, 251 wypełnianie, 188 zapobieganie powiązaniu elementu, 193 pt, 82 punkt kodu, 271
S schemat, 93 schemat DTD, 94 schemat schematów, 196 jako domyślna przestrzeń nazw, 196 schemat.uri, 189 sekcja CDATA, 33 sekwencja, 161, 211, 213 cechy, 213 elementów, 98 instrukcja xsl:sort, 219 kwantyfikacja warunków, 218 usuwanie zduplikowanych pozycji, 219 wartość maksymalna, 215 minimalna, 215 uśrednianie, 214 wiązania, 218, 220, 230 zapętlanie, 220
285
Skorowidz
Skorowidz shorthand properties, 84 sibling nodes, 56 Simple Object Access Protocol, 249 simple type, 132 skalowanie obrazka, 83 proporcjonalne, 83 skrót, 110 //, 65 bieżącego węzła, 59 SOAP, 249 fukcje, 249 koperta, 249 narzędzia, 259 schemat komunikatu, 250 wymiana komunikatów, 249 sortowanie liczb, 50 malejące, 50 rosnące, 50 sekwencji, 219 tekstu, 50 SQL, 226 standard Ecma, 256 IDPF, 258 stopka numerowanie stron, 87 string, 132 string value, 44 strona bloki zawartości, 82 nadrzędna, 81 nagłówek, 85 podziały, 87 szablon definiowanie, 84 dodawanie, 89 zawartość, 89 WWW, 11 zawartość definiowanie, 84 w kolumnach, 88 struktura płaska, 213 strumienie zdjęć, 245 style sheets, 40 Stylus Studio, 266 subskrypcja, 245 symbol specjalny, 111 szablon XSLT, 38 dodanie tekstu HTML, 43 etykieta, 39
286
główny, 39 dodanie tekstu HTML, 42 tworzenie, 41 wbudowany, 41 instrukcje, 39 reguły definiowanie, 42 stosowanie, 52 ręczne, 52 tworzenie, 52 wyrażenie, 55
Ś ścieżka lokalizacji, 56, 212 atrybut węzła, 62 bezwzględna, 57 tworzenie, 64 bieżący węzeł, 59 porównywanie dwóch wartości, 68 względna, 56
T tabela HTML tworzenie, 47 tabela znaków Unicode, 273 target namespace, 188 tekst, 95 template, 38 test expression, 217 testowanie operacje arytmetyczne, 70 porównanie dwóch wartości, 68 pozycji węzła, 69 za pomocą wyrażeń warunkowych, 232 transformacje XSLT, 41 transforming, 37 true, 77 typ anonimowy, 144 czasu, 141 daty i czasu, 140 element pusty definiowanie, 165 główny, 156 liczbowy, 142 limity maksymalne i minimalne, 147 listy, 153 anonimowy, 153 nazwany, 153
Skorowidz
U UDDI, 252 biznesowe, 252 UDF, 206 Unicode, 269 punkty kodu źródło, 271 Uniform Resource Identifier, 113 Uniform Resource Locator, 113 Uniform Resource Name, 113 union type, 154 Universal Description, Discovery, and Integration, 252 uniwersalna nazwa zasobu, 113 unparsed, 33 unparsed entities, 114 URI, 113 nazwy przestrzeni nazw, 182 URL, 113, 182 URN, 113 User Defined Functions, 206 usługa internetowa, 249 oparta na protokole SOAP, 250 rejestr, 252 WSDL, 251 UTC, 141 UTF-16, 270 UTF-8, 270
V VBScript, 244
W W3C, 13, 18 funkcje XPath, 67 rekomendacja dla XML-a, 25 XML Schema, 133 XSL-FO, 79 walidacja dokumentu XML względem XML Schema, 191 plików wynikowych XSLT, 209 pliku wklejonego, 125 pod podanym adresem URI, 125 wielu dokumentów XML, 121 załadowanego pliku, 125 walidator, 125, 135, 267
287
Skorowidz
łączony, 154 anonimowy, 154 nazwany, 154 MIME, 115, 257 nazwany, 144 niestandardowy nazwany, 145 pusty element, 156 wyłącznie element, 156 wyłącznie tekst, 156 definiowanie, 164 xs:anyURI, 138 xs:boolean, 138 xs:date, 138, 140 xs:dateTime, 140 xs:decimal, 138, 142 xs:duration, 140 xs:float, 142 xs:gDay, 141 xs:gMonth, 141 xs:gMonthDay, 141 xs:gYear, 141 xs:int, 142 xs:integer, 142 xs:negativeInteger, 142 xs:nonNegativeInteger, 142 xs:nonPositiveInteger, 142 xs:positiveInteger, 142 xs:restriction, 144 xs:simpleType, 144 xs:string, 138 xs:time, 138, 140 zawartości, 158 zawartość mieszana, 156 definiowanie, 166 złożony, 155 anonimowy, 158 atrybuty, 172 domyślna derywacja, 157 dowolna kolejność elementów-dzieci, 162 nazwany, 158, 159 podstawy, 156 sekwencja elementów-dzieci, 161 tylko element, 160 wywodzenie, 157 wywodzenie z innych typów złożonych, 167 zawierający elementy-dzieci, 160
Skorowidz
Skorowidz wartość auto, 84, 87 całkowita liczba cyfr, 152 ciągu, 44 column, 87 dashed, 83 domyślna, 143, 174 dotted, 83 double, 83 enumeracji, 148 even-page, 87 font-size, 82 groove, 83 grupy, 208 hidden, 83 indefinite, 84 inset, 83 liczba cyfr w części ułamkowej, 152 medium, 83 najniższa możliwa, 147 najwyższa możliwa, 146 niepodzielna, 213 none, 83 odd-page, 87 określanie dopuszczalnego zakresu, 146 dopuszczalnego zbioru, 148 outset, 83 porównywanie, 68 qualified, 192 ridge, 83 solid, 83 sumowanie, 76 średnia, 76 thick, 83 thin, 83 unqualified, 192 ustalona, 143, 174 warunek kwantyfikacja, 218 select, 47 testowanie, 49, 217 wysokości, 68 xsl:if, 48 Web Service, 249 well-formed, 23 wewnętrzne opcje ogólne, 110 węzeł, 38 bieżący, 57 odwołania, 59 skrót, 59 ustalanie, 58
288
dokumentu, 56 główny, 39 identyfikacja, 39 jako dane wyjściowe, 39 kontekstowy, 57, 59 odwoływanie, 59 liczenie, 71 lokalizowanie, 56 potomny, 56 pozyskiwanie wartości, 57 przetwarzanie partiami, 46 warunkowe, 48 przodek, 56 rodzeństwo, 56 rodzic, 56 skrót, 60 sortowanie domyślne, 50 przed przetworzeniem, 50 sprawdzanie pozycji, 69 wybieranie bez znajomości położenia, 65 dzieci, 60 podzbioru, 63 rodzeństwa, 61 rodzica, 61 warunkowe, 63 wszystkich potomków, 65 wyświetlenie zawartości, 44 zapętlanie, 46 zbiór w wyrażeniu, 48 wynikowy, 57 znajdowanie, 69 zlokalizowany, 57 white space, 24 większe lub równe, 68 niż, 68 właściwość border-style, 83 border-width, 83 break-after, 87 break-before, 87 content-height, 83 inherit, 87 margin, 84 onreadystatechange, 241 open, 241 page-height, 84 page-width, 84
Skorowidz
X XDM, 212 XHTML, 204 XLS-FO, 14 XML, 11, 12 a HTML, 11, 14, 15 analizowanie źródła, 38 deklaracja wersji, 25
dokument elementy główne, 22 źródłowy, 44 lista wyborów, 105 narzędzia, 259, 263 do konwersji i walidacji, 267 rozszerzanie, 14 specyfikacja, 21 struktura, 23 strukturalne definicje, 14 w praktyce, 15 zalety języka, 13 zarządzanie informacją, 11 zasoby, 267 specyfikacje, 267 zastosowanie, 239 znaczniki, 14 XML applications, 21 XML Copy Editor, 265 XML declaration, 22 XML Infoset, 212 XML Path Language, 55 XML Schema, 14, 131 atrybuty grupy, 175 predefiniowanie zawartości, 174 definicje lokalne i globalne, 177 w kilku plikach, 194 z różnych przestrzeni nazw, 195 hierarchia typów, 156 język regex, 150 komentarze, 136 komponent, 190 liczba wystąpień, 169 podział pliku, 195 predefiniowanie zawartości elementu, 143 przestrzeń nazw, 134, 188 odwołania do komponentów, 190 typ złożony, 155 typy proste, 137 data i czas, 140 dla liczb, 142 niestandardowe, 137, 144 wbudowane, 139 wersje, 133 wyrażenia regularne, 151 wzorce, 150 zakres dopuszczalnych wartości, 146 zalety, 131
Skorowidz
send, 241 skrócona, 84 WMHelp XMLPad, 266 wrapper, 249 WSDL, 251 narzędzia, 259 schemat, 251 źródło, 252 wskaźnik strefy czasowej, 141 wybory, 100 atrybuty, 105 warunkowe, 49 wyizolowany zasięg, 177 wykomentowanie sekcji, 31, 222 wyrażenie, 44 //nazwa_elementu, 65 choose-when-otherwise, 217 else(), 232 every, 218 FLWOR, 230, 233 for, 220 if-then-else, 217, 232 kwantyfikowane, 218 logiczne, 63 not, 68 regularne, 150 select, 45 składnia języka, 55 some, 218 ścieżkowe, 229 testowe, 217, 232 XQuery, 227 warunkowe, 232 zamknięte, 227 ewaluacja, 232 zwrotne, 220 wzorzec ###0.00, 72 #000.0#, 72 składnia języka, 55
289
Skorowidz
Skorowidz XMLmind XML Editor, 266 XMLwriter XML Editor, 266 XPath, 14, 39, 55 działania arytmetyczne, 72 funkcje, 67 łączenie, 76 osie rodzaje, 62 podstawy, 212 porównanie wersji, 211, 212 rodzaje węzłów, 57 tłumaczenie ścieżek lokalizacji, 56 wersja 2.0, 211 formatowanie ciągów znaków, 216 funkcje daty i czasu, 221 język silnie typizowany, 212 komentarze, 222 model danych, 212 przetwarzanie danych wejściowych nie-XML, 223 sekwencje, 213 zapętlanie, 220 testowanie warunków, 217 wyrażenia, 213 XQuery, 55, 201, 225 a XSLT 2.0, 226 dokument, 227 funkcje użytkownika, 234 i bazy danych, 235 komentarze, 227 łączenie powiązanych źródeł danych, 233 predykaty, 229 przestrzeń nazw, 234 wyrażenia ścieżkowe, 229 warunkowe, 232 XQuery/XPath Data Model, 212 XSD, 131 xsd.uri, 135 XSDL, 131 XSL, 14 dla formatowania obiektów, 37 dla przekształceń, 37 XSL-FO, 37, 79 ogólna struktura, 80 zawartość strony, 80 xsl-region-after, 87 xsl-region-before, 85 XSLT, 14, 37 arkusz stylów, 38 i przestrzenie nazw, 198
290
konwersja XML na HTML, 39 plik wynikowy transformacji, 205 rozszerzanie, 202 walidacja pliku wynikowego, 209 wersja 2.0, 201 funkcje definiowane przez użytkownika, 206 grupowanie danych wynikowych, 208 kilka dokumentów wynikowych, 205 łatwość zastosowania, 203 walidacja plików wynikowych, 209 wsparcie dla dokumentów wynikowych XHTML, 204 wsteczna kompatybilność, 202
Y Yahoo! Finance, 243 Yahoo! Search Media RSS, 247
Z zagnieżdżona struktura if-then-else, 217, 232 zaokrąglanie liczb, 73 zawartość mieszana, 100 zbiór wyborów sekwencja, 163 tworzenie, 163 znacznik główny, 26 otwierający, 27 td, 47 tr, 47 w XML, 12 wszystko-w-jednym, 23 XML a HTML, 13 xsl:output, 42 xsl:stylesheet, 40 xsl:template, 41 zamknięcie, 22 zamykający, 23, 24, 27 znak !=, 68 #, 72 %, 118, 119 &, 111, 113 , 271 , 271 *, 60, 64, 70, 99, 100 //, 65
Skorowidz ?, 99 @, 62 |, 100 +, 70, 99 0, 72 c, 74 funta, 51 kropki, 72 metoda przechowywania, 269 myślnika, 140 poprawna reprezentacja, 269 specjalny, 99 (xy)*, 150 (xy)?, 150 (xy)+, 150 (xyz){2}, 151 [0–9], 150 [abc], 150 \d, 150 \D, 150
kropka, 150 \s, 150 \S, 150 to | tamto, 151 x*, 150 x?, 150 x{5,}, 151 x{5,8}, 151 x{5}, 151 x+, 150 sposób kodowania, 270 Unicode, 273 wieloznaczny, 61
Ź źródło podcastowe, 248 przykładów, 17
Skorowidz 291
Recommend Documents
No documents