Szablon (template) może posiadać nazwę podaną w atrybucie name
.
Wówczas szablon ten można wywołać używając instrukcji call-template
.
Przy takim wywołaniu nie zmienia się kontekst (inaczej niż przy apply-templates
).
Szablon musi posiadać co najmniej jeden z parametrów match
i name
, może
posiadać oba.
Plik: named.xsl.
<xsl:template name="opisz-element"> <p>Element o nazwie <xsl:value-of select="name()"/>.</p> </xsl:template> <xsl:template match="/"> <html> <body> <h1>Wszystkie elementy:</h1> <xsl:for-each select="//*"> <xsl:call-template name="opisz-element"/> </xsl:for-each> <h1>Elementy poziomu głównego:</h1> <xsl:for-each select="/*/*"> <xsl:call-template name="opisz-element"/> </xsl:for-each> </body> </html> </xsl:template>
XSLT pozwala na deklarowanie parametrów i zmiennych, których następnie można używać w wyrażeniach XPath, np.: $nazwa
.
Zmienne w XSLT są deklaratywne (jak w programowaniu funkcyjnym): już w miejscu
deklaracji następuje przypisanie wartości, której następnie nie można modyfikować. Zmienne deklaruje się
w elementach variable
.
Deklaracja zmiennej lokalnej może wystąpić wewnątrz konstruktorów sekwencji.
Zmienna jest widoczna do końca elementu, w którym została zadeklarowana.
Wartość zmiennej lokalnej może być obliczana wielokrotnie (gdy szablon jest wielokrotnie używany
lub wewnątrz pętli for-each
).
Deklaracja zmiennej globalnej może wystąpić na głównym poziomie arkusza. Zmienna jest widoczna we wszystkich szablonach oraz deklaracjach innych zmiennych (i parametrów) globalnych. Cykliczne definicje są błędami. Wartość zmiennej globalnej jest obliczana tylko raz, może zależeć od parametrów lub treści dokumentu.
Wartość zmiennej można podać na dwa sposoby:
select
, wówczas przypisywana jest obliczona wartość wyrażenia,
variable
, która jest interpretowana tak jak konstruktor sekwencji,
a wynik tej interpretacji jest przypisywany na zmienną (jako sekwencja węzłów dokumentu,
chyba że podano atrybut as
).
W XSLT 1.0 istnieje różnica między wartością wyrażenia z select
a wartością uzyskaną
w wyniku interpretacji wnętrza variable
. Ta druga jest typu result tree fragment
i nie można już na niej wykonywać takich operacji jak for-each
czy apply-templates
.
To rozróżnienie nie występuje w XSLT 2.0, dzięki temu możliwe jest to.
<xsl:variable name="ile-elementow" select="count(//element())"/> <xsl:variable name="tekst"> <p>Dokument ma <xsl:value-of select="$ile-elementow"/> elementów.</p> </xsl:variable> <xsl:template match="/"> <html> <body> <xsl:sequence select="$tekst"/> </body> </html> </xsl:template>
<xsl:template match="konto"> <xsl:variable name="jakie">} <xsl:choose> <xsl:when test="saldo > 0">dodatnie</xsl:when> <xsl:when test="saldo < 0">ujemne</xsl:when> <xsl:otherwise>równe zero</xsl:otherwise> </xsl:choose> </xsl:variable> Saldo konta jest <xsl:value-of select="$jakie"/>. </xsl:template>
Parametry arkusza (globalne) są zadeklarowane w elementach param
na głównym poziomie arkusza.
Ich wartość można dostarczyć z zewnątrz przed wykonaniem przekształcenia – procesor XSLT powinien to umożliwiać.
Parametry mogą mieć wartość domyślną, którą podaje się tak samo jak wartość zmiennych. Widoczność parametrów arkusza jest taka jak zmiennych globalnych.
W XSLT 2.0 w atrybucie as
można podać typ parametru, a w atrybucie required
powiedzieć
czy parametr jest obowiązkowy.
Sparametryzować można także pojedyncze szablony, robi się to za pomocą elementów param
umieszczonych na początku treści szablonu. Tak samo jak dla parametrów globalnych można podać
wartość domyślną, typ i obowiązkowość.
Do przekazania wartości parametrów do szablonu służą elementy with-param
umieszczone
wewnątrz apply-templates
lub call-template
. Wartość określa się
tak samo jak wartość zmiennych lub domyślną wartość parametrów.
Szablony nazwane wraz z parametrami mogą działać podobnie jak procedury i pozwalają na „programowanie”.
Pliki: arkusz, dokument wejściowy.
<xsl:template name="silnia"> <xsl:param name="n"/> <xsl:param name="res" select="1"/> <xsl:choose> <xsl:when test="$n > 1"> <xsl:call-template name="silnia"> <xsl:with-param name="n" select="$n - 1"/> <xsl:with-param name="res" select="$n * $res"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$res"/> </xsl:otherwise> </xsl:choose> </xsl:template>
Write and test named template repeat
with parameters value
and n
,
which inserts n
copies of value
parameter in the place of invocation.
W XSLT 2.0 można definiować własne funkcje, których następnie można używać w wyrażeniach XPath arkusza.
Funkcje definiuje się w elementach function
na głównym poziomie arkusza. Opcjonalny parametr
as
opisuje typ wyniku, opcjonalny parametr override
mówi czy chcemy nadpisać
ewnetualnie istniejącą definicję funkcji o takiej samej nazwie, liczbie parametrów i priorytecie (domyślnie tak).
Zawartość elementu function
jest taka jak szablonu: najpierw elementy param
określające parametry funkcji, a następnie konstruktory i instrukcje tworzące wynik funkcji.
Plik: silnia-fun.xsl.
<xsl:function name="loc:silnia"> <xsl:param name="n"/> <xsl:sequence select="if($n <= 1) then 1 else $n * loc:silnia($n - 1)"/> </xsl:function>
Write and test (in XSLT 2.0) function count-elems(name, node)
which returns the number of occurrences of elements with name name
within the subtree rooted in node (including node).
Przy okazji - to ilustracja skróconej składni dla arkuszy XSLT.
<table xsl:version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <tr> <th>Position</th> <th>Country</th> <th>City List</th> <th>Population</th> </tr> <xsl:for-each-group select="cities/city" group-by="@country"> <tr> <td><xsl:value-of select="position()"/></td> <td><xsl:value-of select="@country"/></td> <td> <xsl:value-of select="current-group()/@name" separator=", "/> </td> <td><xsl:value-of select="sum(current-group()/@pop)"/></td> </tr> </xsl:for-each-group> </table>
Create an alternate version of stylesheet for staff.xml which groups employees by their position and for each position prints the number of employees, the average salary of them, and a list of all employees' (last) names.
Use XSLT 2.0 for-each-group
instruction. Optionally, write also an XSLT 1.0 stylesheet.
XSLT jest też XML-em, a więc może być wyprodukowany jako wynik XSLT. Trzeba zrobić coś, żeby odróżnić elementy XSLT,
ktróre mają być interpretowane teraz, od elementów XSLT, które mają być wynikiem transformacji.
Umożliwia to deklaracja namespace-alias
.
Przykład z rekomendacji.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias"> <xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/> <xsl:template match="/"> <axsl:stylesheet> <xsl:apply-templates/> </axsl:stylesheet> </xsl:template> <xsl:template match="block"> <axsl:template match="{.}"> <fo:block><axsl:apply-templates/></fo:block> </axsl:template> </xsl:template> </xsl:stylesheet>
Baza danych eksportuje dane (pojedyncze tabele) w postaci XML. Każdy wiersz wyniku jest umieszczony w elemencie wiersz
,
a poszczególne pola w wierszu mają nazwy takie jak kolumny tabeli. Przykłady dokumentów: tabela1.xml tabela1a.xml tabela2.xml.
W dokumentach takich jak schemat1.xml i schemat2.xml (DTD) opisane są „schematy” tabeli wraz z metadanymi do wykorzystania przy prezentacji (etykiety kolumn, czy pokazywać kolumnę, czy i jak sortować po podanej kolumnie, sortujemy w takiej kolejności, w jakiej podano kolumny).
Należy napisać arkusz XSLT, który na podstawie schematu tabeli utworzy w wyniku arkusz XSLT, służący do prezentacji tabel zgodnych z tym schematem. Wynikowy arkusz powinien prezentować tabele w postaci tabel HTML, uwzględniając dodatkowe informacje podane w schemacie.
A database exports data from tables in XML form.
Every row is placed in row
element,
and particular fields are written within row
in elements
of names based on names of columns.
Example documents: table1.xml table1a.xml table2.xml.
Documents such as table-schema1.xml or table-schema2.xml (here their DTD) specify „schemas” of tables: names of table columns. Additionally, some presentation-related information may be given: label of a column (to appear in column header), whether to show a column or not, whether to sort table by the column and in what order.
The task is to write an XSLT transformation which takes a table schema and returns another XSLT stylesheet capable of presenting tables of the given schema in HTML form.
Procesor XSLT może, ale nie musi, udostępniać funkcjonalność serializacji – zamiany wynikowego drzewa na ciąg bajtów. Wpływ na sposób serializacji mają parametry serializacji, które można ustawiać:
output
arkusza,result-document
arkusza (które służą do tworzenia więcej niż jednego dokumentu w wyniku przekształcenia),
Pełny opis elementów output
i result-document
w rekomendacji.
Poniżej opis niektórych aspektów serializacji.
Parametr version
służy do określenia wersji standardu XML (dla metody XML i XHTML)
lub HTML (dla metody HTML).
Parametry doctype-public
i doctype-system
służą do umieszczenia w wyniku
deklaracji DOCTYPE. Mają znaczenie przy metodach serializacji XML, XHTML i HTML. Należy ich używać,
aby wynik był walidującym się HTML bądź XHTML.
Deklaracja output
dla XHTML 1.1 (z domyślnym zestawem modułów).
<xsl:output method="xhtml" version="1.0" encoding="utf-8" doctype-public="-//W3C//DTD XHTML 1.1//EN" doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"/>
Efekt w dokumencie
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
Do arkusza prezentującego przepisy kulinarne dodaj informację o wersji i DOCTYPE właściwe dla HTML 4.01.
Parametr serializacji cdata-section-elements
może zawierać (rozdzielone spacjami)
nazwy elementów wyniku, których zawartość tekstowa ma być umieszczona w sekcjach CDATA.
Jeśli umieszczenie całego tekstu w jednej sekcji jest niemożliwe, może powstać kilka sekcji.
Wymuś używanie sekcji CDATA dla elementów strong
.
W XSLT 2.0 istnieje mechanizm do zastępowania na wyjściu wskazanych znaków innymi napisami. Można zastąpić jedynie znaki z węzłów tekstowych i wartości atrybutów (a nie np. nazw elementów).
Napis wstawiany w miejsce znaku nie jest już w żaden sposób przetwarzany. Wynikowy dokument może więc być niepoprawny składniowo (gdy wstawiany napis zawiera znaki specjalne).
Mechanizm ten nie pozwala na stosowanie różnych character maps w różnych fragmentach
dokumentu. W takich sytuacjach przydatna może być instrukcja
analyze-string
.
Uwaga, instrukcja analyze-string
działa w warstwie logicznej, podczas gdy mapowanie znaków
tylko podczas serializacji.
Plik: charmaps1.xsl.
Kopiuje dowolny dokument XML. Przy serializacji zastępuje „polskie znaki” łacińskimi odpowiednikami.
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="ascii" use-character-maps="polskie_na_ascii"/> <xsl:character-map name="polskie_na_ascii"> <xsl:output-character character="Ą" string="A"/> <xsl:output-character character="Ć" string="C"/> <!-- ... --> <xsl:output-character character="ź" string="z"/> <xsl:output-character character="ż" string="z"/> </xsl:character-map> <xsl:template match="/"> <xsl:copy-of select="."/> </xsl:template> </xsl:stylesheet>
Dla metod serializacji XML i XHTML, do wyniku zapisywane są deklaracje wszystkich przestrzeni nazw obowiązujących w elementach, które mają trafić do wyniku. Powoduje to niepotrzebne dodawanie do wyniku deklaracji przestrzeni nazw XML Schema, funkcji XPath i innych.
Aby tego uniknąć, można wykorzystać atrybut exclude-result-prefixes
. W atrybucie tym można umieścić:
#default
odnoszący się do domyślnej w danym miejscu
przestrzeni nazw;
#all
, oznaczający wszystkie przestrzenie nazw obowiązujące w danym miejscu.
Atrybut exclude-result-prefixes
może wystąpić:
xsl
,xsl
(lub innym wskazującym na przestrzeń nazw XSLT),
„Wyłączenie” prefiksu obowiązuje w całym poddrzewie elementu w którym występuje
atrybut exclude-result-prefixes
. To rozwiązanie nie gwarantuje, że deklaracja przestrzeni nazw
nie pojawi się w wyniku. W szczególności deklaracja pojawi się, jeżeli jakiś element lub atrybut wyniku
należy do danej przestrzeni nazw.
Weź arkusz XSLT 2.0 z metodą serializacji xml, który zawiera deklarację przestrzeni nazw (np. XML Schema) i postaraj się, aby wynik przekształcenia nie zawierał deklaracji tej przestrzeni nazw.
XSLT (zwłaszcza w wersji 2.0) to dość rozbudowany standard i na ćwiczeniach nie zmieściły się pewne tematy. Oto niektóre z nich: