Wprowadzenie do standardu XSL

Transkrypt

Wprowadzenie do standardu XSL
Wprowadzenie do standardu XSL
Tomasz Przechlewski
2002
Strona główna
Spis treści
Strona tytułowa
1 XSL
2
2 XPath
2.1 Wstęp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 Ścieżki dostępu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3 Wyrażenia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
2
3
7
Spis treści
3 XSLT
3.1 Wprowadzenie . . . . . . . . . .
3.2 Arkusz stylu . . . . . . . . . . .
3.3 Szablony . . . . . . . . . . . . . .
3.4 Tworzenie drzewa wyjściowego
3.5 Generowanie tekstu . . . . . . .
3.6 Numerowanie . . . . . . . . . . .
3.7 Zmienne . . . . . . . . . . . . . .
3.8 Iteracje . . . . . . . . . . . . . . .
3.9 Przetwarzanie warunkowe . . .
3.10 Sortowanie . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9
9
10
10
12
13
14
15
15
15
17
4 XSL:FO
18
Skorowidz
21
JJ
II
J
I
Strona 1 z 25
Powrót
Pełny ekran
Zamknij
Koniec
1.
XSL
Do wizualizacji dokumentu potrzebujemy w zasadzie dwóch elementów:
1. sposobu opisu wyglądu dokumentu docelowego,
2. metody przekształcenia znakowania ogólnego dokumentu wyjściowego na znakowanie zorientowane na prezentację dokumentu docelowego.
Standard XSL adresuje właśnie te dwa aspekty formatowania. Na XSL składają się obecnie trzy
rekomendacje konsorcjum W3C:
Strona główna
XSLT część związana z przekształcaniem dokumentów XML,
XPath część związana z adresowaniem elementów dokumentu XML,
FO część związana ze specyfikacją standardowych obiektów formatujących.
Po pierwsze jedna ze specyfikacji definiuje język XMLowy do specyfikowania samego sposobu
formatowania elementów w druku bądź w przeglądarce, druga opisuje język przekształcania dokumentów
XML w inne dokumenty XML natomiast trzecia definiuje język adresowania elementów dokumentu XML.
Elementy definiujące semantykę samego formatowania są nazywane „obiektami formatującymi”
(formatting objects, w skrócie fo). XSLowe obiekty formatujące są opisane w specyfikacji [6].
Odłączenie języka przetwarzania XSLT od samego języka specyfikującego formatowanie pozwoliło
na użycie również innych sposobów wizualizacji dokumentów niż tylko poprzez obiekty formatujące XSL.
Rolę tych obiektów może spełnić na przykład HTML, który w połączeniu z możliwościami
współczesnych programów interpretująych ten format zapewnia całkiem spore możliwości prezentacyjne.
Alternatywą jest skorzystanie z własnych „obiektów formatujących”.
2.
2.1.
XPath
Wstęp
Dokument XML może być przedstawiony jako struktura drzewiasta. Drzewo dokumentu jest podstawową
strukturą, którą przetwarza język XSLT. Szczegółowy model dokumentu XML jako drzewa jest opisany
w rekomendacji [5].
W drzewie dokumentu znajdują się węzły 7 typów, a mianowicie (por. rys 1):
Strona tytułowa
Spis treści
JJ
II
J
I
Strona 2 z 25
Powrót
Pełny ekran
Zamknij
Koniec
korzeń ten węzeł jest jeden dla każdego dokumentu, jego dzieckiem jest węzeł elementu głównego,
element węzeł odpowiada elementowi, jego dziećmi mogą być węzły elementowe, tekstowe, instrukcje
przetwarzania, atrybuty, komentarze i przestrzenie nazw.
tekst węzeł odpowiada fragmentowi tekstu w dokumencie, nie może mieć węzłów potomnych,
komentarz węzeł zawiera tekst komentarza, nie może mieć węzłów potomnych,
instrukcja sterująca węzeł zawiera tekst instrukcji sterującej.
atrybut węzeł zawierający wartość atrybutu.
Strona główna
przestrzeń nazw węzeł zawierający przestrzeń nazw.
Strona tytułowa
Podstawową konstrukcją standardu XPath jest wyrażenie. Podstawowe typy danych, to: zbiór-węzłów
(node set), logiczny (prawda-fałsz), liczba oraz napis (ciąg znaków).
Wyrażenie jest obliczane w bieżącym kontekście. Kontekst w jakim są obliczane wyrażenia XPath
jest określony w specyfikacjach XSLT oraz XPointer. Na kontekst składają się: bieżący węzeł, bieżąca
pozycja i bieżąca wielkość, zbiór wartości zmiennych, zbiór definicji funkcji, zbiór deklaracji
przestrzeni nazw.
2.2.
Ścieżki dostępu
Ważnym typem wyrażenia jest ścieżka dostępu. Wyrażenie XPATH jest zapisywane w postaci ścieżki
dostępu do adresowanych węzłów zapisanej w postaci poszczególnych kroków oddzielonych znakiem /.
Kroki są obliczane od lewej do prawej. Każdy krok wybiera zbiór-węzłów; pierwszy krok wybiera
zbiór-węzłów względem węzeł bieżącego, kolejne kroki za węzeł bieżący przyjmują sekwencyjnie
wybrane węzły ze zbioru otrzymanego w poprzednim kroku.
Jeżeli ścieżka dostępu zaczyna się od znaku / to oznacza to, że rozpoczynamy nawigację od korzenia
dokumentu.
Jeżeli zaczyna się od znaków // to oznacza, że możemy rozpocząć nawigację gdziekolwiek
w dokumencie.
Jeśli zaczynamy ścieżkę krokiem, to nawigacja zaczyna się w bieżącym węźle drzewa.
Najprostszy zapis kroku, to podanie nazwy elementu, do którego chcemy się przemieścić. Tak więc
zapis info/tytul oznacza, że chcemy wybrać tylko te elementy <tytul>, które są dziećmi elementu
<info>.
Spis treści
JJ
II
J
I
Strona 3 z 25
Powrót
Pełny ekran
Zamknij
Koniec
W przypadku gdy do jednego węzła pasuje więcej niż jeden wzorzec, transformator rozstrzyga, który
szablon użyć stosując reguły priorytetowe. Mówią one między innymi, że szablon przyporządkowany do
wzorca bardziej szczegółowego ma pierwszeństwo nad wzorcem bardziej ogólnym.
2.2.1. Osie
XPATH pozwala na nawigację również po innych tak zwanych osiach. W ogólnym przypadku krok ma
postać oś::test węzła[predykat].
Osie, po których możemy się poruszać to:
Strona główna
• oś dzieci (child) zawierająca węzły bezpośrednio doczepione w drzewie do węzła bieżącego;
• oś potomków (descendant) zawierająca węzły leżące w drzewie poniżej bieżącego;
• oś rodzica (parent) zawierająca węzeł, do którego węzeł bieżący jest bezpośrednio doczepiony,
jeżeli takowy istnieje;
Strona tytułowa
Spis treści
• oś przodków (ancestor) zawierająca węzły położone w drzewie powyżej węzła bieżącego;
• oś sąsiadów z tyłu (following-sibling), tj. wszystkie węzły mające tego samego rodzica, które
znajdują się „za” bieżącym;
JJ
II
• oś sąsiadów z przodu (proceeding-sibling), tj. wszystkie węzły mające tego samego rodzica,
które znajdują się „przed” bieżącym;
J
I
• oś poprzedników (preceding), tj. wszystkie węzły w dokumencie znajdujących się „przed”
bieżącym;
Strona 4 z 25
• oś następników (following), tj. wszystkie węzły w dokumencie znajdujących się „za” bieżącym;
Powrót
• oś atrybutów zawierająca atrybuty węzła bieżącego; oś ta jest pusta jeżeli bieżącym węzłem nie
jest element;
Pełny ekran
• oś przestrzeni nazw zawierająca przestrzenie nazw zadeklarowane dla węzła bieżącego; oś ta
jest pusta jeżeli bieżącym węzłem nie jest element;
Zamknij
• oś węzła bieżącego (self );
• oś potomków i oś węzła bieżącego (descendant-or-self ), tj. węzeł bieżący i węzły leżące
w drzewie poniżej bieżącego;
Koniec
• oś rodziców i oś węzła bieżącego (ancestor-or-self ), tj. węzeł bieżący i węzły leżące w drzewie
powyżej bieżącego.
Osie ancestor, descendant, following, preceding i self dzielą dokument w ten sposób, że nie nakładają
się na siebie i razem zawierają cały dokument (pomijając osie atrybutów i przestrzeni nazw, por. rys. 2).
Każdy krok może zostać zapisywany w postaci oś ::test [predykat ], gdzie: test specyfikuje
wybrane węzły na danej osi zaś predykat określa dodatkowe warunki, które muszą spełniać węzły.
2.2.2. Testy węzłów
Każda oś posiada podstawowy typ węzła (principal node type). Jeżeli oś zawiera elementy, to
podstawowym typem węzła jest element; w każdym innym przypadku jest to typ węzła, który może
zawierać oś, tj.: atrybut i przestrzeń nazw odpowiednio dla osi atrybutów i osi przestrzeni nazw oraz
element dla pozostałych typów osi.
Test zawierający nazwę węzła (tj. nazwę elementu, atrybutu, przestrzeni nazw) zwraca wartość
prawda tylko wtedy, gdy typ tego węzła jest równy podstawowemu typowi węzła osi oraz nazwa węzła
jest równa nazwie wyspecyfikowanej w teście. Przykładowo: child::para wybiera elementy <para>
będące dziećmi węzła bieżącego.
Test postaci * jest prawdziwy dla każdego węzła, którego typ jest zgodny z podstawowym
typem węzła osi. Przykładowo: child::* wybierze wszystkie elementy-dzieci węzła bieżącego, zaś
attribute::* wybierze wszystkie atrybuty węzła bieżącego.
Testy postaci text(), comment() i processing-instruction() są prawdziwe odpowiednio dla
każdego: węzła tekstowego, komentarza oraz instrukcji formatującej. Przykładowo: child::text()
oznacza węzły tekstowe węzła bieżącego.
Opcjonalnym argumentem testu processing-instruction może być napis; w takim przypadku test
jest prawdziwy dla instrukcji formatującej o nazwie równej wartości argumentu.
Jeśli chcemy wybrać wszystkie węzły (również te tekstowe, z komentarzami itp.) należy podać jako
test węzła funkcję node(). Przykładowo, aby zaadresować wszystkie węzły potomne od elementu <spis>
należy zapisać wyrażenie self::spis/descendant::node().
Strona główna
Strona tytułowa
Spis treści
JJ
II
J
I
Strona 5 z 25
Powrót
Pełny ekran
Zamknij
2.2.3. Predykaty
Ostatnim elementem kroku może być predykat. Jest on zapisywany w nawiasach kwadratowych i podaje
warunek, który powinien być spełniony przez wybierany węzeł.
Koniec
Oś może być albo osią „w przód” albo w „tył”. Oś zawierająca węzeł bieżący oraz węzły występujące
po nim w porządku dokumentu jest osią „w przód”. Oś zawierająca węzeł bieżący i węzły występujące
przed nim w porządku dokumentu jest osią „w tył”.
Osie: ancestor, ancestor-or-self, preceding i precendig-sibling są „w tył”; pozostałe osie są osiami
„w przód”.
Węzły w zbiorze-węzłów wybranym względem danej osi są uporządkowane w porządku w jakim
występują w dokumencie jeżeli oś jest osią „w przód” lub w porządku odwrotnym do tego w jakim
występują w dokumencie jeżeli oś jest osią „w tył”. Numer pierwszego węzła wynosi 1.
Dla każdego węzła w zbiorze-węzłów wybranym według osi i testu obliczany jest warunek predykatu,
przy założeniu, że tenże węzeł jest węzłem bieżącym, bieżącą wielkością (context size) jest liczba
węzłów w zbiorze-węzłów a bieżącą pozycją (context position) jest numer węzła określonemu
w sposób podany w poprzednim akapicie.
Jeżeli wyrażenie zwraca wartość prawda węzeł jest wybierany do wynikowego zbioru-węzłów;
w przeciwnym wypadku nie jest.
Jeżeli wyrażenie podane w predykacie wylicza się do liczby, to jest to interpretowane jako test
położenia węzła w stosunku do jego sąsiadów. Na przykład 5 element <para> w trzecim elemencie
<chapter> możemy zaadresować jako chapter[3]//para[5].
W każdym innym przypadku wyrażenie jest konwertowane do wartości boolowskiej. Na przykład
wszystkie elementy <w> zawierające element <i> możemy wyszukać wzorcem w[./i].
2.2.4. Składnia uproszczona
Specyfikacja osi child:: może zostać pominięta, tj. div/para jest równoważne child::div/child::para.
Specyfikacja osi attribute:: może zostać skrócona do @. Przykładowo: para[@lang="pl"] jest
równoważne: child::para[attribute::lang="pl"].
Specyfikacja //, to skrót od /descendant-or-self::node()/
Specyfikacja ., to skrót od self::node()
Specyfikacja .., to skrót od parent::node()
Przykłady:
• para wybiera elementy <para> – dzieci węzła bieżącego;
Strona główna
Strona tytułowa
Spis treści
JJ
II
J
I
Strona 6 z 25
Powrót
Pełny ekran
Zamknij
• * wybiera wszystkie elementy – dzieci węzła bieżącego;
• text() wybiera wszystkie elementy tekstowe – dzieci węzła bieżącego;
• @name wybiera atrybut name będący dzieckiem węzła bieżącego;
Koniec
• @* wybiera wszystkie atrybuty będące dziećmi węzła bieżącego;
• para[1] wybiera pierwszy element <para> będący dzieckiem węzła bieżącego;
• para[last()] wybiera ostatni element <para> będący dzieckiem węzła bieżącego;
• /article/chapter[4]/section[2] wybiera drugi element <section> dziecko czwartego elementu <chapter> dziecko elementu <article>;
• chapter//para wybiera wszystkie elementy <para> będące potomkami elementu <chapter>;
• //para wybiera wszystkie elementy <para> będące potomkami korzenia dokumentu, tj. wszystkie
elementy <para> w dokumencie;
Strona główna
• . wybiera bieżący węzeł;
• .//para wybiera wszystkie elementy <para> będące potomkami węzła bieżącego;
Strona tytułowa
• .. wybiera rodzica węzeła bieżącego;
• ../@lang wybiera atrybut lang rodzica węzeła bieżącego;
• para[@type=’warning’] wybiera wszystkie elementy <para>, dzieci elementu bieżącego, dla
których wartość atrybutu type wynosi warning.
• para[@type=’warning’][5] z elementów <para>, dzieci elementu bieżącego, dla którego wartość
atrybutu type wynosi warning wybiera piąty.
• para[5][@type=’warning’] wybiera piąty element <para>, dziecko elementu bieżącego jeżeli
wartość atrybutu type dla tego elementu wynosi warning.
• para[position()=5 and @type=’warning] to samo co wyżej.
• danie[nazwa=’zupa pomidorowa’] wybiera te elementy danie, dzieci elementu bieżącego, dla
których napisową wartością elementu <nazwa>, które z kolei jest dzieckiem elementu <danie> –
jest zupa pomidorowa.
Spis treści
JJ
II
J
I
Strona 7 z 25
Powrót
Pełny ekran
2.3.
Wyrażenia
Ścieżka dostępu może zostać użyta jako wyrażenie. Wyrażenie zwraca zbiór-węzłów.
Możliwe jest tworzenie wyrażeń logicznych za pomocą operatorów: =, !=, <, >=, <= oraz łączenie
wyrażeń logicznych za pomocą operatorów and oraz or.
Możliwe jest tworzenie wyrażeń logicznych za pomocą operatorów: +, -, *, div, mod.
Zdefiniowane są następujące funkcje:
Zamknij
Koniec
last() zwraca wielkość bieżącą (context size).
position() zwraca bieżącą pozycję (context position).
count(zbiór-węzłów) zwraca liczbę węzłów argumentu zbiór-węzłów.
id(obiekt) zwraca węzeł o wartości atrybutu typu ID równej wartości argumentu obiekt. Jeżeli obiekt
jest napisem, to ten napis jest porównywany z wartością atrybutu ID; jeżeli napis zawiera odstępy
to jest traktowany jako zbiór wartości ID a w rezultacie zwrócony może zostać zbiór-węzłów.
W przypadku innych typów obiektów dokonywana jest odpowiednia konwersja. Szczegóły znajdują
się w specyfikacji.
Strona główna
local-name(zbiór-nazw?) zwraca nazwę (bez prefiksa przestrzeni nazw) pierwszego elementu w podanym zbiorze-nazw.
Strona tytułowa
name(zbiór-nazw?) zwraca pełną nazwę elementu.
string(obiekt?) konwertuje obiekt do napisu. Konwersja zbioru-węzłów polega na zamianie na napis
pierwszego węzła ze zbioru przy przyjęciu porządku w jakim węzły występują w dokumencie.
concat(s1, s2, s3*) łączy napisy w jeden.
Spis treści
JJ
II
J
I
start-with(s1, s2) zwraca prawda jeżeli s1 rozpoczyna się od s2.
contains(s1, s2) zwraca prawda jeżeli s1 zawiera s2.
substring-before(s1, s2) zwraca napis wycięty z s1, poprzedzający pierwsze wystąpienie s2 w s1.
substring-after() zwraca napis wycięty z s1, następujący po pierwszym wystąpieniu s2 w s1.
Strona 8 z 25
substring(s1, n1, n2?) zwraca napis wycięty z s1, od pozycji n1 do pozycji n2, lub do końca napisu,
jeżeli nie podano n2. Numer pierwszego znaku to 1.
Powrót
string-length(s?) zwraca długość argumentu. Jeżeli argument jest pominięty, zwraca długość bieżącego
węzła po konwersji do napisu.
Pełny ekran
normalize-space(s?) Zwraca napis po usunięciu wiodących i końcowych znaków odstępu oraz
zamianie kolejnych znaków odstępu na pojedynczy znak spacji. Jeżeli argument jest pominięty,
zwraca długość bieżącego węzła po konwersji do napisu.
translate(s1,s2,s3) Funkcja podobna w działaniu do standardowego polecenia tr systemu Unix:
w napisie s1 wymienia każdy znak wymieniony w napisie s2 na odpowiadający mu znak w napisie
s3.
Zamknij
Koniec
boolean(obiekt) zamienia obiekt na typ boolowski.
true() zwraca wartość prawda.
false() zwraca wartość fałsz.
lang(s) zwraca wartość prawda jeżeli wartość atrybutu xml:lang węzła bieżącego jest równa s.
number(obiekt?) zamienia obiekt na liczbę.
sum(zbiór-węzłów) zwraca sumę zawartości zbioru-węzłów po ich konwersji do liczby.
floor(liczba) zwraca największą liczbę całkowitą nie większą od liczba.
Strona główna
ceiling(liczba) zwraca najmniejszą liczbę całkowitą nie mniejszą niż liczba.
round(liczba) Zwraca przybliżenie całkowite argumentu liczba.
3.
3.1.
XSLT
Wprowadzenie
Opis sposobu przetwarzania dokumentu jest określony w arkuszu stylu (stylesheet).
Plik musi być dobrze uformowanym plikiem XMLowym – tzn. musi zaczynać się deklaracją XMLową,
a wszystkie znaczniki początku elementu muszą posiadać sparowane znaczniki końca.
W arkuszu stylu mogą znaleźć się dwa rodzaje elementów. Jedne elementy opisują logikę
przetwarzania dokumentu, drugie natomiast, zwane elementami wynikowymi, są elementami, które
zostaną wstawione do drzewa dokumentu wyjściowego. Aby procesor mógł poprawnie rozróżnić jedne
elementy od drugich, elementy opisujące przetwarzanie należą do przestrzeni nazw związanych ze
standardem XSLT. W praktyce oznacza to, że zwyczajowo poprzedza się te elementy przedrostkiem xsl:,
który jest przyporządkowany odpowiedniej przestrzeni nazw XML na jednym z głównych elementów.
Arkusz stylów składa się z wielu szablonów (template) Szablon pełni dwie funkcje: określa
wzorzec pasujący do pewnego fragmentu drzewa wejściowego dokumentu XML oraz określa strukturę
wyjściowego drzewa elementów
Na różnych etapach przetwarzania procesor XSLT usiłuje dobrać do konkretnego węzła dokumentu
najbardziej szczegółowo opisujący go wzorzec zapisany w arkuszu stylów, a następnie wykonać szablon
skojarzony z przyporządkowanym wzorcem.
Wykonanie szablonu odbywa się zawsze w kontekście bieżącego węzła oraz bieżącej listy węzłów.
Strona tytułowa
Spis treści
JJ
II
J
I
Strona 9 z 25
Powrót
Pełny ekran
Zamknij
Koniec
3.2.
Arkusz stylu
Arkusz stylu jest zawarty wewnątrz elementu <xsl:stylesheet>. Wewnątrz <xsl:stylesheet>
wystąpić mogą następujące elementy: <xsl:output>, <xsl:variable>, <xsl:param>, <xsl:template>
oraz kilka innych.
Jednym z pierwszych elementów w arkuszu powinien być element <xsl:output>, którego atrybut
method będzie zawierał informację o formacie pliku wyjściowego. Ma to wpływ na sposób zapisywania
i formatowania pliku wyjściowego. Atrybut ten przyjmuje wartość html, jeśli wynikiem transformacji
ma być dokument HTML, xml, jeśli tworzymy nową wersję dokumentu XML lub text jeżeli wynikiem
przekształcenia ma być zwykły plik tekstowy.
Struktura arkusza stylów może zostać przedstawiona następująco:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="html"/>
<xsl:template match="..."> ... </xsl:template>
<xsl:template name="..."> ... </xsl:template>
</xsl:stylesheet>
3.3.
Szablony
Pojedynczy szablon jest zapisany we wnętrzu elementu <template>.
W atrybucie match podaje się wzorzec adresujący węzeł, do którego dany szablon ma być stosowany.
Załóżmy, że plik katalog.xml ma następującą prostą strukturę:
<katalog>
<czesc id="c8934" typ="klamkomanetka" rys="chorus43.jpg">
<nazwa>Campagnolo Chorus</nazwa>
<cena>585</cena>
</czesc>
<czesc id="c1293" typ="piasta.tyl" rys="veloce91.jpg">
<nazwa>Campagnolo Veloce</nazwa>
<cena>245</cena>
Strona główna
Strona tytułowa
Spis treści
JJ
II
J
I
Strona 10 z 25
Powrót
Pełny ekran
Zamknij
Koniec
</czesc>
...
wtedy następujący szablon:
<xsl:template match="nazwa">
<div class="nc">
<xsl:apply-templates/>
</div>
</xsl:template>
spowoduje wydrukowanie:
<div class="nc">Campagnolo Chorus</div>
<div class="nc">Campagnolo Veloce</div>
We wnętrzu szablonu znajduje się element <xsl:apply-templates>, który jest poleceniem dla
procesora XSLT by w to miejsce wstawić wynik przetwarzania węzłów, będących dziećmi węzła
bieżącego lub – jeżeli element <xsl:apply-templates> posiada atrybut select – zbioru węzłów
określonych przez wartość tego atrybutu. Wartością atrybutu jest wyrażenie dające w wyniku
zbiór-węzłów.
Szablony przekształcają fragmenty drzewa wejściowego na fragmenty drzewa wynikowego. Pojedyncze szablony mogą przekształcać dowolne fragmenty drzewa wejściowego.
Ta rekurencyjna metoda pozwala na zapisanie przetwarzania w postaci szablonów zależnych jedynie
od kontekstu danego węzła, a nie wiedzy o pełnej strukturze dokumentu.
W ogólnym przypadku szablon zawiera tekst powielany literalnie do drzewa wynikowego oraz
polecenia XSLT wykonywane przez procesor XSLT (takie jak <xsl:apply-templates>).
Jeśli procesor nie potrafi dopasować konkretnego wzorca z arkusza stylu, wtedy do transformacji
stosuje wzorzec domyślny. Dla węzłów tekstowych domyślny szablon wpisuje w drzewo wynikowe
tekst będący wartością węzła. Dla węzłów elementowych natomiast szablon domyślny zawiera jedynie
element <xsl:apply-templates>, czyli polecenie „przetwórz wszystkie węzły potomne”.
Element <xsl:call-template> wykonuje szablon nazwany uprzednio za pomocą polecenia
<xsl:template> z określonym atrybutem name. Nazwane szablony mogą być sparametryzowane
i wykonywane dla różnych wartości parametrów.
Załóżmy, że części rowerowe mają być formatowane wewnątrz elementu <div>, którego atrybut
class ma dla części droższych niż 100 zł wartość normalna, a dla pozostałych części wartość tania.
Poniższy arkusz rozwiązuje ten problem, wykorzystując szablon nazwany i parametr cc:
Strona główna
Strona tytułowa
Spis treści
JJ
II
J
I
Strona 11 z 25
Powrót
Pełny ekran
Zamknij
Koniec
<xsl:template name="cz">
<xsl:param name="cc">tania</xsl:param>
<div class="{$cc}"> <xsl:apply-templates/> </div>
</xsl:template>
<xsl:template match="czesc[cena&gt;100]">
<xsl:call-template name="cz">
<xsl:with-param name="cc">normalna</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template match="czesc">
<xsl:call-template name="cz">
<xsl:with-param name="cc">tania</xsl:with-param>
</xsl:call-template>
</xsl:template>
3.4.
Tworzenie drzewa wyjściowego
Szablon przepisuje literalnie elementy, które nie należą do przestrzeni nazw XSLT oraz nie są
zadeklarowanymi niestandardowymi elementami XSLT. Element może zostać utworzony za pomocą
polecenia <xsl:element>. Nazwa elementu wyjściowego jest wartością wymagalnego atrybutu name.
Atrybut ten może zawierać wyrażenia XPath, umieszczone wewnątrz nawiasów klamrowych (por.
punkt 3.5).
Element <xsl:attribute> umożliwia wstawienie atrybutu dla elementu wyjściowego utworzonego
zarówno przez literalne przepisanie elementu jak i poprzez wykorzystanie polecenia <xsl:element>.
Nazwę atrybutu określa wymagalny atrybut name, wartość atrybutu jest określona przez zawartość
elementu <xsl:attribute>. Przykład:
<xsl:template match="doc">
<body>
<attribute name="lang">pl</attribute>
<apply-templates />
</body>
</xsl:template>
Strona główna
Strona tytułowa
Spis treści
JJ
II
J
I
Strona 12 z 25
Powrót
Pełny ekran
Zamknij
Koniec
Element <xsl:text> umożliwia wstawienie napisu; element ten jest stosowany najczęściej do
wstawiania odstępów, gdyż odstępy wstawiane literalnie są domyślnie ignorowane.
3.5.
Generowanie tekstu
Przetworzenie elementu <xsl:value-of> powoduje wstawienie węzła tekstowego do drzewa wynikowego. Element <xsl:value-of> posiada wymagalny atrybut select, którego wartością jest wyrażenie;
wyrażenie jest przekształcane a wynik przekształcenia jest konwertowany do napisu.
Poniższy szablon wydrukuje zestawienie postaci typ: nazwa-części z pliku katalog.xml:
<xsl:template match=’czesc’>
<xsl:value-of select="@typ"/>
<xsl:text>: </xsl:text>
<xsl:value-of select="nazwa"/>
</xsl:template>
W atrybucie elementu wynikowego oraz niektórych elementów XSLT może być wstawione wyrażenie
XPath umieszczone wewnątrz pary nawiasów klamrowych {...}, które w takiej sytuacji podlega
normalnemu przekształceniu, tj. {wyrażenie} jest zamieniane na skonwertowany do napisu wynik
przekształcenia. Przykład:
<xsl:template match=’czesc’>
<img src="{@rys}" alt="{nazwa}"/>
</xsl:template>
Przetworzenie pliku katalog.xml przy wykorzystaniu powyższego szablonu spowoduje wydrukowanie:
<img src="chorus43.jpg" alt="Campagnolo Chorus">
...
Jeżeli wewnątrz wartości atrybutu ma zostać wstawiony literalnie prawy lub lewy nawias klamrowy
należy wstawić dwa takie znaki, tj. {{ lub }}.
Strona główna
Strona tytułowa
Spis treści
JJ
II
J
I
Strona 13 z 25
Powrót
Pełny ekran
Zamknij
Koniec
3.6.
Numerowanie
Element <xsl:number> służy do wstawienia sformatowanego numeru węzła do drzewa wynikowego.
Atrybut count określa węzły, które są numerowane; domyślnie są to wszystkie węzły tego samego typu
i nazwy co węzeł bieżący.
Atrybut format określa format drukowanego numery. Atrybut ten to napis zawierający specyfikacje-formatu
i znaki-przestanowe. Specyfikacje formatu określają postać drukowanej liczby, znaki-przestankowe
są przepisywane literalnie. Specyfikacje formatu mają postać ciągów znaków alfanumerycznych; zdefiniowane wartości to m.in:
1 numeracja arabska, tj.: 1, 2, itd;
Strona główna
a numeracja postaci: a, b, itd;
Strona tytułowa
A numeracja postaci: A, B, itd;
i kolejne liczby rzymskie: i, ii, iii, iv, itd;
Spis treści
I kolejne liczby rzymskie: I, II, III, IV, itd.
Numer elementu może być obliczany za pomocą wyrażenia umieszczonego w atrybucie value.
Wartość wyrażenia jest konwertowana do liczby całkowitej, a następnie wypisywana jest napisowa
reprezentacja tej liczby. Jeżeli nie określono atrybutu value przyjmowana jest kolejność oparta o pozycję
węzła w dokumencie. Określenie numery za pomocą atrybutu value jest niezbędne jeżeli zbiór węzłów
jest sortowany lub przetwarzany w inny zmieniający porządek węzłów sposób (por. punkt 3.10):
JJ
II
J
I
Strona 14 z 25
<xsl:template match=’katalog’>
<xsl:apply-templates select="czesc">
<xsl:sort select="nazwa"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match=’czesc’>
<xsl:number value="position()" format="1. " />
<xsl:value-of select="@typ"/>
<xsl:text>: </xsl:text>
<xsl:value-of select="nazwa"/>
</xsl:template>
Powrót
Pełny ekran
Zamknij
Koniec
W wyniku przetworzenia dokumentu zostanie wydrukowane ponumerowane zestawienie części
posortowane w porządku alfabetycznym.
3.7.
Zmienne
Za pomocą elementu <xsl:variable> możliwe jest zdefiniowanie zmiennej. W przeciwieństwie do
większości języków programowania wartość utworzonej w ten sposób zmiennej nie może być zmieniona.
Nazwa zmiennej jest określana jako wartość atrybutu name, wartość zaś albo jako zawartość elementu,
albo przez atrybut select, którego wartością jest wyrażenie.
Definicja <xsl:variable> może znajdować się na zewnątrz lub wewnątrz szablonów. W pierwszym
przypadku jest zmienną globalną w drugim jej wartość jest określona wyłącznie dla węzłów potomnych
szablonu.
Wartość zmiennej jest wstawiona za pomocą konstrukcji $nazwa-zmiennej.
3.8.
Iteracje
Zawartością elementu <xsl:for-each> jest szablon wykonywany dla każdego węzła wybranego przez
wyrażenie określone w atrybucie select tego elementu. Atrybut slect jest wymagany; wartość wyrażenia musi być typu zbiór-węzłów. Dla każdego węzła ze zbioru-węzłów szablon jest wykonywany
przy przyjęciu tego węzła za węzeł bieżący oraz przyjęciu zbioru wszystkich wybranych węzłów jako
bieżącej listy węzłów. Węzły są przetwarzane w porządku dokumentu lub w porządku określonym poleceniami <xsl:sort> wstawionymi wewnątrz elementu <xsl:for> (por. 3.10). Przykładowo w wyniku
przetworzenia poniższego szablonu zostanie wydrukowane zestawienie wszystkich elementów <title>,
dzieci elementów <sect1> i <sect2>, w porządku w jakim występują w dokumencie:
<xsl:template match="/">
<div class="toc">
<xsl:for-each select="//sect1|//sect2">
<p><xsl:value-of select="title"/></p>
</xsl:for-each>
</div>
</xsl:template>
3.9.
Przetwarzanie warunkowe
Polecenia <xsl:if> oraz <xsl:choose> umożliwiają warunkowe przetwarzanie szablonów.
Strona główna
Strona tytułowa
Spis treści
JJ
II
J
I
Strona 15 z 25
Powrót
Pełny ekran
Zamknij
Koniec
Wartością wymagalnego atrybutu test elementu <xsl:if> jest wyrażenie. Zawartością tego
elementu jest szablon. Jeżeli logiczną wartością wyrażenia określonego w atrybucie test jest prawda,
wykonywany jest szablon; w przypadku przeciwnym nie jest wykonywane żadne działanie. Przykład:
<xsl:template match=’lista.nazw/nazwa’>
<xsl:apply-templates/>
<xsl:if test="not(position()=last())">, </xsl:if>
</xsl:template>
Elementy <nazwa> wewnątrz elementu <lista.nazw> są oddzielone na wydruku przecinkiem, za
wyjątkiem ostatniej nazwy na liście.
W kolejnym przykładzie co drugi wiersz tabeli jest drukowany na żółtym tle:
<xsl:template match=’item’>
<tr>
<xsl:if test="position() mod 2 = 0 ">
<xsl:attribute name="bgcolor">yellow</xsl:attribute>
</xsl:if>
<xsl:apply-templates/>
</tr>
</xsl:template>
Polecenie <xsl:choose> pozwala na wybór z wielu możliwych wariantów. Zawartością <xsl:choose>
jest ciąg elementów <xsl:when>, po których może wystąpić opcjonalny element <xsl:otherwise>. Każdy
element <xsl:when> posiada atrybut test zawierający wyrażenie. Zawartością elementów <xsl:when>
oraz <xsl:otherwise> jest szablon. Przetworzenie elementu <xsl:choose> polega na obliczaniu logicznej wartości jego atrybutu test. Wykonywany jest szablon pierwszego i tylko tego elementu, dla którego
wartość jest równa prawda. Jeżeli żaden z warunków elementów <xsl:when> nie ma wartości prawda,
wykonywany jest szablon określony przez zawartość elementu <xsl:otherwise>. Przykład:
<xsl:choose>
<xsl:when test="@team=’Telekom’">Team Deutsche Telekom</xsl:when>
<xsl:when test="@team=’Saeco’">Saeco-Cannondale</xsl:when>
<xsl:when test="@spec=’Once’">Once-Eroski</xsl:when>
<xsl:otherwise>inny</xsl:otherwise>
</xsl:choose>
Strona główna
Strona tytułowa
Spis treści
JJ
II
J
I
Strona 16 z 25
Powrót
Pełny ekran
Zamknij
Koniec
3.10.
Sortowanie
Sortowanie jest wykonywane po dodaniu elementu <xsl:sort> do zawartości elementów <xsl:apply-templates>
lub <xsl:for-each>. Każdy element <xsl:sort> określa kolejny klucz sortowania.
Element <xsl:sort> ma atrybut select, którego wartością jest wyrażenie. Przy przyjęciu kolejno
każdego przetwarzanego węzła jako węzła bieżącego oraz przyjęciu listy wszystkich przetwarzanych
węzłów w porządku dowolnym jako bieżącej listy węzłów obliczana jest wartość wyrażenia. Obliczona
w ten sposób wartość jest konwertowana do napisu i stanowi klucz sortowania. Domyślną wartością
atrybutu select jest ., co oznacza, że domyślnym kluczem sortowania jest wartość węzła bieżącego po
konwersji do napisu.
Strona główna
Element <xsl:sort> może posiadać następujące atrybuty opcjonalne:
order określenie porządku sortowania; dozwolone wartości to ascending (porządek rosnący, przyjmowany domyślnie) oraz descending (porządek malejący).
Strona tytułowa
lang określenie języka; zbiór wartości jest identyczny jak w przypadku atrybutu xml:lang, np.
lang="pl".
Spis treści
data-type określenie typu sortowanych obiektów oraz sposobu ich sortowania; dozwolone wartości,
to:
text napisy sortowane w porządku alfabetycznym określonym ewentualnie za pomocą wartości
atrybutu lang; number liczby sortowane numerycznie, atrybut lang jest w tym wypadku
ignorowany; qname symbole; sposób sortowania nie jest określony w specyfikacji XSLT;
case-order określenie czy duże litery (majuskuły) są sortowane przed ich małymi odpowiednikami
(minuskuły) czy też porządek powinien być odwrotny. Atrybut ten ma znaczenie wyłącznie wtedy,
gdy wartością atrybutu data-type jest text. Wartość domyślna winna być zależna od wybranego
języka.
Poniższy szablon wydrukuje zestawienie części posortowane według ceny od najdroższych do najtańszych
z pliku katalog.xml:
<xsl:template match=’katalog’>
<xsl:apply-templates select="czesc">
<xsl:sort select="cena" data-type="number"/>
</xsl:apply-templates>
</xsl:template>
JJ
II
J
I
Strona 17 z 25
Powrót
Pełny ekran
Zamknij
Koniec
Aby zestawienie było posortowane oddzielnie dla każdego typu części, wystarczy zmodyfikować
powyższy szablon dodając kolejny klucz sortowania:
<xsl:template match=’katalog’>
<xsl:apply-templates select="czesc">
<xsl:sort select="@typ"/>
<xsl:sort select="cena" data-type="number"/>
</xsl:apply-templates>
</xsl:template>
Strona główna
4.
XSL:FO
XSL:FO jest skomlikowanym językiem o dużych możliwościach, zawierającym ponad 50 różnych
„obiektów formatujących”, począwszy od najprostszych, takich jak prostokątne bloki tekstu poprzez
wyliczenia, tabele i odsyłacze. Obiekty te można formatować wykorzystując przeszło 200 różnych
właściwości (properties), takich jak: kroje, odmiany i wielkości pisma, odstępy, kolory itp. W tym
dokumencie przedstawione jest absolutne miniumum informacji na temat standardu XSL:FO.
Cały dokument XSL:FO zawarty jest wewnątrz elementu <fo:root>. Element ten zawiera dwa
zasadnicze elementy <fo:layout-master-set> oraz <fo:page-sequance>. Pierwszy z nich zawiera
szablony określające wygląd poszczególnych stron oraz sekwencji stron, drugi specyfikuje zawartość
dokumentu (por. rys. 3):
Strona tytułowa
Spis treści
JJ
II
J
I
<?xml version="1.0" ?>
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="s1"
....
</fo:simple-page-master>
<fo:page-sequence-master master-name="ss1">
....
</fo:page-sequence-master>
</fo:layout-master-set>
Strona 18 z 25
</fo:page-sequence master-reference="ss1">
<fo:flow>
Koniec
Powrót
Pełny ekran
Zamknij
...
</fo:flow>
</fo:page-sequence>
</fo:root>
Każdy szablon definiujący pojedynczą stronę jest zawarty w elemencie <fo:simple-page-master>
określającym wymiary różnych obszarów na tej stronie. Przykładowo:
<fo:simple-page-master master-name="body">
<fo:region-body margin-bottom="2cm"
margin-left="3cm" margin-right="2cm"
margin-top="2.5cm" />
</fo:simple-page-master>
Element <fo:page-sequence-master> określa z kolei porządek w jakim poszczególne strony będą
zapełniane treścią.
Kompletny przykładowy arkusz XSLT formatujący katalog części rowerowych jest zdefiniowany
następująco:
<?xml version="1.0" encoding="iso-8859-2"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version="1.0">
Strona główna
Strona tytułowa
Spis treści
JJ
II
J
I
Strona 19 z 25
<xsl:output method="xml" version="1.0"/>
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="body" >
<fo:region-body margin-bottom="2cm"
margin-left="3cm" margin-right="2cm"
margin-top="2.5cm" />
</fo:simple-page-master>
<fo:page-sequence-master master-name="main-seq">
<fo:repeatable-page-master-reference master-reference="body"/>
Powrót
Pełny ekran
Zamknij
Koniec
</fo:page-sequence-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="main-seq">
<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="czesc">
<fo:block font-family="Times"> <xsl:apply-templates/> </fo:block>
</xsl:template>
Strona główna
Strona tytułowa
Spis treści
<xsl:template match="cena">
<fo:inline color="blue" font-weight="bold">
<xsl:apply-templates/>
<xsl:text> zl</xsl:text>
</fo:inline>
</xsl:template>
</xsl:stylesheet>
W rezultacie drukowany jest zestaw akapitów, z których każdy zawiera nazwę części i cenę, przy
czym ta ostatnia jest drukowana w kolorze niebieskim w odmianie półgrubej. Całość ma być drukowana
odmianą „Times” (Times New Roman).
JJ
II
J
I
Strona 20 z 25
Powrót
Pełny ekran
Bibliografia
Zamknij
[1] strona domowa Jamesa Clarka patrz http://www.jclark.com/.
[2] Dokumentacja procesora FOP, patrz http://www.apache.org/fop.
[3] Michael Kay, XSLT Programmer’s Reference. Wrox Press Ltd., 2000.
Koniec
[4] Pakiet do przetwarzania dokumentów SGML w języku Perl patrz http://www.oasis-open.org/
cover/publicSW.html#sgmlspm.
[5] World Wide Web Consortium, XSL Transformations (XSLT), patrz http://www.w3.org/TR/xslt.
html.
[6] World Wide Web Consortium, Extensible Stylesheet Language (XSL), patrz http://www.w3.org/
TR/xsl/.
[7] World Wide Web Consortium, XML Path Language (XPath), patrz http://www.w3.org/TR/xpath.
html.
Skorowidz
arkusz stylu, 9
bieżąca
— lista węzłów, 15, 17
— pozycja, 3
— wielkość, 3
bieżący
— kontekst, 3
bieżący węzeł, zob. węzeł bieżący
boolean, 9
ceiling, 9
concat, 8
contains, 8
count, 8
element
— wynikowy, 9
false, 9
floor, 9
fo:layout-master-set, 18
Strona główna
Strona tytułowa
fo:page-sequance, 18
fo:page-sequence-master, 19
fo:root, 18
fo:simple-page-master, 19
Spis treści
JJ
II
J
I
id, 8
krok, 3
lang, 9
last, 8
local-name, 8
Strona 21 z 25
Powrót
name, 8
normalize-space, 8
number, 9
Pełny ekran
oś, 4
Zamknij
position, 8
predykat, 5
rekurencja, 11
Koniec
round, 9
sortowanie, 17
start-with, 8
string, 8
string-length, 8
substring, 8
substring-after, 8
substring-before, 8
sum, 9
ścieżka dostępu, 3
translate, 8
true, 9
węzeł, 2
— bieżący, 15, 17
— typ podstawowy, 5
wzorzec
— domyślny, 11
xsl:apply-templates, 11, 17
xsl:attribute, 12
xsl:call-template, 11
xsl:choose, 15, 16
xsl:element, 12
xsl:for, 15
xsl:for-each, 15, 17
xsl:if, 15, 16
xsl:number, 14
xsl:otherwise, 16
xsl:output, 10
xsl:param, 10
xsl:sort, 15, 17
xsl:stylesheet, 10
xsl:template, 10, 11
xsl:text, 13
xsl:value-of, 13
xsl:variable, 10, 15
xsl:when, 16
zbiór-węzłów, 3, 7, 11, 15
— konwersja do napisu, 8
Strona główna
Strona tytułowa
Spis treści
JJ
II
J
I
Strona 22 z 25
Powrót
Pełny ekran
Zamknij
Koniec
<?xml version="1.0" encoding="iso-8859-2"?>
<Memo status="secret">
<To>Comrade Napoleon</To>
<From>Snowball</From>
<Body>
<P>George Orwell says:
<!-- In Animal Farm if you don’t knoww -->
<Q author=’Orwell’>...the pigs had to
expend enormous labour every day upon mysterious things called files, reports,
minutes and memoranda. These were large sheets of paper which had to be closely
converted with writing, and as soon as they were so converted, they were
burnt in the furnace...</Q>. Do you think XML would have helped the pigs?
</P>
<!-- Add something on XSL -->
</Body>
<Close>Comrade Snowball</Close>
<?xyz rpq?>
</Memo>
Strona główna
Strona tytułowa
Spis treści
root
JJ
II
J
I
Strona 23 z 25
memo
Powrót
Pełny ekran
to
from
status
body
close
comment
pi
Zamknij
Comrade Napoleon
Snowball
p
Comrade Snowball
Koniec
root
memo
Strona główna
Strona tytułowa
to
...
from
...
body
p
close
p
p
Spis treści
...
JJ
II
J
I
Strona 24 z 25
...
...
q
...
Powrót
Pełny ekran
Zamknij
...
Koniec
Rysunek 2. Osie
Strona główna
fo:root
Strona tytułowa
Spis treści
fo:layout-master-set
fo:simple-page
-master
fo:page-sequence
-master
fo:declarations
fo:color
-profile
fo:page-sequence
fo:title
fo:static
-content
fo:flow
JJ
II
J
I
Strona 25 z 25
Rysunek 3. Ogólna struktura dokumentu XSL:FO
Powrót
Pełny ekran
Zamknij
Koniec

Podobne dokumenty