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


Rozdział --> 10[Author:T] .
--> XLinks i XPointers[Author:T]

Ten rozdział poświęcimy w całości tworzeniu połączeń między dokumentami i ich częściami - specyfikacjom XLink i XPointer. W HTML mamy do dyspozycji hiperłącza, jednak autorzy XML poszli znacznie dalej tworząc specyfikacje XLink, XPointer, XPath i XBase.

Niestety, omawiane tematy to kolejne obszary, w których W3C znacznie wyprzedza całą resztę świata - jeszcze nie istnieją implementacje tych technologii. Microsoft, który już nieraz pośliznął się implementując standardy XML, które później się zmieniały, dopiero zaczyna w Internet Explorerze XLinks i XPointers obsługiwać. W przyszłości niewątpliwie pojawią się pełne implementacje, ale na razie omawiane tu tematy są ściśle teoretyczne.

W skrócie: powiązanie XLinks i XPointers

Łącza XLinks opisują sposób łączenia jednego dokumentu z innym. XPointers to wskaźniki określające położenie wybranego fragmentu w dokumencie, korzystają przy tym z rekomendacji XPath. Teraz w skrócie omówimy całość łączy XML.

W chwili pisania specyfikacja XLink ma status proponowanej rekomendacji i datowana jest na --> 20 grudnia 2000 roku[Author:T] . Najnowszą wersję tej rekomendacji znajdziesz pod adresem www.w3.org/TR/xlink. XLinks używa się do łączenia jednego dokumentu z innym, oto co W3C mówi we wstępie:

W tej specyfikacji opisano Język łączy XML (XML Linking Language, XLink), która umożliwia wstawianie do dokumentów XML elementów tworzących i opisujących łącza między zasobami. Za pomocą składni XML można opisać zarówno proste łącza podobne do hiperłączy HTML, jak i łącza znacznie bardziej wyrafinowane.

Oto przykład, który ma Ci nieco przybliżyć łącza XLinks. W przeciwieństwie do HTML, rolę łącza pełnić może dowolny element - jego rodzaj określa się podając odpowiednią wartość atrybutu xlink:type:

<PRZEGLĄD_FILMOWY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="simple"

xlink:show="new"

xlink:href="http://www.starpowdermovies.com/reviews.xml">

Pan Blandings buduje dom swoich marzeń

</PRZEGLĄD_FILMOWY>

W tym wypadku utworzyliśmy proste łącze działające podobnie jak hiperłącze HTML - decyduje o tym atrybut xlink:type o wartości simple. Ustawiliśmy też atrybut xlink:show na new, co powoduje otwarcie łącza w nowym oknie. Atrybut xlink:href zawiera adres URI nowego dokumentu (adres ten może być bardzo ogólny, niekoniecznie musi mieć postać używanych dotąd adresów URL).

Zaczęliśmy od łącza prostego, aby na początek pokazać coś znajomego. Oprócz prostych łączy jednokierunkowych - jak to pokazane tutaj - można tworzyć też łącza dwukierunkowe, a także łącza między wieloma dokumentami, a nawet zbiorami dokumentów. Można też łącza zapisywać w bazach danych łączy nazywanych bazami łączy.

XLinks umożliwiają łączenie konkretnego dokumentu, ale często taka dokładność wyboru nie jest wystarczająca. W tym wypadku w sukurs przychodzą XPointers umożliwiające wskazanie miejsca w dokumencie nawet bez modyfikowania tego dokumentu w celu wstawiania tam jakiegokolwiek znacznika.

W celu wskazania jakiegoś miejsca w dokumencie XPointers korzystają ze specyfikacji XPath. XPath pozwala wskazać węzeł dokumentu XML za pomocą wyrażeń takiego typu, jak pokazane niżej:

/child::*[position()=126]/child::*[position()=first()]

Obecnie XPointers mają status rekomendacji proponowanej --> i opublikowane zostały 8 stycznia 2001 roku[Author:T] . Najnowszą wersję specyfikacji XPointer znajdziesz pod adresem www.w3.org/TR/xptr. Oto jak W3C omawia XPointers:

W specyfikacji tej zdefiniowano Język wskaźników XML (XML Pointer Language, XPointer) używany jako podstawa identyfikatorów fragmentów zasobów dostępnych przez URI, takich jak text/xml, application/xml, text/xml-external-parsed-entity czy application/xml-external-parsed-entity.

XPointer oparty jest na Języku ścieżek XML (XML Path Language, XPath) i obsługuje adresowanie poszczególnych części dokumentów XML. Umożliwia badanie struktury dokumentów hierarchicznych i wybieranie poszczególnych części na podstawie różnych cech, takich jak typy elementów, wartości atrybutów, treść tekstowa czy położenie względne.

Wprawdzie XPointers bazują na XPath, ale rozszerzają składnię XPath, co zostanie w tym rozdziale omówione.

Aby dodać wskaźnik XPointer do adresu URI, wystarczy za tym adresem umieścić znak # (używany w HTML do zakładek) i dopisać xpointer() w nawiasach podając wyrażenie XPath. Oto przykład:

<PRZEGLĄD_FILMOWY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="simple"

xlink:show="new"

xlink:href="http://www.starpowdermovies.com/reviews.xml#

xpointer(/child::*[position()=126]/child::*[position()=first()])">

Pan Blandings buduje dom swoich marzeń

</PRZEGLĄD_FILMOWY>

Tyle tytułem wstępu do XLinks i XPointers. Obie specyfikacje omówimy dalej w tym rozdziale, omówimy też XBase --> oraz krótko XPath[Author:T] .

Zmienność XML

Trzeba zdawać sobie sprawę z tego, że specyfikacje XLink, XPointer i XBase, podobnie jak inne fragmenty XML nie mające jeszcze statusu rekomendacji, mogą się zmieniać. Opisywane specyfikacje są już bliskie stania się rekomendacjami, więc zmiany względem opisu zamieszczonego w tej książce nie powinny być zbyt duże. Trzeba też pamiętać, że kiedy pojawią się implementacje tych specyfikacji, to i one mogą się nieco różnić od propozycji W3C.

Wszystko o łączach XLinks

Hiperłącza są bardzo ważną częścią HTML, tworzy się je za pomocą elementu A:

<A HREF="http://www.starpowdermovies.com/reviews.html#blandings">

Pan Blandings buduje dom swoich marzeń

</A>

Hiperłącza w dokumencie HTML mają albo postać tekstu - zwykle podkreślonego i w innym kolorze - albo postać obrazka. Kliknięte hiperłącze otwiera nowy dokument lub wybrane jego miejsce w ramce istniejącej lub w nowym oknie, może też uruchomić program JavaScript. W tabeli 10.1 zestawiono oficjalnie obowiązujące atrybuty elementu A z HTML:

Tabela 10.1.
Atrybuty elementu A z HTML

Atrybut

Opis

ACCESSKEY

Przypisuje klawisz skrótu do hiperłącza.

CHARSET

Określa kodowanie lokalizacji docelowej hiperłącza. Ustawia się zgodnie z zestawami RFC 2045 (wartość domyślna to ISO-8859-1).

CLASS

Określa klasę stylu dla elementu.

COORDS

Określa współrzędne (w pikselach) dotyczące atrybutu SHAPE definiującego obszar na mapie obszarów.

DIR

Określa kierunek neutralnego kierunkowo tekstu. Ustawienie LTR oznacza tekst od lewej do prawej, RTL tekst pisany od prawej do lewej.

HREF

Określa docelowy adres URL hiperłącza. Użyć można albo tego atrybutu, albo atrybutu NAME.

HREFLANG

Określa język bazowy miejsca docelowego łącza. Ustawiane zgodnie z wartościami RFC 1766.

ID

Określa niepowtarzalny identyfikator znacznika.

LANG

Służy jako język bazowy znacznika.

NAME

Określa nazwę zakładki, której można użyć do odwoływania się do fragmentów docelowego dokumentu. Użyć można albo tego atrybutu, albo atrybutu HREF.

REL

Określa związek opisany przez hiperłącze.

REV

W zasadzie ma takie samo zdarzenie, jak REL, ale składnia działa w kierunku odwrotnym.

SHAPE

Określa typ obszaru definiowanego w znaczniku AREA.

STYLE

Styl typu inline wskazujący sposób prezentacji elementu.

TABINDEX

Ustawia kolejność łączy na stronie w przypadku poruszania się klawiszem tabulatora.

TARGET

Określa nazwę ramki, z którą ma być związany adres HREF.

TITLE

Informacja o tytule elementu.

TYPE

Typ MIME miejsca docelowego wskazanego w atrybucie HREF.

Zestawione atrybuty umożliwiają realizację różnych funkcji, ale zawsze konieczne jest użycie elementu A, a uzyskane łącze ma typ najprostszy z możliwych: po kliknięciu powoduje przejście do nowego dokumentu lub do innej lokalizacji dokumentu bieżącego.

Związki między dokumentami mogą być znacznie bardziej złożone. Mogą na przykład być potrzebne następujące funkcje:

Są jeszcze inne możliwości, a XLinks umożliwiają ich realizację.

XLinks nie ograniczają zestawu używanych elementów do jednego A, a to oznacza, że łącza XML nie zawsze muszą mieć postać podkreślonego, niebieskiego tekstu (można je oczywiście w dowolny sposób wyróżnić). Możliwość przetworzenia na łącze dowolnego elementu jest doskonałą wiadomością, gdyż można stworzyć elementy zawsze łączące się z określonymi zasobami. Użytkownik może nawet oczekiwać, że fragment sformatowany elementem CYTAT będzie powiązany ze źródłem tego cytatu.

XLinks tworzy się stosując atrybuty, a nie elementy. W szczególności atrybutu xlink:type używa się do utworzenia łącza - można mu nadać jedną z wartości: simple, extended, locator, arc, resource, title lub none.

Tabela 10.2.
Atrybuty łączy XLinks

Atrybut

Opis

xlink:actuate

Atrybut ten określa, kiedy następuje przejście przez łącze. Może mieć wartości onLoad, onRequest lub undefined, a także inne rozpoznawane przez używane oprogramowanie.

xlink:from

Atrybut określa zasób początkowy łącza.

xlink:href

Jest to atrybut lokalizujący, który zawiera dane umożliwiające aplikacji obsługującej łącza odnalezienie zasobu docelowego.

xlink:role

Tego atrybutu używa się do opisania funkcji docelowego zasobu w sposób czytelny dla komputera, a w przypadku elementów typu rozszerzonego (extended) służy jako etykieta kategorii zasobu dla reguł przejścia po elementach łukowych. Atrybut ten może być przydatny dla wyszukiwarek.

xlink:show

Tego atrybutu używa się do wskazania, jak ma być wyświetlany zasób docelowy. Aplikacja XLinks musi rozpoznawać następujące wartości: new (otwiera się nowy obszar wyświetlania), replace (dane aktualnie wyświetlane są zamieniane na dołączone), embed (nowy zasób jest włączany do obecnie pokazywanego) oraz undefined (oprogramowanie decyduje o sposobie wyświetlenia).

xlink:title

Atrybut ten opisuje funkcję zasobu łącza w sposób zrozumiały dla ludzi.

xlink:to

Definiuje miejsce docelowe lub zasoby końcowe.

xlink:type

Atrybut ten określa typ łącza XLinks, może mieć jedną z wartości: simple, extended, locator, arc, resource, title, none. Ich znaczenie opiszemy dalej.

Za pomocą atrybutów XLinks można zasymulować ich działanie w przeglądarkach takich jak Internet Explorer. Jako przykład utworzymy proste łącze. Internet Explorer obsługuje atrybut onClick elementów XML. Dodamy do tego atrybutu funkcję JavaScriptu powodującą zmianę bieżącego adresu URI. W tym celu zastosujemy obiekt location:

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

<?xml-stylesheet type="text/css" href="xlink_example.css"?>

<!DOCTYPE html SYSTEM "xlink_example.dtd">

<DOKUMENT>

<P>

Zaczynamy sprawdzanie? kliknij

<LINK xml:type="simple" href="http://www.w3c.org"

onClick="location.href='http://www.w3c.org'">W3C</LINK>

</P>

</DOKUMENT>

Dołączymy jeszcze arkusz stylów xlink_example.css, aby nasze łącze wyglądało tak, jak zwykłe hiperłącza HTML. Możemy nawet spowodować, że kursor myszki w Internet Explorerze zmieni swój kształt na dłoń, jak to ma miejsce przy zwykłych łączach:

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

Wyniki pokazano na rysunku 15.1: łącze proste XLinks zachowuje się podobnie, jak zwykłe hiperłącze HTML (oczywiście oznacza to niewykorzystanie możliwości XLinks). Kliknięcie na to łącze spowoduje, że Internet Explorer przejdzie do nowego dokumentu.

--> Rysunek 10.1.[Author:T]

Symulowanie łącza prostego XLinks w Internet Explorerze

0x01 graphic

Powstaje zatem pytanie, kiedy i których atrybutów języka XLink należy użyć? Wszystko zależy od rodzaju tworzonego łącza określonego atrybutem xlink:type. W zależności od tego typu niektóre atrybuty mogą być wymagane, inne pozostają opcjonalne. Zestaw obowiązujących reguł zestawiono w tabeli 10.3, gdzie poszczególnym wierszom odpowiadają różne atrybuty XLink, natomiast kolumnom odpowiadają typy łącz XLinks.

Tabela 10.3.
Atrybuty wymagane i opcjonalne według ustawienia xlink:type

simple

extended

locator

arc

resource

title

type

wymagany

wymagany

wymagany

wymagany

wymagany

wymagany

href

opcjonalny

pomijany

wymagany

pomijany

pomijany

pomijany

role

opcjonalny

opcjonalny

opcjonalny

opcjonalny

opcjonalny

pomijany

title

opcjonalny

opcjonalny

opcjonalny

opcjonalny

opcjonalny

pomijany

show

opcjonalny

pomijany

pomijany

opcjonalny

pomijany

pomijany

actuate

opcjonalny

pomijany

pomijany

opcjonalny

pomijany

pomijany

from

pomijany

pomijany

pomijany

opcjonalny

pomijany

pomijany

to

pomijany

pomijany

pomijany

opcjonalny

pomijany

pomijany

Zwróć uwagę na to, że wszystkie wymienione atrybuty używają przestrzeni nazw xlink; adresem URI tej przestrzeni zawsze jest http://www.w3.org/1999/xlink, co zresztą wynikało z poprzedniego przykładu:

<PRZEGLĄD_FILMOWY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="simple"

xlink:show="new"

xlink:href="http://www.starpowdermovies.com/reviews.xml">

Pan Blandings buduje dom swoich marzeń

</PRZEGLĄD_FILMOWY>

Baza XML (XBase)

Kolejną specyfikacją W3C związaną z wiązaniem dokumentów i tworzeniem łącz jest specyfikacja XBase.

W chwili pisania specyfikacja ta ma status --> rekomendacji proponowanej i wydana została 20 grudnia 2000 roku[Author:T] . Bieżącą wersję tego dokumentu znajdziesz pod adresem www.w3.org/TR/xmlbase. Specyfikacja ta opisuje adres bazowy URI dokumentów XML, tak jak znacznik <BASE> w HTML. Tak naprawdę właśnie znacznik <BASE> był powodem powstania XBase - W3C chce zapewnić pełną obsługę łączy istniejących w HTML 4.0, a dopiero potem na tej podstawie tworzyć dalsze rozszerzenia.

W dokumencie XML odnajduje się --> atrybut[Author:T] xml:base, aby określić bazowy adres URI tego dokumentu. Pozostałe adresy w dokumencie rozwijane są względem danego adresu bazowego. Zwróć uwagę na to, że w opisywanym elemencie używana jest przestrzeń nazw xml, a nie xlink. Przestrzeń nazw xml jest w XML przestrzenią predefiniowaną, zatem aby jej użyć, nie musisz jej deklarować. Przestrzeni tej odpowiada adres URI http://www.w3.org/XML/1998/namespace. Oto przykład użycia elementu xml:base:

<PRZEGLĄD_FILMOWY xmlns:xlink="http://www.w3.org/1999/xlink"

xml:base="http://www.starpowder.com"

xlink:type="simple"

xlink:show="new"

xlink:href="reviews.xml">

Pan Blandings buduje dom swoich marzeń

</PRZEGLĄD_FILMOWY>

Przy użyciu wartości atrybutu xml:base adres URI atrybutu xlink:href, u nas reviews.xml, rozwijany jest jako http://www.starpowder.com/reviews.xml. W ten sposób można użyć atrybutu xml:base do podania bazowego adresu URI związanego z dokumentem (a nawet z konkretnym elementem).

Deklarowanie atrybutów XLink

Zwróć uwagę na to, że jeśli chcesz walidować dokumenty XML, musisz zadeklarować atrybuty XLink tak samo, jak wszystkie inne atrybuty. Do poprzedniego przykładu można użyć następującej DTD:

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

<!DOCTYPE PRZEGLĄD_FILMOWY [

<!ELEMENT PRZEGLĄD_FILMOWY (#PCDATA)>

<!ATTLIST PRZEGLĄD_FILMOWY

xmlns:xlink CDATA #IMPLIED

xml:base CDATA #IMPLIED

xlink:type CDATA #IMPLIED

xlink:href CDATA #IMPLIED

xlink:show CDATA #IMPLIED

xlink:actuate CDATA #IMPLIED

xlink:title CDATA #IMPLIED>

]>

<PRZEGLĄD_FILMOWY xmlns:xlink="http://www.w3.org/1999/xlink"

xml:base="http://www.starpowder.com"

xlink:type="simple"

xlink:show="new"

xlink:href="reviews.xml">

Pan Blandings buduje dom swoich marzeń

</PRZEGLĄD_FILMOWY>

Można też na stałe zakodować wartości większości atrybutów XLink - w tym wypadku konieczne byłoby tylko podanie wartości atrybutu xlink:href:

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

<!DOCTYPE PRZEGLĄD_FILMOWY [

<!ELEMENT PRZEGLĄD_FILMOWY (#PCDATA)>

<!ATTLIST PRZEGLĄD_FILMOWY

xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"

xml:base CDATA #FIXED "http://www.starpowder.com"

xlink:type CDATA #FIXED "simple"

xlink:href CDATA #REQUIRED

xlink:show CDATA #FIXED "new"

xlink:actuate CDATA #FIXED "onRequest"

xlink:title CDATA #IMPLIED>

]>

<PRZEGLĄD_FILMOWY xlink:href="reviews.xml">

Pan Blandings buduje dom swoich marzeń

</PRZEGLĄD_FILMOWY>

Z uwagi na to, że język XLink jest tak ogólny, deklarowanie elementów XLink może być dość skomplikowane - elementy łącz mogą mieć elementy potomne, te mogą mieć własne elementy potomne i tak dalej. Pamiętaj, że jeśli chcesz swój dokument walidować, musisz zadeklarować wszystkie elementy XLink w DTD lub w schemacie XML.

Masz już ogólne pojęcie o użyciu atrybutów XLinks, teraz przyjrzymy się im kolejno dokładniej. Zaczniemy od atrybutu najważniejszego, czyli xlink:type.

Atrybut xlink:type

Atrybut xlink:type określa typ tworzonego łącza XLink. Atrybut ten może mieć następujące wartości:

Wartość

Opis

simple

Tworzy łącze proste.

extended

Tworzy łącze rozszerzone.

locator

Tworzy łącze lokalizatora wskazujące zasób.

arc

Tworzy łuk łączący wiele zasobów i różne ścieżki przejścia pomiędzy nimi.

resource

Tworzy łącze zasobu, które wskazuje konkretny zasób.

title

Tworzy łącze tytułowe. Tego typu elementy są użyteczne na przykład wtedy, gdy czytelna dla człowieka informacja w postaci etykiety potrzebuje dalszego oznakowania lub gdy w celu zapewnienia obsługi wielu języków konieczne jest zastosowanie wielu tytułów.

Tworzenie łącz prostych już widzieliśmy:

<PRZEGLĄD_FILMOWY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="simple"

xlink:show="new"

xlink:href="http://www.starpowder.com/reviews.xml#

xpointer(/child::*[position()=126]/child::*[position()=first()])">

Pan Blandings buduje dom swoich marzeń

</PRZEGLĄD_FILMOWY>

Inne rodzaje łączy poznamy dalej w tym rozdziale.

Wskazywanie zasobów - atrybut xlink:href

Atrybut xlink:href nazywany jest także atrybutem lokalizatorem. Atrybut ten podaje informacje umożliwiające aplikacji XLink odnaleźć zdalny zasób.

Definicja URI

Łącza XLinks mogą być bardzo ogólne, zwykle do lokalizowania zasobów używa się adresu URI podawanego w atrybucie xlink:href. Badamy teraz sposób tworzenia łączy w XML i być może chciałbyś niejako przy okazji przyjrzeć się formalnej definicji URI - znajdziesz ją pod adresem www.ics.uci.edu/pub/ietf/uri/rfc2396.txt.

Widziałeś już, że w atrybucie xlink:href można podać jednocześnie adres URI oraz wskaźnik XPointer:

<PRZEGLĄD_FILMOWY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="simple"

xlink:show="new"

xlink:href="http://www.starpowder.com/reviews.xml#

xpointer(/child::*[position()=126]/child::*[position()=first()])">

Pan Blandings buduje dom swoich marzeń

</PRZEGLĄD_FILMOWY>

Dalej pokażemy, jak skomplikowane mogą być wartości tego atrybutu.

Opisywanie zasobów: xlink:role i xlink:title

Ważnymi atrybutami XLink są xlink:role oraz xlink:title; umożliwiają one opisanie zdalnego zasobu. Oba są opcjonalne, poniżej pokazano przykład ich użycia:

<PRZEGLĄD_FILMOWY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="simple"

xlink:show="new"

xlink:role="PRZEGLĄD_FILMOWY[PL]"

xlink:title="Opis filmu 'Pan Blandigns buduje dom swoich marzeń'"

xlink:href="http://www.starpowder.com/reviews.xml#

xpointer(/child::*[position()=126]/child::*[position()=first()])">

Pan Blandings buduje dom swoich marzeń

</PRZEGLĄD_FILMOWY>

Atrybut xlink:title zawiera czytelny dla człowieka opis zasobu wskazywanego przez łącze. Chodzi o to, aby użytkownik mógł zawczasu sprawdzić, co znajduje się „na drugim końcu” łącza - wystarczy, aby aplikacja wyświetliła tę podpowiedź.

Treść atrybutu xlink:role z kolei przeznaczona jest do przetwarzania maszynowego i określa rolę łącza. Atrybut ten opisuje kategorię, do jakiej łącze należy; w naszym wypadku użyliśmy wartości PRZEGLĄD_FILMOWY[PL].

Jak dotąd nikt nie próbował ustandaryzować kategorii łączy w sposób podobny, jak RDF (opisany w pierwszym rozdziale) standaryzuje treści zasobów. Po prostu istnieje tu zbyt wiele możliwości. Wprawdzie wyszukiwarki mogą użyć atrybutu xlink:role do klasyfikacji łącza, ale ról używa się zwykle do definiowania łączy kierunkowych przy tworzeniu łączy rozszerzonych, które omówimy dalej.

Jeśli swoje dokumenty zamierzasz walidować, atrybuty xlink:role i xlink:title musisz zadeklarować. W poniższym przykładzie użyto DTD i atrybutowi xlink:role elementu PRZEGLĄD_FILMOWY nadano wartość stałą PRZEGLĄD_FILMOWY[PL]:

<!ELEMENT PRZEGLĄD_FILMOWY (#PCDATA)>

<!ATTLIST PRZEGLĄD_FILMOWY

xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"

xlink:type CDATA #FIXED "simple"

xlink:href CDATA #REQUIRED

xlink:title CDATA #IMPLIED

xlink:role CDATA #FIXED "PRZEGLĄD_FILMOWY[PL]"

>

Atrybut xlink:show

Atrybutu xlink:show można użyć do wskazania, jak dołączony zasób ma być wyświetlony przy aktywacji łącza. Atrybut xlink:show może mieć cztery wartości predefiniowane:

Wartość

Opis

replace

Zamienia nowym zasobem zasób bieżący w aktualnym oknie, o ile takie istnieje.

new

Otwiera nowy obszar wyświetlania (na przykład nowe okno) dla nowego zasobu.

embed

Włącza wskazywany zasób do zasobu bieżącego.

undefined

Informuje, że nie wymagane jest żadne konkretne ustawienie atrybutu xlink:show.

Powyższe wartości atrybutu xlink:show są wartościami predefiniowanymi, ale nic nie stoi na przeszkodzie, aby stosować także swoje własne wartości.

Domyślne zachowanie łączy HTML polega na przeniesieniu się do wskazywanego dokumentu i zastąpienie nim dokumentu bieżącego. Takie zachowanie można zamodelować w XLinks używając wartości replace atrybutu xlink:show:

<PRZEGLĄD_FILMOWY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="simple"

xlink:show="replace"

xlink:href="http://www.starpowder.com/reviews.xml">

Pan Blandings buduje dom swoich marzeń

</PRZEGLĄD_FILMOWY>

Sposób traktowania tego przez aplikację zależy od użytego oprogramowania. Wprawdzie masz prawo się spodziewać, że bieżący dokument będzie zastąpiony nowym, może stać się inaczej. Na przykład aplikacja arkusza kalkulacyjnego może zastąpić wskazywanym zasobem wyświetlane dane, a nie całą zawartość bieżącego okienka. Atrybut xlink:show może też sprawić, że aplikacja użyje po uruchomieniu łącza innego arkusza stylów - to, co się stanie, zależy od programisty.

Jeśli wartością atrybutu xlink:show jest new, aktywacja łącza zwykle otwiera nowe okno ze wskazywanym zasobem:

<PRZEGLĄD_FILMOWY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="simple"

xlink:show="new"

xlink:href="http://www.starpowder.com/reviews.xml">

Pan Blandings buduje dom swoich marzeń

</PRZEGLĄD_FILMOWY>

Jednak tak jak poprzednio, oprogramowanie znowu może się różnie zachować. Wartość new może po prostu oznaczać dodanie nowej kolumny do tabeli lub wyświetlenie nowego wiersza zestawienia. Do tego ustawienia podchodzić należy ostrożnie - pamiętaj, że użytkownicy znający HTML nie przywykli do tego, że łącza automatycznie otwierają nowe okienka. Być może warto byłoby dodać jakieś objaśnienie, w przeciwnym wypadku tego typu zachowanie może być dla użytkownika niezrozumiałe.

Podobnie należy traktować ustawienie embed. Chodzi o to, aby przy aktywacji łącza nowy zasób włączany był do dokumentu bieżącego, ale sposób realizacji tego zależeć może od aplikacji. Załóżmy, że mamy do czynienia z następującym dokumentem planety.xml:

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

<?xml-stylesheet type="text/xml" href="planety.xsl"?>

<PLANETY>

<PLANETA>

<NAZWA>Merkury</NAZWA>

<MASA JEDNOSTKI="(Ziemia=1)">.0553</MASA>

<DZIEŃ JEDNOSTKI="dni">58.65</DZIEŃ>

<PROMIEŃ JEDNOSTKI="mile">1516</PROMIEŃ>

<GĘSTOŚĆ JEDNOSTKI="(Ziemia=1)">.983</GĘSTOŚĆ>

<ODLEGŁOŚĆ JEDNOSTKI="miliony mil">43.4<ODLEGŁOŚĆ><!--w peryhelium-->

</PLANETA>

<PLANETA>

<NAZWA>Wenus</NAZWA>

<MASA JEDNOSTKI="(Ziemia=1)">.815</MASA>

<DZIEŃ JEDNOSTKI="dni">116.75</DZIEŃ>

<PROMIEŃ JEDNOSTKI="mile">3716</PROMIEŃ>

<GĘSTOŚĆ JEDNOSTKI="(Ziemia=1)">.943</GĘSTOŚĆ>

<ODLEGŁOŚĆ JEDNOSTKI="miliony mil">66.8<ODLEGŁOŚĆ><!--w peryhelium-->

</PLANETA>

<PLANETA>

<NAZWA>Ziemia</NAZWA>

<MASA JEDNOSTKI="(Ziemia=1)">1</MASA>

<DZIEŃ JEDNOSTKI="dni">1</DZIEŃ>

<PROMIEŃ JEDNOSTKI="mile">2107</PROMIEŃ>

<GĘSTOŚĆ JEDNOSTKI="(Ziemia=1)">1</GĘSTOŚĆ>

<ODLEGŁOŚĆ JEDNOSTKI="miliony mil">128.4<ODLEGŁOŚĆ><!--w peryhelium-->

</PLANETA>

</PLANETY>

Oto jak mogą wyglądać łącza do różnych planet; używamy tu także XPointers do wskazania poszczególnych planet z pliku planety.xml. Wartością atrybutów xlink:show jest embed:

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

<ASTRO_NOWOŚCI>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="simple"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=1]">

Merkury

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="simple"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=2]">

Wenus

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="simple"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=3]">

Ziemia

</DANE_PLANETY>

</ASTRO_NOWOŚCI>

Po uruchomieniu wszystkich łączy z powyższego dokumentu dane z poszczególnych elementów PLANETA mogą zostać do bieżącego dokumentu włączone dając coś takiego (pamiętaj, że szczegółowa interpretacja zależy jednak od aplikacji!):

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

<ASTRO_NOWOŚCI>

<DANE_PLANETY>

<NAZWA>Merkury</NAZWA>

<MASA JEDNOSTKI="(Ziemia=1)">.0553</MASA>

<DZIEŃ JEDNOSTKI="dni">58.65</DZIEŃ>

<PROMIEŃ JEDNOSTKI="mile">1516</PROMIEŃ>

<GĘSTOŚĆ JEDNOSTKI="(Ziemia=1)">.983</GĘSTOŚĆ>

<ODLEGŁOŚĆ JEDNOSTKI="miliony mil">43.4<ODLEGŁOŚĆ><!--w peryhelium-->

</DANE_PLANETY>

<DANE_PLANETY>

<NAZWA>Wenus</NAZWA>

<MASA JEDNOSTKI="(Ziemia=1)">.815</MASA>

<DZIEŃ JEDNOSTKI="dni">116.75</DZIEŃ>

<PROMIEŃ JEDNOSTKI="mile">3716</PROMIEŃ>

<GĘSTOŚĆ JEDNOSTKI="(Ziemia=1)">.943</GĘSTOŚĆ>

<ODLEGŁOŚĆ JEDNOSTKI="miliony mil">66.8<ODLEGŁOŚĆ><!--w peryhelium-->

</DANE_PLANETY>

<DANE_PLANETY>

<NAZWA>Ziemia</NAZWA>

<MASA JEDNOSTKI="(Ziemia=1)">1</MASA>

<DZIEŃ JEDNOSTKI="dni">1</DZIEŃ>

<PROMIEŃ JEDNOSTKI="mile">2107</PROMIEŃ>

<GĘSTOŚĆ JEDNOSTKI="(Ziemia=1)">1</GĘSTOŚĆ>

<ODLEGŁOŚĆ JEDNOSTKI="miliony mil">128.4<ODLEGŁOŚĆ><!--w peryhelium-->

</DANE_PLANETY>

<ASTRO_NOWOŚCI>

Atrybutowi xlink:show można też nadać wartość undefined, wtedy aplikacja może zastosować własny domyślny sposób prezentacji zasobu docelowego łącza. Zresztą zawsze trzeba mieć na uwadze, że aplikacja może pracowicie poustawiane wartości xlink:show zignorować i zastosować własne, na przykład jeśli zastosowano wartości new, a przeglądarka nie jest w stanie obsłużyć wielu okienek.

Atrybutowi xlink:show możesz także nadawać własne wartości. Na przykład podanie wartości nowy_wiersz może spowodować wyświetlenie danych w nowym wierszu tabeli. Omawiany atrybut może też powiedzieć nieco o formacie dokumentu, a nie o sposobie jego wyświetlenia - stać się tak może, jeśli podasz jako wartość nazwę arkusza stylów. Możesz też przypisać temu atrybutowi kod JavaScriptu powodujący uruchomienie wartości atrybutu xlink:show w chwili aktywacji łącza.

Nie zapominaj o zadeklarowaniu atrybutu xlink:show w przypadku walidacji dokumentów. Deklaracja ta w DTD może wyglądać na przykład tak:

<!ELEMENT ASTRO_NOWOŚCI (#PCDATA)>

<!ATTLIST ASTRO_NOWOŚCI

xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"

xlink:type CDATA #FIXED "simple"

xlink:href CDATA #REQUIRED

xlink:show (new | replace | embed | undefined) #IMPLIED "replace">

Atrybut xlink:actuate

Atrybut xlink:actuate pozwala wskazać, kiedy łącze ma być uruchamiane. Atrybut ten może mieć następujące wartości predefiniowane:

Wartość

Opis

onRequest

Łącze ma być uruchamiane na żądanie użytkownika.

onLoad

Łącze ma być uruchamiane podczas ładowania dokumentu lub zasobu.

undefined

Nie narzuca się żadnych wymagań względem chwili uruchamiania łącza.

Atrybutowi temu można też nadawać własne wartości.

Pierwsza wartość predefiniowana, onRequest, oznacza, że łącze ma być uruchamiane dopiero wtedy, kiedy zażąda tego użytkownik. Zwykle żądanie takie zgłaszane jest przez kliknięcie łącza myszką, jak to zresztą ustawiliśmy na początku tego rozdziału symulując działanie łącza XLinks w Internet Explorerze:

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

<?xml-stylesheet type="text/css" href="xlink_example.css"?>

<!DOCTYPE html SYSTEM "xlink_example.dtd">

<DOKUMENT>

<P>

Zaczynamy sprawdzanie? kliknij

<LINK xml:type="simple" href="http://www.w3c.org"

xlink:actuate="onRequest"

onClick="location.href='http://www.w3c.org'">W3C</LINK>

</P>

</DOKUMENT>

Jeśli wartość atrybutu xlink:actuate ustawisz na onLoad, łącze zostanie uruchomione już w chwili ładowania zasobu zawierającego to łącze. Możemy na przykład spowodować, aby obrazek mapy był ładowany wraz z ładowaniem dokumentu go zawierającego - zrealizujemy to następująco:

<MAPA_OBRAZKOWA xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="simple"

xlink:href="http://www.starpowder.com/gifs/image_map.gif"

xlink:actuate="onLoad">

</MAPA_OBRAZKOWA>

W końcu użycie wartości undefined oznacza, że moment uruchomienia łącza pozostawiamy aplikacji (oczywiście, jak zwykle, i tak ostateczna interpretacja atrybutu xlink:actuate zależy od aplikacji).

Można jako wartości atrybutu xlink:actuate użyć własnych ustawień. Można na przykład zastosować wartości takie jak onLoadData, onShowImage czy onUnload.

Jak zwykle walidacja dokumentów wymaga zadeklarowania także atrybutu xlink:actuate; w przypadku użycia DTD może to wyglądać następująco:

<!ATTLIST ASTRO_NOWOŚCI

xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"

xlink:type CDATA #FIXED "simple"

xlink:href CDATA #REQUIRED

xlink:show (new | replace | embed | undefined) #IMPLIED "replace"

xlink:actuate (onRequest | onLoad | undefined) #IMPLIED "onRequest">

Łącza rozszerzone

Zapewne łącza proste i sposób ich działania są Ci już dobrze znane, gdyż działają one dokładnie tak samo jak hiperłącza HTML. Teraz czas na zapowiedziane już wcześniej rozszerzenia dostępne w XLinks - takie rozbudowane łącza noszą nazwę łączy rozszerzonych. Tego typu łącza mogą wiązać ze sobą wiele zasobów, obsługiwać różne ścieżki połączenia zasobów, ścieżki dwukierunkowe i łącza zewnętrzne. W tej chwili warto spróbować się przestawić na znacznie ogólniejszy sposób myślenia, spojrzeć na łącza jako wszystkie możliwe relacje między zasobami.

Terminologia łączy rozszerzonych

Omawiane tutaj idee mogą wydawać się bardzo niejasne w porównaniu z dobrze znanym działaniem tradycyjnych łączy prostych, ale pamiętaj, że W3C usiłuje umożliwić opisanie za pomocą XML wszelkich relacji między wieloma zasobami oraz opisanie działania tych relacji. Jest to naprawdę duże wyzwanie. Z formalnego punktu widzenia łącza rozszerzone są skierowanymi grafami z nazwami. Łączone zasoby są węzłami, a same łącza między nimi są krawędziami grafu.

Ogólnie rzecz biorąc łącza rozszerzone składają się z połączeń między zbiorem zasobów. Zasoby mogą być lokalne, czyli być częścią elementu łącza rozszerzonego lub zdalne, czyli być poza elementem łącza rozszerzonego (co jednak wcale nie znaczy, że muszą należeć do innego dokumentu). Jeśli łącze nie zawiera żadnego zasobu lokalnego, nazywane jest łączem zewnętrznym.

Sposób obsługi łączy zewnętrznych jest całkowicie zależne od aplikacji. Pokażę tutaj pewne zasady, ale tak naprawdę wszystko to są trochę zamki budowane na piasku. O ile mi wiadomo, nie istnieje obecnie żadne powszechnie dostępne oprogramowanie w pełni obsługujące łącza rozszerzone.

Hipotetycznym przykładem może być system ekspertowy, w którym łącza między wieloma różnymi zasobami są uruchamiane w zależności od odpowiedzi na pytania tak/nie. Chodzi o to, że po odpowiedzi na szereg pytań system ekspertowy może zawężać zakres możliwych odpowiedzi i skierować użytkownika do zasobu, który najlepiej udzieli odpowiedzi na nawet bardzo złożone zapytania.

Jak wspomniano wcześniej, zasoby należące do łącza rozszerzonego mogą być albo lokalne, albo zdalne. Zasoby lokalne same są częścią łącza rozszerzonego i zawarte są w elemencie, którego atrybut xlink:type ustawiono na resource.

Zasoby zdalne z kolei znajdują się poza elementem łącza, choć nie muszą wcale znajdować się w innym dokumencie. Elementów lokalizujących używa się do wskazania zasobu zdalnego; takie elementy mają atrybut xlink:type o wartości locator. Podczas tworzenia elementu lokalizującego (lokalizatora) trzeba nadać także atrybutowi xlink:href wartość wskazującą zasób zdalny.

Oto przykład łącza rozszerzonego. Łącze to zawiera pięć zasobów - dwa łącza inline i trzy łącza zewnętrzne:

<ASTRO_DANE xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="extended" xlink:title="Dane planet">

<NAZWA xlink:type="resource" xlink:role="NAZWA">

Dane planet

</NAZWA>

<DATA xlink:type="resource" xlink:role="OSTATNIA_AKTUALIZACJA">

1 września 2001r.

</DATA>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=1]"

xlink:title="Merkury"

xlink:role="DANE_PLANETY">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=2]">

xlink:title="Wenus"

xlink:role="DANE_PLANETY">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=3]">

xlink:title="Ziemia"

xlink:role="DANE_PLANETY">

</DANE_PLANETY>

</ASTRO_DANE>

Łącza inline to łącza, które mają atrybut xlink:type o wartości resource, a zasoby tych łącz zawarte są w elemencie łączącym. W tym wypadku takimi łączami są elementy NAZWA oraz DATA; oba zawierają zasób lokalny (w tym wypadku jest to po prostu tekst, choć może tu być także cały ciąg wzajemnie w sobie zawartych elementów).

Łącza zewnętrzne naszego przykładu mają atrybut xlink:type o wartości locator. Łącza te służą do lokalizowania zasobów zewnętrznych, które mogą być w tym samym dokumencie lub w innym. W tym przykładzie wszystkie te zasoby znajdują się w innym dokumencie, planety.xml.

Tak jak poprzednio walidacja dokumentów wymaga zadeklarowania używanych elementów i atrybutów. W naszym przykładzie można dodać następującą DTD:

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

<!DOCTYPE ASTRO_DANE [

<!ELEMENT ASTRO_DANE (NAZWA, DATA, DANE_PLANETY*)>

<!ATTLIST ASTRO_DANE

xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"

xlink:type (extended) #FIXED "extended"

xlink:title CDATA #IMPLIED

xlink:role CDATA #IMPLIED>

<!ELEMENT NAZWA (#PCDATA)>

<!ATTLIST NAZWA

xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"

xlink:type CDATA #FIXED "resource"

xlink:title CDATA #IMPLIED

xlink:role CDATA #IMPLIED>

<!ELEMENT DATA (#PCDATA)>

<!ATTLIST DATA

xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"

xlink:type CDATA #FIXED "resource"

xlink:title CDATA #IMPLIED

xlink:role CDATA #IMPLIED>

<!ELEMENT DANE_PLANETY (#PCDATA)>

<!ATTLIST DANE_PLANETY

xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"

xlink:type CDATA #FIXED "locator"

xlink:href CDATA #IMPLIED

xlink:role CDATA #IMPLIED

xlink:title CDATA #IMPLIED

xlink:show CDATA #IMPLIED>

]>

<ASTRO_DANE xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="extended" xlink:title="Dane planet">

<NAZWA xlink:type="resource" xlink:role="NAZWA">

Dane planet

</NAZWA>

<DATA xlink:type="resource" xlink:role="OSTATNIA_AKTUALIZACJA">

1 września 2001r.

</DATA>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=1]"

xlink:title="Merkury"

xlink:role="DANE_PLANETY">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=2]">

xlink:title="Wenus"

xlink:role="DANE_PLANETY">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=3]">

