Již v době uvolnění XSLT 1.0 bylo jasné, že časem vznikne další specifikace, která možnosti jazyka dále rozšíří. V určitém okamžiku však bylo potřeba možnosti XSLT 1.0 zmrazit, aby vůbec vznikl stabilní standard, který budou jednotliví producenti XSLT procesorů implementovat.
XSLT 2.0 tak standardizuje v podstatě všechna rozšíření, o kterých jsme hovořili v předchozí kapitole. Největší změnou je však přechod od XPath 1.0 k XPath 2.0. Nová verze XPathu přitom podporuje datové typy definované XML schématu – pokud je pro dokument k dispozici. Všechny XPath výrazy navíc vracejí posloupnost – ty jako své položky mohou obsahovat jak uzly, tak skalární typy. Pro posloupnosti je definováno mnoho nových převážně množinových funkcí. Přímo v XPathu lze vyhodnocovat podmínky a jednoduché cykly.
Samotné XSLT se tak revolučních změn nedočkalo, protože mnohé chybějící funkce jsou součástí XPathu 2.0. Mezi největší změny můžeme počítat standardní instrukci pro výstup do více souborů, velmi mocnou instrukci pro seskupování uzlů, možnost definování uživatelských funkcí přímo ve stylu, výstupní metodu XHTML a regulární výrazy.
Nová verze jazyka XSLT má dvě úrovně – Basic a Schema-Aware. Pokročilejší úroveň Schema-Aware podporuje W3C XML Schema – datový model dokumentu obsahuje datové typy určené na základě schématu, generovaný výstup lze průběžně validovat, díky lepší typové kontrole se v kódu mohou snáze objevit chyby a informace o typech také dává lepší prostor pro optimalizace.
V následujícím textu si na několika příkladech ukážeme, jak XSLT 2.0 usnadňuje některé úlohy obtížněji řešitelné v XSLT 1.0. Podíváme se jen na funkčnost, která je v „Basic“ úrovni jazyka XSLT 2.0.
XPath 2.0 operuje nad novým datovým typem posloupnost. Posloupnosti lze přímo v XPathu zpracovávat množstvím množinových funkcí, ale můžeme přes ně provádět i iteraci, která konstruuje novou posloupnost. S výhodou to lze použít například pro sečtení naší objednávky.
Příklad 14.1. Součet objednávky pomocí XPath 2.0 –
objednavka4.xsl
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <!-- Sečtení objednávky --> <xsl:template match="/"> <xsl:variable name="nadpis"> Objednávka pro <xsl:value-of select="objednavka/jmeno"/> ze dne <xsl:value-of select="objednavka/datum"/> </xsl:variable> <html> <head> <title><xsl:value-of select="$nadpis"/></title> </head> <h1><xsl:value-of select="$nadpis"/></h1> <table border="1"> <tr> <th>Název</th> <th>Ks</th> <th>Cena</th> <th>Celkem</th> </tr> <xsl:for-each select="objednavka/polozka"> <tr> <td><xsl:value-of select="nazev"/></td> <td><xsl:value-of select="pocet"/></td> <td><xsl:value-of select="cena"/></td> <td><xsl:value-of select="pocet * cena"/></td> </tr> </xsl:for-each> <tr> <th>Celkem</th> <th colspan="3"> <!-- XPath 2.0 obsahuje i příkazy pro cykly --> <xsl:value-of select="sum(for $n in objednavka/polozka return $n/cena * $n/pocet)"/> </th> </tr> </table> </html> </xsl:template> </xsl:stylesheet>
Nová verze XPathu konečně přidává i podmíněný výraz, takže mnoho úkolů lze zapsat kompaktnějším způsobem.
Příklad 14.2. Podmíněný výraz v XPath 2.0 –
katalog-radky.xsl
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:output method="html" encoding="utf-8"/> <xsl:template match="/"> <html> <head> <title>Katalog <xsl:value-of select="katalog/info/firma"/></title> </head> <body> <h1>Katalog <xsl:value-of select="katalog/info/firma"/></h1> <table width="100%" border="1"> <xsl:apply-templates select="//polozka"/> </table> </body> </html> </xsl:template> <xsl:template match="polozka"> <!-- XPath 2.0 obsahuje podmíněný výraz --> <tr bgcolor="{if (position() mod 2 = 0) then '#FF8000' else '#FFC0C0'}"> <xsl:apply-templates select="nazev|kategorie|cena"/> </tr> </xsl:template> <xsl:template match="nazev"> <th><xsl:apply-templates/></th> </xsl:template> <xsl:template match="kategorie"> <td align="center"><xsl:apply-templates/></td> </xsl:template> <xsl:template match="cena"> <td align="right"><xsl:apply-templates/> Kč</td> </xsl:template> </xsl:stylesheet>
Gramatika XPathu se rovněž uvolnila, takže lze zapisovat výrazy
jako /kniha/(kapitola|priloha)/nazev
.
Funkce mohou být aplikovány i jako součást cesty. Například si můžeme nechat vrátit seznam názvů všech položek katalogu, kde jsou názvy převedeny na velká písmena:
/katalog/polozka/nazev/upper-case(.)
Pomocí zápisu
*:
se nyní
můžeme odvolávat na element v libovolném jmenném prostoru. To se hodí
pro zpracování formátů, které pro různé verze používají odlišné jmenné
prostory, ale význam elementů přitom zůstává stejný.lokální_jméno
Příklad 14.3. Zpracování elementů bez ohledu na jejich jmenný prostor –
gpx2html.xsl
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <!-- Univerzální transformace pro vykreslení GPX soubou na Google Maps pomocí JS API --> <!-- Dokumentace ke Google Maps API: http://code.google.com/apis/maps/ --> <xsl:output method="html" encoding="utf-8" indent="yes"/> <xsl:template match="*:gpx"> <html> <head> <title>Ukázka vykreslení GPX trasy pomocí Google Maps</title> <script src="http://maps.google.com/maps?file=api&v=2&hl=cs&key=ABQIAAAA4Wxrd1ZmQfRHvggZWM0QkxSVN_sXTad_Y81zCJbFzQPF08FeYBRZ9fK6emwt6oYGCxubaLiCphkWCg" type="text/javascript"/> <script type="text/javascript"> function initMap() { if (GBrowserIsCompatible()) { var map = new GMap2(document.getElementById("map")); map.setMapType(G_HYBRID_MAP); var points =[]; <xsl:apply-templates select="*:wpt|*:trk/*:trkseg/*:trkpt|*:rte/*:rtept"/> map.addOverlay(new GPolyline(points)); } } </script> </head> <body onload="initMap()"> <div id="map" style="width: 800px; height: 600px; margin-left: auto; margin-right: auto"/> </body> </html> </xsl:template> <xsl:template match="*:trkpt|*:wpt|*:rtept"> <xsl:if test="position() = 1"> map.setCenter(new GLatLng(<xsl:value-of select="@lat"/>, <xsl:value-of select="@lon"/> ), 10); map.setUIToDefault(); </xsl:if> <xsl:text/>points.push(new GLatLng(<xsl:value-of select="@lat"/>, <xsl:value-of select="@lon"/> )); </xsl:template> </xsl:stylesheet>
Relační operátory jako <
,
>
, =
, … fungují tak, že pokud je
alespoň na jedné straně porovnání posloupnost (seznam uzlů v XPathu
1.0) stačí, aby podmínka byla splněna pro jeden prvek
posloupnosti. Porovnání se tak automaticky chová jakoby před ním byl
uveden existenční kvantifikátor. V XPathu 2.0 můžeme toto chování
ručně kontrolovat pomocí nových konstrukcí some
a every
. Například následující výraz vrátí
prvočísla menší než 100.
for $i in (2 to 100) return if (every $j in (2 to $i - 1) satisfies $i mod $j ne 0) then $i else ()
Zároveň vidíme, že pro porovnávání nepoužíváme
!=
, ale ne
(not
equal). Operátory ne
, eq
, …
porovnávají vždy dvě hodnoty, nikdy se neprovádí porovnávání
s případnými několika položkami posloupnosti jako u operátorů
!=
, =
, ….
Nový operátor is
může být použit k ověření
totožnosti dvou uzlů.
Operátory <<
a >>
umožňují testovat, zda j nějaký uzel v dokumentu před (resp. za)
nějaký jiným uzlem. Například pomocí podmínky //p[1] <<
//h1[1]
snadno otestujeme, zda je v dokumentu před prvním
nadpisem nějaký odstavec.
Nad posloupnostmi lze nyní provádět běžné množinové
operace. Kromě sjednocení, které lze nyní kromě operátoru
|
zapsat i pomocí operátoru
union
, můžeme nově zjišťovat i rozdíl
(except
) a průnik (intersect
)
posloupností.
Všechny funkce a operátory dostupné v XPath 2.0 jsou popsané na adrese http://www.w3.org/TR/xquery-operators/.