xlink:title="Ziemia"

xlink:role="DANE_PLANETY">

</DANE_PLANETY>

</ASTRO_DANE>

Jak dotąd jedynie wskazywaliśmy, jakie elementy należące do łącze rozszerzonego reprezentują zasoby lokalne lub zdalne. Jednak użycie atrybutów xlink:from i xlink:to pozwala stworzenie łączy skierowanych nazywanych łukami.

Tworzenie łuków przy pomocy atrybutów xlink:from i xlink:to

W przypadku łączy prostych nie ma wątpliwości, gdzie należy się przenieść po uruchomieniu łącza - wskazuje to atrybut xlink:href. Jednak w przypadku łączy złożonych sprawa się komplikuje - jeśli na przykład chcesz uruchomić łącze pokazane w ostatnim przykładzie, gdzie powinieneś się znaleźć? Mamy tu do czynienia ze wszelkiego rodzaju ścieżkami między różnymi zasobami.

Każda możliwa ścieżka między każdymi dwoma zasobami nazywana jest łukiem. Łuki w elementach XML reprezentowane są przez dodanie atrybutu xlink:type o wartości arc.

Aby wskazać sposób działania łuku, używa się atrybutów xlink:show oraz xlink:actuate. Ważna rzecz: łuki mają także atrybuty xlink:from i xlink:to wskazujące łączone zasoby. Wartości tych atrybutów ustawia się tak, by odpowiadały atrybutom xlink:role zasobu źródłowego i docelowego.

Poniżej pokazano poprzedni przykład, przy czym element NAZWA zamieniono na START oraz opisano trzy łuki: jeden z elementu START do wszystkich trzech elementów DANE_PLANETY (poszczególne łuki łączą jeden element początkowy z jednym końcowym). Łuki zawarto w elementach PRZEGLĄD:

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

<ASTRO_DANE xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="extended" xlink:title="Dane planet">

<START xlink:type="resource" xlink:role="START">

Dane planet

</START>

<DATA xlink:type="resource" xlink:role="OSTATNIA_AKTUALIZACJA">

1 września 2001r.

</DATA>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=1]"

xlink:title="Merkury"

xlink:role="Merkury">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=2]">

xlink:title="Wenus"

xlink:role="Wenus">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=3]">

xlink:title="Ziemia"

xlink:role="Ziemia">

</DANE_PLANETY>

<PRZEGLĄD xlink:type="arc xlink:from="START"

xlink:to="Merkury" xlink:show="new"

xlink:actuate="onRequest">

</PRZEGLĄD>

<PRZEGLĄD xlink:type="arc xlink:from="START"

xlink:to="Wenus" xlink:show="new"

xlink:actuate="onRequest">

</PRZEGLĄD>

<PRZEGLĄD xlink:type="arc xlink:from="START"

xlink:to="Ziemia" xlink:show="new"

xlink:actuate="onRequest">

</PRZEGLĄD>

</ASTRO_DANE>

Jak zwykle walidacja dokumentów wymaga zadeklarowania wszystkich elementów i atrybutów. W przypadku używania DTD może to wyglądać tak oto:

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

<!DOCTYPE ASTRO_DANE [

<!ELEMENT ASTRO_DANE (START, DATA, DANE_PLANETY*, PRZEGLĄD*)>

<!ATTLIST ASTRO_DANE

xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"

xlink:type (extended) #FIXED "extended"

xlink:title CDATA #IMPLIED

xlink:role CDATA #IMPLIED>

<!ELEMENT START (#PCDATA)>

<!ATTLIST START

xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"

xlink:type CDATA #FIXED "resource"

xlink:title CDATA #IMPLIED

xlink:role CDATA #IMPLIED>

<!ELEMENT DATA (#PCDATA)>

<!ATTLIST DATA

xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"

xlink:type CDATA #FIXED "resource"

xlink:title CDATA #IMPLIED

xlink:role CDATA #IMPLIED>

<!ELEMENT DANE_PLANETY (#PCDATA)>

<!ATTLIST DANE_PLANETY

xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"

xlink:type CDATA #FIXED "locator"

xlink:href CDATA #IMPLIED

xlink:role CDATA #IMPLIED

xlink:title CDATA #IMPLIED

xlink:show CDATA #IMPLIED>

<!ELEMENT PRZEGLĄD (#PCDATA)>

<!ATTLIST PRZEGLĄD

xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"

xlink:type CDATA #FIXED "arc"

xlink:from CDATA #IMPLIED

xlink:to CDATA #IMPLIED

xlink:show CDATA #IMPLIED

xlink:actuate (onRequest | onLoad | undefined) #IMPLIED>

]>

<ASTRO_DANE xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="extended" xlink:title="Dane planet">

<START xlink:type="resource" xlink:role="START">

Dane planet

</START>

<DATA xlink:type="resource" xlink:role="OSTATNIA_AKTUALIZACJA">

1 września 2001r.

</DATA>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=1]"

xlink:title="Merkury"

xlink:role="Merkury">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=2]">

xlink:title="Wenus"

xlink:role="Wenus">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=3]">

xlink:title="Ziemia"

xlink:role="Ziemia">

</DANE_PLANETY>

<PRZEGLĄD xlink:type="arc xlink:from="START"

xlink:to="Merkury" xlink:show="new"

xlink:actuate="onRequest">

</PRZEGLĄD>

<PRZEGLĄD xlink:type="arc xlink:from="START"

xlink:to="Wenus" xlink:show="new"

xlink:actuate="onRequest">

</PRZEGLĄD>

<PRZEGLĄD xlink:type="arc xlink:from="START"

xlink:to="Ziemia" xlink:show="new"

xlink:actuate="onRequest">

</PRZEGLĄD>

</ASTRO_DANE>

Łuki nie muszą koniecznie odwoływać się do jednego tylko zasobu, jak to było w poprzednim przykładzie. Możemy też wszystkim trzem elementom DANE_PLANETY przypisać tę samą rolę DANE_PLANETY i później za pomocą jednego elementu PRZEGLĄD zdefiniować trzy łuki: po jednym do każdego zasobu DANE_PLANETY:

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

<ASTRO_DANE xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="extended" xlink:title="Dane planet">

<START xlink:type="resource" xlink:role="START">

Dane planet

</START>

<DATA xlink:type="resource" xlink:role="OSTATNIA_AKTUALIZACJA">

1 września 2001r.

</DATA>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=1]"

xlink:title="Merkury"

xlink:role="DANE_PLANETY">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=2]">

xlink:title="Wenus"

xlink:role="DANE_PLANETY">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=3]">

xlink:title="Ziemia"

xlink:role="DANE_PLANETY">

</DANE_PLANETY>

<PRZEGLĄD xlink:type="arc xlink:from="START"

xlink:to="DANE_PLANETY" xlink:show="new"

xlink:actuate="onRequest">

</PRZEGLĄD>

</ASTRO_DANE>

Tak naprawdę można pomijać atrybuty xlink:from i xlink:to - wtedy łuki tworzone są między danym elementem a elementami lokalizującymi danego łącza rozszerzonego (mogą one zawierać także elementy bez atrybutów xlink:from i xlink:to).

Sposób faktycznej interpretacji atrybutów xlink:from i xlink:to zależy od aplikacji odczytującej zawierający je dokument.

Łącza inline a łącza zewnętrzne

Jeśli łącze nie zawiera żadnych łączonych przez się zasobów, nazywamy je łączem zewnętrznym. Możliwość oddzielenia łączy od łączonych zasobów to naprawdę duży krok naprzód (to samo było motywem zasadniczej zmiany w HTML 4.0 polegającej na stosowaniu arkuszy stylów zamiast specjalizowanych znaczników jak <CENTER>; to samo dotyczy zewnętrznych modułów kodu w Internet Explorerze nazywanych zachowaniami). Użycie łączy zewnętrznych ma wiele zalet.

Łącza zewnętrzne mogą znajdować się w odrębnych dokumentach nazywanych bazami łączy. Zbiór łączy zewnętrznych w bazie łączy nazywany jest zbiorem łączy.

Oto przykład - wszystkie łącza z tego dokumentu wskazują na zasoby do tego dokumentu nie należące, zatem dokument ten jest bazą łączy:

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

<ASTRO_DANE xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="extended" xlink:title="Dane planet">

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml"

xlink:title="START"

xlink:role="START">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=1]"

xlink:title="Merkury"

xlink:role="Merkury">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=2]">

xlink:title="Wenus"

xlink:role="Wenus">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=3]">

xlink:title="Ziemia"

xlink:role="Ziemia">

</DANE_PLANETY>

<PRZEGLĄD xlink:type="arc xlink:from="START"

xlink:to="Merkury" xlink:show="new"

xlink:actuate="onRequest">

</PRZEGLĄD>

<PRZEGLĄD xlink:type="arc xlink:from="START"

xlink:to="Wenus" xlink:show="new"

xlink:actuate="onRequest">

</PRZEGLĄD>

<PRZEGLĄD xlink:type="arc xlink:from="START"

xlink:to="Ziemia" xlink:show="new"

xlink:actuate="onRequest">

</PRZEGLĄD>

</ASTRO_DANE>

Wszystkie łączone zasoby znajdują się poza bieżącym dokumentem. Dodaliśmy łącza lokalizujące do wszystkich planet z dokumentu planety.xml oraz łuki od punktu wejściowego do poszczególnych planet. Zwykle w bazie łączy używa się trzech rodzajów łączy: łączy rozszerzonych, lokalizatorów i łuków. Nie mogą wystąpić żadne łącza typu resource.

Bazy łączy podlegają takim samym regułom jak wszelkie inne dokumenty XML, wobec czego walidacja ich wymaga dodania DTD:

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

<!DOCTYPE ASTRO_DANE [

<!ELEMENT ASTRO_DANE (DANE_PLANETY*, PRZEGLĄD*)>

<!ATTLIST ASTRO_DANE

xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"

xlink:type (extended) #FIXED "extended"

xlink:title CDATA #IMPLIED

xlink:role CDATA #IMPLIED>

<!ELEMENT DANE_PLANETY (#PCDATA)>

<!ATTLIST DANE_PLANETY

xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"

xlink:type CDATA #FIXED "locator"

xlink:href CDATA #REQUIRED

xlink:role CDATA #IMPLIED

xlink:title CDATA #IMPLIED

xlink:show CDATA #IMPLIED>

<!ELEMENT PRZEGLĄD (#PCDATA)>

<!ATTLIST PRZEGLĄD

--> xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"[Author:T]

xlink:type CDATA #FIXED "arc"

xlink:from CDATA #IMPLIED

xlink:to CDATA #IMPLIED

xlink:show CDATA #IMPLIED

xlink:actuate (onRequest | onLoad | undefined) #IMPLIED>

]>

<ASTRO_DANE xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="extended" xlink:title="Dane planet">

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml"

xlink:title="START"

xlink:role="START">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=1]"

xlink:title="Merkury"

xlink:role="Merkury">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=2]">

xlink:title="Wenus"

xlink:role="Wenus">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=3]">

xlink:title="Ziemia"

xlink:role="Ziemia">

</DANE_PLANETY>

<PRZEGLĄD xlink:type="arc xlink:from="START"

xlink:to="Merkury" xlink:show="new"

xlink:actuate="onRequest">

</PRZEGLĄD>

<PRZEGLĄD xlink:type="arc xlink:from="START"

xlink:to="Wenus" xlink:show="new"

xlink:actuate="onRequest">

</PRZEGLĄD>

<PRZEGLĄD xlink:type="arc xlink:from="START"

xlink:to="Ziemia" xlink:show="new"

xlink:actuate="onRequest">

</PRZEGLĄD>

</ASTRO_DANE>

Zbiory łączy zewnętrznych można dowolnie rozbudowywać. W poniższym przykładzie dodano łącza POPRZEDNIA i NASTĘPNA między poszczególnymi planetami:

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

<ASTRO_DANE xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="extended" xlink:title="Dane planet">

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml"

xlink:title="START"

xlink:role="START">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=1]"

xlink:title="Merkury"

xlink:role="Merkury">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=2]">

xlink:title="Wenus"

xlink:role="Wenus">

</DANE_PLANETY>

<DANE_PLANETY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="locator"

xlink:show="embed"

xlink:href="http://www.starpowdermovies.com/planety.xml#

xpointer(/descendant::PLANETA[position()=3]">

xlink:title="Ziemia"

xlink:role="Ziemia">

</DANE_PLANETY>

<PRZEGLĄD xlink:type="arc xlink:from="START"

xlink:to="Merkury" xlink:show="new"

xlink:actuate="onRequest">

</PRZEGLĄD>

<PRZEGLĄD xlink:type="arc xlink:from="START"

xlink:to="Wenus" xlink:show="new"

xlink:actuate="onRequest">

</PRZEGLĄD>

<PRZEGLĄD xlink:type="arc xlink:from="START"

xlink:to="Ziemia" xlink:show="new"

xlink:actuate="onRequest">

</PRZEGLĄD>

<NASTĘPNA xlink:type="arc" xlink:from="Merkury"

xlink:to="Wenus" xlink:show="new"

xlink:actuate="onRequest">

</NASTĘPNA>

<NASTĘPNA xlink:type="arc" xlink:from="Wenus"

xlink:to="Ziemia" xlink:show="new"

xlink:actuate="onRequest">

</NASTĘPNA>

<NASTĘPNA xlink:type="arc" xlink:from="Ziemia"

xlink:to="Merkury" xlink:show="new"

xlink:actuate="onRequest">

</NASTĘPNA>

<POPRZEDNIA xlink:type="arc" xlink:from="Ziemia"

xlink:to="Wenus" xlink:show="new"

xlink:actuate="onRequest">

</POPRZEDNIA>

<POPRZEDNIA xlink:type="arc" xlink:from="Wenus"

xlink:to="Merkury" xlink:show="new"

xlink:actuate="onRequest">

</POPRZEDNIA>

<POPRZEDNIA xlink:type="arc" xlink:from="Merkury"

xlink:to="Ziemia" xlink:show="new"

xlink:actuate="onRequest">

</POPRZEDNIA>

</ASTRO_DANE>

Pojawia się tutaj kolejna wątpliwość: skoro łącza zewnętrzne nie są zawarte w żadnym ze wskazywanych zasobów, jak oprogramowanie ma je odnaleźć? W tym wypadku specyfikacja W3C jest dość niejasna, podobnie jak w przypadku łączenia z dokumentami XML zewnętrznych arkuszy stylów. Zakłada się, że aplikacja sama będzie odpowiedzialna za odnalezienie odpowiednich baz łączy.

Trzeba przyznać, że trudno sobie wyobrazić, jak aplikacja ma odnajdować bazy łączy, jeśli znaczniki i treść mają być całkowicie oddzielne, zatem nie można bazy łączy wstawić do żadnego ze wskazywanych z zasobów (to tak, jak w przypadku komentowania czyjejś pracy, kiedy nie masz dostępu do dokumentu źródłowego).

Jeśli jesteś w stanie dodać w zasobie łącze do bazy łączy, W3C sugeruje zrobienie tego: w celu utworzenia w bazie łączy można użyć predefiniowanej roli xlink:external-linkbase:

<ŁĄCZA_ZEWNĘTRZNE xlink:type="simple"

xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:role="xlink:external-linkset"

xlink:href="baza_łączy.xml"/>

</ŁĄCZA_ZEWNĘTRZNE>

--> [Author:T]

Dotąd w tym rozdziale mówiliśmy o tym, że atrybutu xlink:href używa się do wskazania zasobów. Jednak możliwości są tutaj naprawdę duże: nie tylko można podać tutaj URI, ale można także użyć wskaźników XPointers do wybrania konkretnych miejsc w dokumencie lub jego fragmentów. --> Zanim jednak przejdziemy do omawiania specyfikacji XPointer, powiedzieć należy nieco o specyfikacji XPath, która jest podstawą XPointer i bez której trudno będzie tę ostatnią zrozumieć.[Author:T]

Wyrażenia XPath to silne narzędzie pozwalające dobierać węzły dokumentu. Użycie XPath nie oznacza ograniczenia się do węzła bieżącego i jego węzłów potomnych, można też wskazywać węzeł rodzica, przodków i tak dalej. Wskazywanie węzła, względem którego chcesz pracować, nazywamy w XPath określeniem osi --> .[Author:T]

--> Zrozumieć XPath[Author:T]

Do wskazania w XPath węzła lub zbioru węzłów używa się ścieżki lokalizacji. Ścieżka ta z kolei składa się z jednego lub więcej kroków lokalizacji oddzielanych od siebie znakami / lub //. Jeśli ścieżka zaczyna się od /, nazywamy ją ścieżką bezwzględną, gdyż całą ścieżkę podaje się względem węzła głównego. W przeciwnym wypadku ścieżkę nazywamy względną, zaczyna się ona od bieżącego węzła nazywanego węzłem kontekstowym. Wszystko jasne? To dobrze, bo to dopiero początek.

Krok lokalizacji składa się z osi, badania węzła oraz zera lub więcej predykatów. Jeśli na przykład wyrażenie ma postać child::PLANETA[position()=5], nazwą osi jest child, badanie węzła to wyrażenie PLANETA, natomiast zapis [position()=5] to predykat. Ścieżki lokalizacji składać się mogą z jednego lub więcej kroków lokalizacji, na przykład /descendant::PLANET/child::NAZWA wybiera elementy NAZWA mające rodzica PLANETA. Najlepszym sposobem zrozumienia, jak to działa, jest obejrzenie przykładów i na następnych stronach takich przykładów będzie mnóstwo. Przyjrzymy się rodzajom obsługiwanych w XPath osi, sposobów badania węzłów i predykatów.

Osie XPath

W ścieżce lokalizacji XPath child::NAZWA wskazującej element NAZWA będącym dzieckiem węzła bieżącego, child (dziecko) nazywamy osią. W XPath obsługiwane są też różne inne osie i konieczna jest ich znajomość:

Opis

ancestor

Dotyczy przodków węzła kontekstowego. Przodkami są rodzice węzła kontekstowego, rodzice tych rodziców i tak dalej, aż po węzeł główny włącznie.

ancestor-or-self

Dotyczy węzła kontekstowego i jego przodków.

attribute

Dotyczy atrybutów węzła kontekstowego.

child

Dotyczy dzieci węzła kontekstowego.

descendant

Dotyczy potomków węzła kontekstowego. Potomek to dziecko, dziecko dziecka i tak dalej.

descendant-or-self

Dotyczy węzła kontekstowego i jego potomków.

following

Dotyczy wszystkich węzłów z dokumentu, do którego należy węzeł kontekstu, które znajdują się po nim.

following-sibling

Dotyczy wszystkich węzłów znajdujących się na tym samym poziomie co węzeł kontekstu, za tym węzłem.

namespace

Dotyczy węzłów przestrzeni nazw węzła kontekstu.

parent

Dotyczy węzła rodzica węzła kontekstowego.

preceding

Dotyczy wszystkich węzłów z dokumentu, do którego należy węzeł kontekstu, które znajdują się przed nim.

preceding-sibling

Dotyczy wszystkich węzłów znajdujących się na tym samym poziomie co węzeł kontekstu, przed tym węzłem.

self

Zawiera węzeł kontekstowy.

Osie można wskazywać w każdym kroku lokalizacji lub ścieżce. Poniższy przykład przedstawia arkusz stylów XSL, w którym atrybutowi select elementu xsl:value-of przypisano wyrażenia XPath. Użyto osi child do poinformowania, że chodzi o wybranie węzłów dzieci węzła kontekstu, którym jest element PLANETA (dalej pokażemy zapis skrótowy pozwalający pomijać część child::):

<xsl:template match="PLANETA">

<HTML>

<CENTER>

<xsl:value-of select="child::NAZWA"/>

</CENTER>

<CENTER>

<xsl:value-of select="child::MASA"/>

</CENTER>

<CENTER>

<xsl:value-of select="child::DZIEŃ"/>

</CENTER>

</HTML>

</xsl:template>

W powyższych wyrażeniach osią jest child, nazwy elementów NAZWA, MASA i DZIEŃ są badaniami węzłów (lub testami węzłów).

Badanie węzłów w XPath

Jako testów węzłów można użyć nazw węzłów, można też użyć znaku * do wybrania wszystkich elementów. Na przykład wyrażenie child::*/child::NAZWA powoduje wybranie elementów NAZWA będących „wnukami” węzła kontekstu. Można też użyć innych testów:

Test węzła

Opis

comment()

Wybiera węzły komentarza.

node()

Wybiera węzły dowolnego typu.

processing-instruction()

Wybiera węzły instrukcji przetwarzania. W nawiasach można podać także nazwę instrukcji.

text()

Wybiera węzły tekstowe.

Predykaty XPath

Predykat należący do kroku XPath jest zapewne najciekawszą częścią tego kroku, gdyż zapewnia największą elastyczność. W predykatach można użyć wszystkiego rodzaju wyrażeń - oto dopuszczalne typy:

Teraz kolejno wszystkim rodzajom się przyjrzymy.

Zbiory węzłów XPath

Zbiór węzłów - jak to wskazuje sama nazwa - to po prostu zbiór węzłów. Wyrażenie takie jak child::PLANETA zwraca zbiór węzłów elementów PLANETA. Wyrażenie child::PLANETA/child::NAZWA zwraca listę węzłów elementów NAZWA będących dziećmi elementów PLANETA. Do wybrania ze zbioru węzła lub węzłów można użyć różnych funkcji używanych w predykatach:

Funkcja

Opis

last()

Zwraca liczbę węzłów w zbiorze.

position()

Zwraca położenie węzła kontekstowego w zbiorze węzła kontekstowego (zliczanie zaczyna się od 1).

count(zbiór-węzłów)

Zwraca liczbę węzłów w przekazanym zbiorze. Jeśli argument nie zostanie podany, zliczone zostaną węzły zbioru węzła kontekstowego.

id(string ID)

Zwraca zbiór węzłów zawierających element o identyfikatorze pasującym do wartości przekazanej funkcji, a jeśli elementów takich nie ma, zwraca pusty zbiór węzłów. Można podać zestaw identyfikatorów rozdzielonych spacjami, a funkcja zwróci zbiór węzłów elementów z takimi identyfikatorami.

local-name(zbiór-węzłów)

Zwraca nazwę lokalną pierwszego węzła ze zbioru węzłów. Pominięcie parametru powoduje uruchomienie funkcji na węźle kontekstu.

namespace-uri(zbiór-węzłów)

Zwraca adres URI przestrzeni nazw pierwszego węzła ze zbioru. Pominięcie parametru powoduje użycie przez funkcję węzła kontekstu.

name(zbiór-węzłów)

Zwraca pełną, kwalifikowaną nazwę pierwszego węzła ze zbioru. Pominięcie parametru powoduje użycie przez funkcję węzła kontekstu.

Oto przykład, w którym ponumerujemy elementy dokumentu wynikowego przy użyciu funkcji position():

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="PLANETY">

<HTML>

<HEAD>

<TITLE>

Planety

</TITLE>

</HEAD>

<BODY>

<xsl:apply-templates select="PLANETA"/>

</BODY>

</HTML>

</xsl:template>

<xsl:template match="PLANETA">

<P>

<xsl:value-of select="position()"/>

<xsl:value-of select="NAZWA"/>

</P>

</xsl:template>

</xsl:stylesheet>

Oto wyniki - planety z dokumentu XML zostały ponumerowane:

<HTML>

<HEAD>

<TITLE>

Planety

</TITLE>

</HEAD>

<BODY>

<P>1.

Merkury</P>

<P>2.

Wenus</P>

<P>3.

Ziemia</P>

</BODY>

</HTML>

Funkcji działających na zbiorach węzłów można używać w predykatach, na przykład wyrażenie child::PLANETA[position()=last()] wybierze ostatnie dziecko PLANETA z węzła kontekstowego.

Wyrażenia logiczne XPath

W wyrażeniach XPath można używać także wyrażeń logicznych. Liczba uważana jest za fałsz, jeśli równa jest zeru i uważana jest za prawdę w każdym innym przypadku. Napis pusty ("") uważany jest za fałsz, wszystkie inne napisy odpowiadają prawdzie.

Operatory logiczne XPath umożliwiają wyliczenie wartości typu prawda/fałsz:

Operator

Opis

!=

różne

<

mniejsze (w dokumentach XML zapisywać należy jako &lt;)

<=

mniejsze bądź równe (w dokumentach XML zapisywać należy jako &lt;=)

=

równe (uwaga dla programistów języków C, C++, Java, JavaScript: nie należy używać podwójnego znaku równości)

>

większe

>=

większe bądź równe

W dokumentach XML nie należy używać znaku < bezpośrednio, lecz należy używać odwołania do encji &lt;.

Poszczególne elementy wyrażenia logicznego łączyć można spójnikami and i or podobnie jak to robiliśmy w JavaScripcie i Javie.

Oto przykład użycia operatora logicznego > - reguła dotyczy wszystkich elementów PLANETA o numerze większym od 5:

<xsl:template match="PLANETA[position() > 5]">

<xsl:value-of select="."/>

</xsl:template>

Istnieją też funkcje true() i false() zwracające zawsze wartości odpowiednio prawdy i fałszu.

Funkcji not() można użyć do odwrócenia logicznej wartości wyrażenia; poniżej wybieramy wszystkie elementy PLANETA oprócz ostatniego:

<xsl:template match="PLANETA[not(position() = last())]">

<xsl:value-of select="."/>

</xsl:template>

W końcu funkcja lang() zwraca wartość prawdy lub fałszu w zależności od tego, czy język węzła kontekstu (określony atrybutem xml:lang) jest taki sam, jak język przekazany tej funkcji jako parametr.

Liczby w XPath

Liczby w XPath zapisywane są jako zmiennoprzecinkowe liczby podwójnej precyzji (w rozdziale 10 podano nieco więcej szczegółów technicznych; formalnie rzecz biorąc liczby XPath przechowywane są w formacie zmiennoprzecinkowym podwójnej precyzji IEEE 754). W takiej postaci przechowywane są wszystkie liczby, nawet liczby całkowite jak 5 w poniższym przykładzie:

<xsl:template match="PLANETA[position() > 5]">

<xsl:value-of select="."/>

</xsl:template>

Do przetwarzania liczb można użyć kilku operatorów:

Operator

Działanie

+

dodawanie

-

odejmowanie

*

mnożenie

div

dzielenie (znak / zwykle oznaczający to działanie jest w XML i XPath intensywnie wykorzystywany w innych celach)

mod

modulo (reszta z dzielenia pierwszego argumentu przez drugi)

Na przykład użycie zapisu <xsl:value-of select="180 + 420"/> wstawia napis 600 do dokumentu wynikowego. Przykład ten wybiera wszystkie planety, których dzień (mierzony dniami ziemskimi) podzielony przez masę (podaną w masach Ziemi) daje wynik większy od 100:

<xsl:template match="PLANETA">

<HTML>

<BODY>

<xsl:apply-templates select="PLANETA[DZIEŃ div MASA > 100]"/>

</BODY>

</HTML>

</xsl:template>

XPath obsługuje także kilka funkcji działających na liczbach:

Funkcja

Opis

ceiling()

Zwraca najmniejszą liczbę całkowitą większą od liczby przekazanej jako parametr.

floor()

Zwraca największą liczbę całkowitą mniejszą od liczby przekazanej jako parametr.

round()

Zaokrągla przekazaną liczbę do najbliższej liczby całkowitej.

sum()

Zwraca sumę przekazanych funkcji liczb.

W poniższym przykładzie określamy średnią masę planet z dokumentu planety.xml:

<xsl:template match="PLANETY">

<HTML>

<BODY>

Średnia masa planet wynosi:

<xsl:value-of select="sum(child::MASA)

div count(descendant::MASA)"/>

</BODY>

</HTML>

</xsl:template>

Napisy w XPath

Napisy XPath składają się ze znaków Unicode. Istnieje wiele takich funkcji, zestawiono je w poniższej tabeli:

Funkcja

Opis

starts-with(string napis1, string napis2)

Zwraca prawdę, jeśli pierwszy napis zaczyna się drugim napisem.

contains(string napis1, string napis2)

Zwraca prawdę, jeśli pierwszy napis zawiera drugi.

substring(string napis1, number ofset, number ilość)

Zwraca ilość znaków z przekazanego napisu od znaku ofset poczynając.

substring-before(string napis1, string napis2)

Zwraca część napisu1 do pierwszego wystąpienia napisu2.

substring-after(string napis1, string napis2)

Zwraca część napisu1 od pierwszego wystąpienia napisu2 poczynając.

string-length(string napis1)

Zwraca liczbę znaków w napisie1.

normalize-space(string napis1)

Zwraca napis1 po usunięciu spacji wiodących i końcowych oraz po zamianie wszystkich ciągów kolejnych spacji na pojedyncze.

translate(string napis1, string napis2, string napis3)

Zwraca napis1 po zastąpieniu wszystkich wystąpień napis2 napisami napis3.

concat(string napis1, string napis2, ...)

Zwraca wszystkie przekazane napisy połączone w całość.

format-number(number liczba1, string napis2, string napis3)

Zwraca napis zawierający sformatowaną liczbę1, przy czym napis2 używany jest jako ciąg formatujący, natomiast napis3 to opcjonalne ustawienie językowe. Ciągi formatujące są takie same, jak w metodzie Javy java.text.DecimalFormat.

Wynikowe fragmenty drzewa w XPath

Wynikowy fragment drzewa to część dokumentu XML nie będąca kompletnym węzłem ani kompletnym zestawem węzłów. Fragmenty takie mogą być tworzone na różne sposoby, na przykład w przypadku użycia funkcji document() podczas wskazywania czegoś w innym dokumencie.

W XPath niewiele można zrobić z wynikowymi fragmentami drzewa XPath; tak naprawdę można jedynie użyć funkcji string() lub boolean() do zamiany ich odpowiednio na napis lub wartość logiczną.

Przykłady wyrażeń XPath

Już nieźle znasz teorię XPath, teraz czas na jakieś konkretne przykłady. W poniższej tabeli podano szereg przykładów ścieżek z objaśnieniem ich działania. Zwróć uwagę na to, że w predykatach można użyć operatorów and i or do połączenia ze sobą wielu wzorców.

Przykład

Znaczenie

child::PLANETA

Zwraca elementy PLANETA będące dziećmi węzła (czyli węzła kontekstowego).

child::*

Zwraca wszystkie dzieci bieżącego węzła będące elementami.

child::text()

Zwraca wszystkie dzieci bieżącego węzła będące węzłami tekstowymi.

child::node()

Zwraca wszystkie dzieci bieżącego węzła niezależnie od ich typu.

attribute::JEDNOSTKI

Zwraca atrybut JEDNOSTKI bieżącego węzła.

descendant::PLANETA

Zwraca wszystkie elementy PLANETA będące dziećmi węzła kontekstu.

ancestor::PLANETA

Zwraca wszystkich przodków PLANETA węzła kontekstu.

ancestor-or-self::PLANETA

Zwraca wszystkich przodków PLANETA węzła kontekstowego. Jeśli węzeł ten także jest typu PLANETA, także jest włączany do zbioru wyników.

descendant-or-self::PLANETA

Zwraca elementy PLANETA będące potomkami węzła kontekstowego. Jeśli sam węzeł kontekstu też jest typu PLANETA, jest dołączany do zbioru wyników.

self::PLANETA

Zwraca węzeł kontekstowy, o ile jest on elementem typu PLANETA.

child::NAZWA/descendant::PLANETA

Zwraca elementy PLANETA będące potomkami elementów NAZWA będących dziećmi węzła kontekstowego.

child::*/child::PLANETA

Zwraca wszystkie elementy PLANETA będące wnukami bieżącego węzła.

/

Zwraca węzeł główny dokumentu (czyli rodzica elementu głównego).

/descendant::PLANETA

Zwraca wszystkie elementy PLANETA z dokumentu.

/descendant::PLANETA/child::NAZWA

Zwraca elementy NAZWA mające element PLANETA za rodzica.

child::PLANETA[position()=3]

Zwraca trzecie dziecko typu PLANETA węzła kontekstu.

child::PLANETA[position() = last()]

Zwraca ostatnie dziecko PLANETA węzła kontekstowego.

/descendant::PLANETA[position() = 3]

Zwraca trzeci element PLANETA z dokumentu.

child::PLANETY/child::PLANETA[position() = 4]/child::NAZWA[position() = 3]

Zwraca trzeci element NAZWA czwartego elementu PLANETA z elementu PLANETY.

child::PLANETA[position() > 3]

Zwraca dzieci PLANETA węzła kontekstu znajdujące się za trzecim takim elementem.

preceding-sibling::NAZWA[position() = 2]

Zwraca drugi wstecz element NAZWA znajdujący się na tym samym poziomie, co bieżący węzeł.

child::PLANETA[attribute::KOLOR="CZERWONY"]

Zwraca dzieci PLANETA węzła kontekstowego mające atrybut KOLOR o wartości CZERWONY.

child::PLANETA[attriute::KOLOR="CZERWONY"][position() = 3]

Zwraca trzecie dziecko PLANETA węzła kontekstu mające atrybut KOLOR o wartości CZERWONY.

child::PLANETA[position() = 3][attribute::KOLOR = "CZERWONY"]

Zwraca trzecie dziecko PLANETA węzła kontekstu tylko wtedy, gdy dziecko to ma atrybut KOLOR o wartości CZERWONY.

child::MASA[child::NAZWA = "WENUS"]

Zwraca dzieci MASA węzła kontekstu mające dzieci NAZWA zawierające napis WENUS.

child::PLANETA[child::NAZWA]

Zwraca dzieci PLANETA węzła kontekstu mające dzieci NAZWA.

child::*[self::NAZWA or self::MASA]

Zwraca dzieci węzła kontekstu typów NAZWA oraz MASA.

child::*[self::NAZWA or self::MASA][position() = first()]

Zwraca pierwsze dziecko typu NAZWA lub MASA węzła kontekstu.

Jak widać w powyższej tabeli, niektóre formy są całkiem złożone, a ich zapis jest niepokojąco długi. Istnieje jednak także skrócona forma zapisu XPath.

Składnia skrócona XPath

Istnieje szereg skrótów zapisu składni XPath. Oto odpowiednie reguły:

Wyrażenie

Skrót

self::node()

.

parent::node()

..

child::dziecko

dziecko

attribute::dziecko

@dziecko

/descendant-or-self::node()/

//

Można też skracać zapis wyrażeń predykatów, na przykład [position() = 3] można zapisać jako [3], [position() = last()] jako [last()] i tak dalej. Użycie składni skróconej wyrażeń XPath znacznie ułatwia ich użycie. Oto przykłady zapisu skróconych wyrażeń XPath:

Przykład

Znaczenie

PLANETA

Zwraca elementy PLANETA będące dziećmi węzła (czyli węzła kontekstowego).

*

Zwraca wszystkie dzieci bieżącego węzła będące elementami.

text()

Zwraca wszystkie dzieci bieżącego węzła będące węzłami tekstowymi.

@JEDNOSTKI

Zwraca atrybut JEDNOSTKI bieżącego węzła.

@*

Zwraca wszystkie atrybuty węzła kontekstu.

PLANETA[3]

Zwraca trzecie dziecko PLANETA węzła kontekstu.

PLANETA[first()]

Zwraca pierwsze dziecko PLANETA węzła kontekstu.

*/PLANETA

Zwraca wszystkie wnuki (dzieci dzieci) PLANETA węzła kontekstu.

/PLANETY/PLANETA[3]/NAZWA[2]

Zwraca drugi element NAZWA trzeciego elementu PLANETA elementu PLANETY.

//PLANETA

Zwraca wszystkich potomków PLANETA węzła głównego.

PLANETY//PLANETA

Zwraca wszystkich potomków PLANETA elementów PLANETY będących dziećmi węzła bieżącego.

//PLANETA/NAZWA

Zwraca elementy NAZWA mające rodzica PLANETA.

.

Zwraca węzeł kontekstu.

.//PLANETA

Zwraca elementy PLANETA będące potomkami węzła kontekstowego.

..

Zwraca rodzica węzła kontekstowego.

../@JEDNOSTKI

Zwraca atrybut JEDNOSTKI rodzica węzła kontekstowego.

PLANETA[NAZWA]

Zwraca dzieci PLANETA węzła kontekstowego mające dzieci NAZWA.

PLANETA[NAZWA="Wenus"]

Zwraca dzieci PLANETA węzła kontekstowego mające dzieci NAZWA z treścią Wenus.

PLANETA[@JEDNOSTKI="dzień"]

Zwraca dzieci PLANETA węzła kontekstu mające atrybut JEDNOSTKI o wartości dzień.

PLANETA[6][@JEDNOSTKI="dzień"]

Zwraca szóste dziecko PLANETA węzła kontekstu, jeśli ma ono atrybut JEDNOSTKI o wartości dzień. To samo wyrażenie można zapisać też jako PLANETA[@JEDNOSTKI="dzień"][6].

PLANETA[@KOLOR and @JEDNOSTKI]

Zwraca wszystkie dzieci PLANETA węzła kontekstu mające atrybuty KOLOR oraz JEDNOSTKI.

Oto przykład, w którym użyto właśnie zapisu skróconego opisując węzły sąsiadujące z węzłem elementów PLANETA:

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="PLANETY">

<xsl:apply-templates select="PLANETA"/>

<xsl:template>

<xsl:template match="PLANETA">

<xsl:apply-templates select="MASA"/>

<xsl:template>

<xsl:template match="MASA">

<xsl:value-of select="../NAZWA"/>

<xsl:value-of select="../DZIEŃ"/>

<xsl:value-of select="."/>

<xsl:template>

</xsl:stylesheet>

--> Wszystko o XPointers[Author:T]

Na początku tego rozdziału przyglądaliśmy się łączu, w którym użyto wskaźnika XPointer do wybrania konkretnego elementu z dokumentu:

<PRZEGLĄD_FILMOWY xmlns:xlink="http://www.w3.org/1999/xlink"

xlink:type="simple"

xlink:show="new"

xlink:href="http://www.starpowdermovies.com/reviews.xml#

xpointer(/child::*[position()=126]/child::*[position()=first()])">

Pan Blandings buduje dom swoich marzeń

</PRZEGLĄD_FILMOWY>

Część XPointer wygląda tutaj tak:

xpointer(/child::*[position()=126]/child::*[position()=first()])">

Wskaźnik ten jest dołączany do adresu URI za znakiem #.

Być może zauważyłeś, że powyższe wyrażenie XPointer jest bardzo podobne do wyrażeń XPath i nie dzieje się tak bez powodu - XPointers korzystają z nieco rozszerzonych XPath.

XPointers mają wszystkie możliwości, które mają ścieżki XPath. Oznacza to między innymi, że XPointers mogą składać się z kroków lokalizacji wskazujących jakieś konkretne miejsce w dokumencie mimo, że do samego dokumentu nic nie trzeba dodawać. Można też użyć funkcji id() wskazującej konkretne elementy, pozwala to wskazywać elementy o zadanym atrybucie typu ID.

Jednak z uwagi na to, że XPointers specyfikację XPath rozszerzają, istnieją pewne różnice. Największa różnica polega na tym, że jako że użytkownik może wybierać części dokumentów za pomocą myszy, XPointers umożliwiają wybieranie punktówzakresów, a nie tylko zwykłych węzłów XPath. Punkt to punkt: jakieś miejsce w dokumencie. Zakres składa się z całego kodu XML znajdującego się między dwoma punktami, może zawierać elementy i tekst.

Aby obsłużyć punkty i zakresy, w XPointers ideę węzłów rozszerzono do pojęcia lokalizacji. Każda lokalizacja jest węzłem XPath, punktem lub zakresem. Wobec tego zbiory węzłów stają się w specyfikacji XPointer zbiorami lokalizacji.

Wskaźniki XPointers tworzy się tak samo, jak tworzy się ścieżki XPath. XPointers składają się ze ścieżek lokalizacji podzielonych na kroki lokalizacji porozdzielane od siebie ukośnikami /. Na krok lokalizacji składa się oś, test węzła oraz zero lub więcej predykatów:

oś::test_węzła[predykat]

Na przykład w wyrażeniu child::PLANETA[position() = 5] osią jest child, PLANETA to test węzła, a [position() = 5] jest predykatem.

Ścieżki lokalizacji mogą składać się z jednego lub więcej kroków lokalizacji, na przykład ścieżka descendant::PLANETA/child::NAZWA składa się z dwóch kroków i wybiera elementy NAZWA mające rodziców PLANETA.

Możliwości XPointers są większe niż możliwości XPath, wobec tego przyjrzymy się teraz wszystkim częściom składowym: osiom, badaniu węzłów i predykatom, ale tym razem już z punktu widzenia XPointers.

Osie XPointers

Opis

ancestor

Dotyczy przodków węzła kontekstowego. Przodkami są rodzice węzła kontekstowego, rodzice tych rodziców i tak dalej, aż po węzeł główny włącznie.

ancestor-or-self

Dotyczy węzła kontekstowego i jego przodków.

attribute

Dotyczy atrybutów węzła kontekstowego.

child

Dotyczy dzieci węzła kontekstowego.

descendant

Dotyczy potomków węzła kontekstowego. Potomek to dziecko, dziecko dziecka i tak dalej.

descendant-or-self

Dotyczy węzła kontekstowego i jego potomków.

following

Dotyczy wszystkich węzłów z dokumentu, do którego należy węzeł kontekstu, które znajdują się po nim.

following-sibling

Dotyczy wszystkich węzłów znajdujących się na tym samym poziomie co węzeł kontekstu, ale za tym węzłem.

namespace

Dotyczy węzłów przestrzeni nazw węzła kontekstu.

parent

Dotyczy węzła rodzica węzła kontekstowego.

preceding

Dotyczy wszystkich węzłów z dokumentu, do którego należy węzeł kontekstu, które znajdują się przed nim.

preceding-sibling

Dotyczy wszystkich węzłów znajdujących się na tym samym poziomie co węzeł kontekstu, ale przed tym węzłem.

self

Zawiera węzeł kontekstowy.

Wprawdzie osie są takie same jak w XPath, ale inne są już możliwości badania węzłów.

Testowanie węzłów XPointer

Oto testy węzłów, których można używać w XPointers:

Test węzła

Opis

*

Wybiera dowolne elementy.

node()

Wybiera węzły dowolnego typu.

text()

Wybiera węzły tekstowe.

comment()

Wybiera węzły komentarza.

processing-instruction()

Wybiera węzły instrukcji przetwarzania. W nawiasach można podać także nazwę instrukcji.

point()

Wybiera punkt w zasobie.

range()

Wybiera zakres w zasobie.

Szczególną uwagę zwróć na dwa ostatnie testy: point() i range(). Odpowiadają one dwóm nowym konstrukcjom wprowadzonym w XPointers, czyli punktom i zakresom, omówimy je dokładnie pod koniec tego rozdziału.

Aby rozszerzyć XPath o punkty i zakresy, w specyfikacji XPointer wprowadzono pojęcie lokalizacji, która może być węzłem XPath, punktem lub zakresem. Jednak testy węzłów nadal pozostają testami węzłów, nie są zamieniane na testy lokalizacji. Kiedy mówimy o testach węzłów, to w XPointers ich definicja została tak rozszerzona, aby mogły one objąć także testy punktów i zakresów. Ta pewna niekonsekwencja zapewne zostanie ostatecznie wyjaśniona w ostatecznej postaci rekomendacji XPointer.

Predykaty XPointer

XPointers obsługują takie same typy wyrażeń jak XPaths:

Jak to już objaśniano, istnieją specjalne funkcje dostosowane do użycia z poszczególnymi rodzajami wyrażeń, poza tym w XPointers istnieją dodatkowe funkcje pozwalające rzutować części wyrażeń na odpowiednie typy XPath: boolean(), string(), text() oraz number(). Dodano też funkcję unique() umożliwiającą sprawdzenie, czy XPointer wskazuje pojedynczą lokalizację, a nie wiele lub żadną.

W XPointers dodano też funkcje zwracające zbiory lokalizacji, funkcje te zostaną teraz omówione.

Funkcje zbiorów lokalizacji XPointer

W XPointers zdefiniowano cztery funkcje zwracające zbiory lokalizacji:

Funkcja

Opis

id()

Zwraca element o zadanym identyfikatorze.

root()

Zwraca zbiór lokalizacji składający się jedynie z węzła głównego.

here()

Zwraca zbiór lokalizacji składający się jedynie z lokalizacji bieżącej.

origin()

Ma takie samo znaczenie jak here(), ale ta funkcja używana jest w łączach zewnętrznych.

Funkcja id() jest tą samą funkcją, co zdefiniowana w XPath - zwraca wszystkie lokalizacje o zadanym identyfikatorze.

Funkcja root() działa dokładnie tak jak znak /: odwołuje się do węzła głównego (nie jest to węzeł elementu głównego, ale węzeł dotyczący całego dokumentu). Funkcja root() nie należy obecnie do specyfikacji XPath, ale występuje w XPointer. Nie wiadomo jeszcze, czy pozostanie tam także w ostatecznej rekomendacji.

Funkcja here() odnosi się do elementu bieżącego. Jest użyteczna, gdyż XPointers zwykle znajdują się w węzłach tekstowych lub wartościach atrybutów i konieczne może być odwołanie się do bieżącego elementu, a nie do bieżącego węzła. Załóżmy na przykład, że chcesz odwołać się do drugiego od końca elementu NAZWA znajdującego się na tym samym poziomie, co element zawierający XPointer - zastosować należy wtedy wyrażenie:

here()/preceding-sibling::NAZWA[position() = 2]

Funkcja origin() jest bardzo podobna do here(), ale używa jej się w łączach zewnętrznych, które należeć mogą do innego dokumentu, z którego łącze zostało uruchomione. Może to być bardzo przydatne, jeśli samo łącze należy do bazy łączy i nie należy odwoływać się do elementu, do którego łącze należy, ale do pierwotnego elementu, z którego zostało uruchomione.

W XPointers można używać również składni skróconej. Poniżej podano kilka przykładów opartych na pliku planety.xml:

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

<?xml-stylesheet type="text/xml" href="planety.xsl"?>

<PLANETY>

<PLANETA>

<NAZWA>Merkury</NAZWA>

<MASA JEDNOSTKI="(Ziemia=1)">.0553</MASA>

<DZIEŃ JEDNOSTKI="dni">58.65</DZIEŃ>

<PROMIEŃ JEDNOSTKI="mile">1516</PROMIEŃ>

<GĘSTOŚĆ JEDNOSTKI="(Ziemia=1)">.983</GĘSTOŚĆ>

<ODLEGŁOŚĆ JEDNOSTKI="miliony mil">43.4<ODLEGŁOŚĆ><!--w peryhelium-->

</PLANETA>

<PLANETA>

<NAZWA>Wenus</NAZWA>

<MASA JEDNOSTKI="(Ziemia=1)">.815</MASA>

<DZIEŃ JEDNOSTKI="dni">116.75</DZIEŃ>

<PROMIEŃ JEDNOSTKI="mile">3716</PROMIEŃ>

<GĘSTOŚĆ JEDNOSTKI="(Ziemia=1)">.943</GĘSTOŚĆ>

<ODLEGŁOŚĆ JEDNOSTKI="miliony mil">66.8<ODLEGŁOŚĆ><!--w peryhelium-->

</PLANETA>

<PLANETA>

<NAZWA>Ziemia</NAZWA>

<MASA JEDNOSTKI="(Ziemia=1)">1</MASA>

<DZIEŃ JEDNOSTKI="dni">1</DZIEŃ>

<PROMIEŃ JEDNOSTKI="mile">2107</PROMIEŃ>

<GĘSTOŚĆ JEDNOSTKI="(Ziemia=1)">1</GĘSTOŚĆ>

<ODLEGŁOŚĆ JEDNOSTKI="miliony mil">128.4<ODLEGŁOŚĆ><!--w peryhelium-->

</PLANETA>

</PLANETY>

Oto obiecane przykłady wskaźników XPointers. Zwróć uwagę, że można używać znanych z XPath nawiasów kwadratowych powodujących wybranie konkretnej lokalizacji ze zbioru lokalizacji.

Przykład

Znaczenie

PLANETA

Zwraca elementy PLANETA będące dziećmi węzła (czyli węzła kontekstowego).

*

Zwraca wszystkie dzieci bieżącego węzła będące elementami.

text()

Zwraca wszystkie dzieci bieżącego węzła będące węzłami tekstowymi.

@JEDNOSTKI

Zwraca atrybut JEDNOSTKI bieżącego węzła.

@*

Zwraca wszystkie atrybuty węzła kontekstu.

PLANETA[3]

Zwraca trzecie dziecko PLANETA węzła kontekstu.

PLANETA[first()]

Zwraca pierwsze dziecko PLANETA węzła kontekstu.

*/PLANETA

Zwraca wszystkie wnuki (dzieci dzieci) PLANETA węzła kontekstu.

/PLANETY/PLANETA[3]/NAZWA[2]

Zwraca drugi element NAZWA trzeciego elementu PLANETA elementu PLANETY.

//PLANETA

Zwraca wszystkich potomków PLANETA węzła głównego.

PLANETY//PLANETA

Zwraca wszystkich potomków PLANETA elementów PLANETY będących dziećmi węzła bieżącego.

//PLANETA/NAZWA

Zwraca elementy NAZWA mające rodzica PLANETA.

.

Zwraca węzeł kontekstu.

.//PLANETA

Zwraca elementy PLANETA będące potomkami węzła kontekstowego.

..

Zwraca rodzica węzła kontekstowego.

../@JEDNOSTKI

Zwraca atrybut JEDNOSTKI rodzica węzła kontekstowego.

PLANETA[NAZWA]

Zwraca dzieci PLANETA węzła kontekstowego mające dzieci NAZWA.

PLANETA[NAZWA="Wenus"]

Zwraca dzieci PLANETA węzła kontekstowego mające dzieci NAZWA z treścią Wenus.

PLANETA[@JEDNOSTKI="dzień"]

Zwraca dzieci PLANETA węzła kontekstu mające atrybut JEDNOSTKI o wartości dzień.

PLANETA[6][@JEDNOSTKI="dzień"]

Zwraca szóste dziecko PLANETA węzła kontekstu, jeśli ma ono atrybut JEDNOSTKI o wartości dzień. To samo wyrażenie można zapisać też jako PLANETA[@JEDNOSTKI="dzień"][6].

PLANETA[@KOLOR and @JEDNOSTKI]

Zwraca wszystkie dzieci PLANETA węzła kontekstu mające atrybuty KOLOR oraz JEDNOSTKI.

W XPath można wybierać jedynie dane na poziomie węzła. Jest to wystarczające, kiedy używa się oprogramowania obsługującego XML jako zbiór węzłów, na przykład w przypadku przekształceń XSL, ale czasem to za mało. Na przykład użytkownik używający wyświetlonego dokumentu XML może kliknąć myszką jakiś punkt lub wybrać zakres dokumentu (takie obszary nie muszą się zaczynać ani kończyć na granicach węzłów, mogą zawierać różne drzewka i ich fragmenty). W celu zapewnienia dokładniejszej kontroli nad danymi XML w XPointers udostępniono punktyzakresy.

Użycie punktów XPointer

Zgodnie ze specyfikacją XPointer do zdefiniowania punktu potrzebne są dwie rzeczy: węzeł oraz indeks - całkowita liczba dodatnia lub zero. Węzeł stanowi odniesienie dla punktu, indeks określa, jak daleko punkt jest od swojego odniesienia.

Powstaje jednak pytanie: w czym mierzyć indeks? W znakach czy w węzłach? Istnieją dwa rodzaje węzłów i w obu z nich indeks wylicza się inaczej.

Punkty węzłowe

Kiedy węzeł odniesienia może mieć węzły dzieci (czyli jest węzłem elementu lub węzłem głównym), nazywamy go punktem węzłowym.

Indeks punktu węzłowego mierzony jest węzłami potomnymi. Indeks takiego punktu nie może być większy od liczby dzieci węzła odniesienia. Jeśli użyje się indeksu zero, punkt znajdzie się bezpośrednio przed węzłami dziećmi. Indeks 5 oznacza umieszczenie punktu zaraz za piątym węzłem dzieckiem.

W przypadku punktów węzłowych można użyć osi: węzły sąsiadujące punktu to dzieci węzła odniesienia znajdujące się przed i za punktem. Same punkty jednak nie mają dzieci.

Punkty znakowe

Jeśli węzeł odniesienia nie może zawierać węzłów potomnych, a tylko tekst, indeks wyrażany jest w znakach. Punkty tego typu nazywamy punktami znakowymi.

Indeks punktów znakowych musi być nieujemną liczbą całkowitą oraz musi być nie większy niż długość tekstu w węźle. Jeśli indeks jest zerem, punkt znajduje się tuż przed pierwszym znakiem. Indeks 5 wskazuje punkt znajdujący się zaraz za piątym znakiem. Punkty znakowe nie mają węzłów sąsiadujących ani dzieci.

Na przykład element DOKUMENT można potraktować jako węzeł odniesienia w dokumencie następującym:

<DOKUMENT>

Witamy!

</DOKUMENT>

W tym wypadku mamy siedem punktów znakowych, po jednym przed każdym znakiem. Punkt znakowy o indeksie 0 znajduje się tuż przed pierwszym znakiem W, o indeksie 1 przed i i tak dalej.

Warto pamiętać, że w specyfikacji XPointer zestawy kolejnych spacji zbijane są w jedną spację. Punktów nie można też umieszczać wewnątrz etykiet początkowych i końcowych, instrukcji przetwarzania ani komentarzy czy jakichkolwiek innych znaczników.

Tworzenie punktów

W celu utworzenia punktu użyć należy w predykacie funkcji start-point(), na przykład tak:

start-point()[position()=10]

Oto przykład: załóżmy, że chcemy umieścić punkt tuż przed literą e w słowie Merkury w elemencie NAZWA:

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

<?xml-stylesheet type="text/xml" href="planety.xsl"?>

<PLANETY>

<PLANETA>

<NAZWA>Merkury</NAZWA>

<MASA JEDNOSTKI="(Ziemia=1)">.0553</MASA>

<DZIEŃ JEDNOSTKI="dni">58.65</DZIEŃ>

<PROMIEŃ JEDNOSTKI="mile">1516</PROMIEŃ>

<GĘSTOŚĆ JEDNOSTKI="(Ziemia=1)">.983</GĘSTOŚĆ>

<ODLEGŁOŚĆ JEDNOSTKI="miliony mil">43.4<ODLEGŁOŚĆ><!--w peryhelium-->

</PLANETA>

.

.

.

Możemy użyć następującego wyrażenia:

xpointer(/PLANETY/PLANETA[1]/NAZWA/text()/start-point()[position()=1])

Analogicznie sięgnięcie przed cyfrę 6 w tekście 58.65 w elemencie DZIEŃ wymagać będzie wyrażenia:

xpointer(/PLANETY/PLANETA[1]/DZIEŃ/text()/start-point()[position()=3])

Użycie zakresów XPointer

Zakresy można tworzyć za pomocą dwóch punktów: początkowego i końcowego, byle tylko oba znajdowały się w jednym dokumencie i by punkt początkowy nie był za punktem końcowym (jeśli oba punkty są takie same, mówimy o zakresie zdegenerowanym). Zakres to wszystkie struktury XML między punktem początkowym a końcowym.

Zakres nie musi być zamkniętym fragmentem dokumentu, może na przykład rozciągać się między różnymi poddrzewkami dokumentu. Jedyne, czego się wymaga, to aby oba punkty były w tym samym dokumencie.

Tworzenie zakresów

W celu utworzenia zakresu używa się dwóch ścieżek lokalizacji rozdzielonych słowem kluczowym to zamknięte w funkcji xpointer(). Oto przykład zakresu zawierającego całe słowo Merkury z dokumentu planety.xml:

xpointer(/PLANETY/PLANETA[1]/NAZWA/text()/start-point()[position()=0] to /PLANETY/PLANETA[1]/NAZWA/text()/start-point()[position()=7])

Z kolei utworzenie zakresu zawierającego cały tekst z wartością promienia Merkurego, czyli 1516, będzie miał postać:

xpointer(/PLANETY/PLANETA[1]/PROMIEŃ/text()/start-point()[position()=0] to /PLANETY/PLANETA[1]/PROMIEŃ/text()/start-point()[position()=4])

Funkcje zakresu

Specyfikacja XPointer opisuje funkcje obsługujące zakresy:

Funkcja

Opis

range-to(zbiór-lokalizacji)

Pobiera lokalizacje i zwraca zakres całkowicie je obejmujący. Na przykład lokalizacja elementu jest przekształcana na zakres przez zwrócenie rodzica elementu jako węzła odniesienia, punktu początkowego jako liczby sąsiadów elementu poprzedzającego oraz punktu końcowego jako punktu o jeden większego od punktu początkowego. Innymi słowy funkcja ta ma wiązać ze sobą lokalizacje i zakresy.

range-inside(zbiór-lokalizacji)

Zwraca zakres lub zakresy obejmujące wszystkie lokalizacje z podanego zbioru. Jeśli na przykład przekazana zostanie lokalizacja elementu, wynikowy zakres zawierał będzie wszystko, co jest wewnątrz elementu.

start-point(zbiór-lokalizacji)

Zwraca zbiór lokalizacji zawierający punkty początkowe. Punkty te są punktami początkowymi zakresów, które zawierałyby wszystkie przekazane lokalizacje. Na przykład start-point(//PLANETA[2]) zwróci punkt znajdujący się zaraz za drugim elementem PLANETA, natomiast start-point(//PLANETA) zwróci zbiór lokalizacji punktów znajdujących się przed elementami PLANETA.

end-point(zbiór-lokalizacji)

Działa tak samo jak start-point(), ale zwraca punkty końcowe tych samych zakresów obejmujących przekazane lokalizacje.

Użycie zakresów napisu

Specyfikacje XPointer zawiera także funkcję wyszukiwania napisów string-range(). Funkcja ta zwraca zbiór lokalizacji z jednym zakresem dla każdego niezachodzącego na inne wyszukiwanego napisu. Podczas wyszukiwania uwzględniana jest wielkość liter.

Można też wskazać opcjonalne argumenty indeks i długość, które określają ilość znaków po wyszukanym napisie, gdzie zakres ma się zaczynać i ile znaków ma zawierać. Oto ogólna składnia funkcji string-range():

string-range(zbiór-lokalizacji, napis, [indeks, [długość]])

Dopasowywanie do napisu pustego

Napis pusty "" znaleziony zostanie bezpośrednio przed jakimkolwiek znakiem, zatem takiego wzorca można użyć do wybrania samego początku napisu.

I tak poniższe wyrażenie zwraca zbiór lokalizacji zawierający zakresy obejmujące wszystkie wystąpienia słowa Saturn:

string-range(/, "Saturn")

Aby wybrać konkretne wystąpienie napisu ze zbioru wynikowych lokalizacji, użyć należy nawiasów kwadratowych. Poniższe wyrażenie zwróci zakres obejmujący drugie wystąpienie słowa Saturn:

string-range(/, "Saturn")[2]

Poniższe wyrażenie z kolei zwróci zakres obejmujący trzecie wystąpienie słowa Jowisz w elemencie NAZWA szóstego elementu PLANETA:

string-range(//PLANETA[6]/NAZWA, "Jowisz")[3]

Można też wskazać zakres przy użyciu argumentów indeks (od 1) i długość. Poniższe wyrażenie zwraca zakres obejmujący litery sz w trzecim wystąpieniu słowa Jowisz w elemencie NAZWA w szóstym elemencie PLANETA:

string-range(//PLANETA[6]/NAZWA, "Jowisz", 5, 2)[3]

Jeśli należy wskazać pojedynczy punkt, można użyć zakresu zdegenerowanego (o zerowej długości):

string-range(//PLANETA[6]/NAZWA, "Jowisz", 5, 0)[3]

Innym sposobem uzyskania pojedynczego punktu jest użycie funkcji start-point() zwracającej punkt początkowy zakresu:

start-point(string-range(//PLANETA[6]/NAZWA, "Jowisz", 5, 2)[3])

Poniższe wyrażenie wskazuje drugi znak @ w dowolnym węźle tekstowym w dokumencie wraz z pięcioma znakami za @:

string-range(/, "@", 1, 6)[2]

Skrócony zapis XPointer

Z uwagi na to, że tak często zdarza się odwoływać do elementów według lokalizacji lub identyfikatora, w specyfikacji XPointer przewidziano skrócone formy zapisu. Oto przykład; załóżmy, że chcemy określić lokalizację elementu DZIEŃ dla planety Wenus w pliku planety.xml:

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

<?xml-stylesheet type="text/xml" href="planety.xsl"?>

<PLANETY>

<PLANETA>

<NAZWA>Merkury</NAZWA>

<MASA JEDNOSTKI="(Ziemia=1)">.0553</MASA>

<DZIEŃ JEDNOSTKI="dni">58.65</DZIEŃ>

<PROMIEŃ JEDNOSTKI="mile">1516</PROMIEŃ>

<GĘSTOŚĆ JEDNOSTKI="(Ziemia=1)">.983</GĘSTOŚĆ>

<ODLEGŁOŚĆ JEDNOSTKI="miliony mil">43.4<ODLEGŁOŚĆ><!--w peryhelium-->

</PLANETA>

<PLANETA>

<NAZWA>Wenus</NAZWA>

<MASA JEDNOSTKI="(Ziemia=1)">.815</MASA>

<DZIEŃ JEDNOSTKI="dni">116.75</DZIEŃ>

<PROMIEŃ JEDNOSTKI="mile">3716</PROMIEŃ>

<GĘSTOŚĆ JEDNOSTKI="(Ziemia=1)">.943</GĘSTOŚĆ>

<ODLEGŁOŚĆ JEDNOSTKI="miliony mil">66.8<ODLEGŁOŚĆ><!--w peryhelium-->

</PLANETA>

.

.

.

Odwołanie będzie wyglądało strasznie:

http://www.starpowdermovies.com/planety.xml#

xpointer(/child::*[position()=1]/

child::*[position()=2]/child::*[position()=3])

Jak jednak wiesz już z wykładu o XPath, można zastosować wiele skrótów - na przykład [position()=x] można zapisać jako [x]. W XPointers można stosować skróty jeszcze dalej idące, mianowicie można pominąć nawiasy kwadratowe i wtedy nasze wyrażenie przybierze postać:

http://www.starpowdermovies.com/planety.xml#1/2/3

Kiedy widzisz zestawione w ten sposób kroki lokalizacji zapisane pojedynczymi liczbami, kroki te odpowiadają położeniu elementów.

Podobnie można użyć jako kroków lokalizacji słów oznaczających wartości atrybutów typu ID elementu. Załóżmy na przykład, że element PLANETA opisujący Wenus ma identyfikator Planeta_Miłości (czyli atrybut ID został w DTD zadeklarowany jako typu ID).

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

<?xml-stylesheet type="text/xml" href="planety.xsl"?>

<PLANETY>

<PLANETA>

<NAZWA>Merkury</NAZWA>

<MASA JEDNOSTKI="(Ziemia=1)">.0553</MASA>

<DZIEŃ JEDNOSTKI="dni">58.65</DZIEŃ>

<PROMIEŃ JEDNOSTKI="mile">1516</PROMIEŃ>

<GĘSTOŚĆ JEDNOSTKI="(Ziemia=1)">.983</GĘSTOŚĆ>

<ODLEGŁOŚĆ JEDNOSTKI="miliony mil">43.4<ODLEGŁOŚĆ><!--w peryhelium-->

</PLANETA>

<PLANETA ID="Planeta_Miłości">

<NAZWA>Wenus</NAZWA>

<MASA JEDNOSTKI="(Ziemia=1)">.815</MASA>

<DZIEŃ JEDNOSTKI="dni">116.75</DZIEŃ>

<PROMIEŃ JEDNOSTKI="mile">3716</PROMIEŃ>

<GĘSTOŚĆ JEDNOSTKI="(Ziemia=1)">.943</GĘSTOŚĆ>

<ODLEGŁOŚĆ JEDNOSTKI="miliony mil">66.8<ODLEGŁOŚĆ><!--w peryhelium-->

</PLANETA>

.

.

.

Teraz do elementu DZIEŃ opisującego Wenus możemy dostać się tak:

http://www.starpowdermovies.com/planety.xml#

xpointer(//child::*[id("Planeta_Miłości")]/child::*[position()=3]

Także tym razem zapis skrótowy jest znacznie prostszy:

http://www.starpowdermovies.com/planety.xml#Planeta_Miłości/3

W tym przykładzie użyto funkcji id(); aby jej użyć, konieczne jest deklarowanie atrybutów identyfikujących jako należących do typu ID. Jednak nie wszystkie dokumenty mają przecież DTD lub schemat XML, zatem XPointers umożliwiają określenie wzorców alternatywnych przez podanie wielu wskaźników XPointers. Oto przykład złożonego zapisu:

http://www.starpowdermovies.com/planety.xml#

xpointer(id("Planeta_Miłości"))xpointer(//*[@id="Planeta_Miłości"]/3

Jeśli zawiedzie pierwszy XPointer używający funkcji id(), użyty zostanie drugi, który wyszukuje element zawierający atrybut o nazwie ID mający żądaną wartość. Jednak dopiero przyszłość pokaże, jaka część tej funkcjonalności zostanie zaimplementowana w aplikacjach.

Na tym kończymy nasz wykład na temat XLinks i XPointers. Jak się mogłeś przekonać, są to narzędzia o bardzo dużych możliwościach, znacznie większych od zwykłych hiperłączy HTML. Jednak oba standardy zostały zaproponowane już kilka lat temu i nadal nie ma żadnych ich implementacji. Można mieć nadzieję, że już wkrótce się to zmieni.

Jeżeli krawędzie posiadają grot wskazujący kierunek to grafy takie nazywa się sieciami )przyp. tłum.)

12 Część I Podstawy obsługi systemu WhizBang (Nagłówek strony)

Rozdział 1 Pierwsze kroki (Nagłówek strony)

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

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

w oryginale 15

Aby zachować kompletność wykładu, wstawiam między specyfikacje XLinks i XPointers opis XPath potrzebny do XPointers. Opis ten wziąłem ze stron 643-654 z nie tłumaczonego rozdziału 13.

w oryginale: szkic roboczy z 21 lutego 2000r.

wg stanu na chwilę tłumaczenia

dodałem - p. uwaga na początku rozdziału

Na rysunek należy nałożyć kursor dłoni; nie udaje mi się go uzyskać ani w przypadku użycia Alt-PrtScr, ani PrtScr.

stan w chwili tłumaczenia

u autora „element”, ale dalej pokazany jest atrybut.

dodane świadomie

proponuję zostawić pusty wiersz

to zdanie dodałem w związku z wstawieniem następnej części rozdziału

dodałem akapit sprzed tytułu rozdziału jako wprowadzający

Fragment wstawiony z rozdziału 13 (zgodnie z opisem na początku rozdziału)

Koniec wstawionego fragmentu z rozdziału 13



Wyszukiwarka

Podobne podstrony:
r03-01, ## Documents ##, XML Vademecum profesjonalisty
r05-01, ## Documents ##, XML Vademecum profesjonalisty
r04-01, ## Documents ##, XML Vademecum profesjonalisty
r07-01, ## Documents ##, XML Vademecum profesjonalisty
r06-01, ## Documents ##, XML Vademecum profesjonalisty
r12-01, ## Documents ##, XML Vademecum profesjonalisty
r08-01, ## Documents ##, XML Vademecum profesjonalisty
r11-01, ## Documents ##, XML Vademecum profesjonalisty
r09-01, ## Documents ##, XML Vademecum profesjonalisty
Projektowanie Baz Danych Xml Vademecum Profesjonalisty [XML]
Projektowanie baz danych XML Vademecum profesjonalisty pxmlvp 2
Projektowanie baz danych XML Vademecum profesjonalisty pxmlvp
Projektowanie baz danych XML Vademecum profesjonalisty 2
Projektowanie Baz Danych Xml Vademecum Profesjonalisty [XML]
Projektowanie baz danych XML Vademecum profesjonalisty pxmlvp
Projektowanie Baz Danych Xml Vademecum Profesjonalisty R 5 Architektura Systemu Baz Danych
Projektowanie baz danych XML Vademecum profesjonalisty
Asembler dla procesorow Intel Vademecum profesjonalisty asinvp
CorelDRAW 11 Vademecum profesjonalisty Tom 2

więcej podobnych podstron