Az XSL (XML Stylesheet Language) és XSLT (XSL Transformation) szabványok kiegészítik az XML dokumentumokat formázási és új szerkezet-kialakítási lehetőségekkel.
Alapszabály, hogy az XML dokumentumokat mind az embereknek, mind pedig a számítógépeknek könnyedén kell tudnia olvasni. Az XML dokumentum megjelenítésekor a jelölőelemeket a megfelelő szövegstílusokkal kell helyettesíteni. Az XSL és az XSLT szabványok azért jöttek létre, hogy ezt a feladatot megoldják.
Stíluslapok
Ahhoz, hogy egy XML dokumentumot megfelelőképpen tudjunk megjeleníteni, az esetek nagy többségében szükség van ún. stíluslapokra.
A HTML formátumnál általában nincs szükség stíluslapok használatára, mivel a nyelv önmagában tartalmaz olyan elemeket, amelyek a dokumentum formázására használhatók. Ennek ellenére a HTML-hez is létezik stíluslap szabvány, a CSS (Cascading Style Sheets). Ez a szabvány azonban nem kötődik szorosan a HTML-hez, néhány újabb böngésző már képes olyan XML dokumentumokat megjeleníteni, melyek a CSS használatával lettek formázva. A CSS szabvány ennek ellenére is elég gyenge, ellentétben a DSSSL (Document Style Semantics and Specification Language) szabvánnyal, ami viszont túl bonyolultra sikeredett, ezért nem nagyon van olyan alkalmazás, ami ezt támogatja. Az XSL szabvány éppen azért jött létre, hogy a CSS és DSSSL szabványok közötti űrt kitöltse, felhasználva mindkettő előnyeit.
Ugyanazt a stíluslapot több hasonló dokumentumban felhasználhatjuk, így az elkészítéshez szükséges időt nagyban csökkenthetjük. A stíluslapban definiált szabályok szoros összefüggésben vannak a dokumentumban szereplő elemekkel, ebből következik, hogy a DTD-vel is.
Egy dokumentumhoz több stíluslap is rendelhető, ezzel a dokumentum megjelenítése szerkesztés nélkül is változtathatóvá válik. Elkészíthetünk például egy-egy stíluslapot a dokumentum képernyőn, illetve a nyomtatásban történő megjelenítésére is, ahol például a kiemeléshez használt formázások eltérőek (képernyőn a kiemelés lehet például szín, míg nyomtatásban vastag betű).
Az XSL-ben különböző formázó objektumokat használhatunk (blokk- és soros elemek, táblázat cellák), melyek mindegyike sok jellemzővel rendelkezik, mindegyik objektum négyszögletes elrendezést követ. Az XSL-ben a formázó utasításoknak többféle megjelenítési formája lehet, de a legkézenfekvőbb talán az XML elemek használata. Ennek megfelelően az objektum típusokat elemekkel azonosítjuk, míg a jellemzőket attribútumokkal. A szabványhoz létezik egy DTD is, melynek a Formatting Objects DTD nevet adták (FO DTD). Azokban a dokumentumokban, melyek ezt a DTD használják, az ebben definiált elemekkel kell körülvenni a formázni kívánt dokumentumrészletet.
<block text-align=”centered”>Középre igazított bekezdés.</block>
Az XSL feldolgozók megértik az FO DTD-vel formázott XML dokumentumokat, és ennek megfelelően tudják formázni azt. Azt viszont semmi sem biztosítja, hogy minden XML dokumentum megfelel ennek a DTD-nek. Már csak azért sem, mert ez ellenkezne az XML alapgondolatával. Egy XML dokumentum ugyanis önleíró, és nem önformázó, tehát szükség van egy átalakításra, amely az XML forrásállományt önformázóra alakítja. Erre találták ki az XSLT szabványt, amely azt írja le, hogy egy XML dokumentumot hogyan hozhatunk publikálásra alkalmas formátumra. Az átalakítás során létrejön egy átmeneti állomány. Az XSLT a következő műveleteket képes elvégezni:
- előtagokkal és utótagokkal kiegészíti a tartalmat;
- elemek létrehozása, törlése, sorba rendezése, átsorolása;
- elemeket újra felhasználni a dokumentum más részein;
- egyik XML formáról egy másikra, vagy HTML-formára alakítani az adatokat;
- kijelölni az elemek osztályaira alkalmazandó XSL formázó objektumokat.
Az XSLT feldolgozó tehát egy új dokumentumot állít elő, felhasználva ehhez az XSLT szabványnak megfelelő DTD-t.
Az átalakítás az ún. mintaillesztő (template) szabályoknak megfelelően történik, melyek a stíluslapban vannak definiálva. A feldolgozó a forrásdokumentumban található útvonalakat összehasonlítja a mintákkal, és az eredeti jelölőelemeket kicseréli úgynevezett „kimeneti” jelölőelemekkel.
A következő példában egy olyan szabályt mutatunk be, amely a „kiemel” elemet félkövér betűtípussal jeleníti meg:
<template match =”kiemel”>
<fo:inline-sequence font-weight=”bold”>
<apply-templates/>
</fo:inline sequence>
</template>
Ez egy <kiemel>vastagbetűs</kiemel>szó.
Mint a fenti példában is látható az XSLT átalakító utasításait az XSL formázó utasításaitól névterekkel különböztetjük meg.
A gyakran ismétlődő részek kihagyására is van lehetőség, úgynevezett „mintaszövegek” létrehozásával.
<template match=”fontos”>
FONTOS! <apply-templates/>
</template>
Ha például egy olyan dokumentumot készítünk, amelyben gyakran előfordul a „Példa:” szó, és ezt minden esetben ugyanazok a jelölőelemek veszik körük (pl. „<pl>Példa:</pl>”), akkor lehetőség van arra, hogy ez automatikusan bekerüljön a megfelelő helyekre.
Példa: Ez itt a példa
A tartalom megjelenítésének sorrendje nem feltétlenül egyezik meg a dokumentumon belüli sorrenddel, sőt az is előfordulhat, hogy bizonyos részeket nem minden esetben szeretnénk megjeleníteni. Az XSLT át tud helyezni, vagy ki tud hagyni részleteket a dokumentumból, illetve tud új részleteket is beszúrni. Ha gyakran előfordulnak a dokumentumban olyan kulcsszavak, melyek mindig ugyanazon jelölőelemek között szerepelnek, akkor ezeket felesleges minden helyen megismételni, mivel az XSLT képes ezeket megtalálni, és a dokumentum más részein felhasználni.
Előfordulhat olyan eset, hogy ugyanazon elemet a dokumentum különböző részein másképpen kell formázni, attól függően, hogy milyen környezetben van. Az előforduló esetekre különböző szabályokat lehet létrehozni.
<template match=”eloszo/bekezd”>
...
</template>
Az XSLT dokumentum bizonyos esetekben stíluslapnak tekinthető anélkül, hogy a FO DTD-nek megfelelő kimeneti állományt hozna létre. A FO elemeket tartalmazó XSL állományok másik népszerű kimeneti formátuma a HTML.
A következő példa a „bekezd” elemet a HTML megfelelőjére alakítja:
<template match=”bekezd”>;
<html:p><apply-templates/></html:p>
</template>
Azt, hogy egy dokumentum milyen stíluslapot használjon az „xml-stylesheet” feldolgozási utasítással adhatjuk meg, melynek meg kell előznie a gyökérelemet:
Az utasításnak számos paramétere lehet, amiket ugyanúgy kell megadni, mint egy nyitó jelölőelem jellemzőit. A paraméterek neve és lehetséges értékei megegyeznek a HTML Link elem jellemzőivel és annak értékeivel. A Href és Type jellemzők határozzák meg a stíluslap helyét és típusát:
<?xml-stylesheet href=”stilus1.xsl” type=”text/xsl” ?>
Ha több stíluslapot szeretnénk használni, akkor azokat egymást követően megadhatjuk, de ebben az esetben érdemes a Title jellemzőt is megadni, hogy a felhasználó menüből tudja kiválasztani a számára megfelelőt.
<?xml-stylesheet href=”stegysz.xsl” type=”text/xsl” Title=”Egyszerű megjelenítés” ?>
<?xml-stylesheet href=”stmodern.xsl” type=”text/xsl” Title=”Modern megjelenítés” alternative=”yes” ?>
Ha egyszerre több stíluslapra is szeretnénk hivatkozni, akkor szintén több feldolgozási utasításra van szükség. Ebben az esetben a megjelenítést végző alkalmazás fogja eldönteni, hogy adott esetben melyiket használja:
<?xml- et href=”cssstil.xsl” type=”text/css” title=”default” ?>
Egy XSLT stíluslapot a „http://www.w3.org/Transform/1.0” névtérrel tudunk azonosítani. A szabvány mellékleteként szereplő DTD-ben definiálva van a 34 elem, és azok jellemzői, melyekkel a stíluslapokat szerkeszthetjük.
A következő listában a használható elemek szerepelnek, a zárójelben pedig a jellemzők (ha vannak):
- apply-imports
- apply-templates (select, mode): minták alkalmazása
- attribute (name, namespace, xml:space)
- attribute-set (name, use-attribute-sets): jellemzők halmaza
- call-template (name)
- choose (xml:space)
- comment (xml:space)
- copy (xml:space, use-attribute-sets)
- copy-of (select)
- element (name, namespace, xml:space, use-attribute-sets)
- fallback (xml:space)
- for-each (select, xml:space): mindegyikre alkalmazd
- if (test, xml:space)
- import (Href)
- include (Href)
- key (name, match, use)
- locale (name, decimal-separator, grouping-separator, infinity, minus-sign, NaN, percent, per-mille, zero-digit, digit, pattern-separator): helyi beállítások
- message (xml:space)
- number (level, count, from, format, lang, letter-value, grouping-separator, grouping-size, sequence-src)
- otherwise (xml:space): egyébként
- param (name, select)
- processing-instruction (name, xml:space): feldolgozási utasítások
- preserve-space (Elements): térközöket megtart
- sort (select, lang, data-type, order, case-order): rendezés
- strip-space (Elements): térközök minimalizálása
- stylesheet (result-ns, default-space, indent-result, id, xmlns:xls, xml:space, result-version, result-encoding, extension-element-prefixes)
- template (match, name, priority, mode, xml:space): minta
- text
- transform (lásd. stylesheet)
- value-of (select): értéke
- variable (name, select): változó
- when (test, xml:space)
- with-param (name, select)
A gyökérelem neve, amihez az összes XSLT szabványhoz tartozó beágyazott elemnek igazodnia kell a „Stylesheet”, de használhatjuk helyette a „Transform” elemet is.
<stylesheet xmlns=”http://www.w2.org/XSL/Transform/1.0”>
…
</stylesheet>
A XSLT stíluslap tartalmazhat olyan elemeket is, melyek nem tartoznak a szabványhoz, de ebben az esetben ezekhez külön névteret kell definiálni.
Lehetőség van más stíluslapok beillesztésére az Import elem segítségével. Az import állományt a Href jellemzővel kell megadni. Egyszerre több állományt is importálhatunk, de az import utasításoknak a stílusszabályok előtt kell szerepelniük.
<stylesheet>
<import href=”kozos.xsl”>
<template>…</template>
…
Ha egy elemre több szabály is vonatkozik az importálás miatt, akkor mindig az importált szabály az, ami kevésbé fontos. Ha viszont az állományt az Include utasítással illesztjük be, akkor az abban található szabályok egyenrangúak a stíluslapban definiált szabályokkal. Az Include utasítás tetszőleges helyen szerepelhet, egyetlen szabály rá, hogy az import utasítások után kell állnia.
<include href=”kozos.xsl”>…</include>
Előfordulhat olyan eset, amikor egy elemre többféle szabály vonatkozik. Ekkor a feldolgozó programnak valami alapján el kell döntenie, hogy melyiket használja. Minden szabály rendelkezik egy úgynevezett prioritással. Azok a szabályok, melyek egy egyszerű elemet neveznek meg, a prioritása 0. Az ennél összetettebb, specifikusabb szabályok prioritása 0,5. Ha több azonos prioritású szabály vonatkozik ugyanarra az elemre, akkor a Priority jellemzőt kell használni a prioritások megadására. Ha ilyen esetben nem használjuk a Priority jellemzőt, akkor mindig az utolsó szabály lesz a magasabb prioritású.
Ha olyan elemeket is alkalmazunk, melyeket nem kívánunk formázni, akkor azokra valószínűleg nem is hozunk létre szabályt. Az XSLT dokumentumok megfelelő feldolgozása viszont csak akkor történhet meg, ha minden egyes elemhez tartozik egy szabály. Ilyen esetekben létrehozhatunk egy olyan szabályt, amely az összes, egyik formázó szabályban sem szereplő elemet helyettesítheti.
<template match=/|*”>
<apply-templates/>
</template>
Ez a szabály explicit módon mindig jelen van, de ha megadjuk, akkor például az apply-templates elem elhagyásával elérhetjük azt, hogy csak azok az elemek kerüljenek feldolgozásra, melyekhez van szabály.
Ha azt akarjuk elérni, hogy az összes elem szövegtartalma látszódjon, akkor a következő szabályt kell alkalmaznunk:
<template match=”text()”>
<value-of select=”.”/>
</template>
Az apply-templates alapértelmezés szerint minden gyermek elemet feldolgoz, ezt viszont a Select jellemző használatával megváltoztathatjuk. Az alábbi példa csak azokat a bekezdéseket dolgozza fel, melyek type jellemzőjének értéke „normal”:
<template match=”bekezd”>
<apply-templates select=”bekezd[@type=’normal’]”/>
</template>
Ha a forrásállományban található egy felsorolás, amit az átalakítás során ABC sorrendbe szeretnénk rendezni, akkor erre is van lehetőségünk:
<felsorolas>
<tetel>körte</tetel>
<tetel>alma</tetel>
<tetel>eper</tetel>
</felsorolas>
<template match=”felsorolas”>
<apply-templates><sort/></apply-templates>
</template>
A fenti példából jól látszik az is, hogy az apply-templates elem nem üres elem.
Ha a rendezés nem a felsorolás elemeinek szövege alapján történik, akkor megadhatunk egy rendezési kulcsot is. Az alábbi példa az „ar” jellemző értéke alapján rendezi a tételeket:
<felsorolas>
<tetel ar=”125”>körte</tetel>
<tetel ar=”89”>alma</tetel>
<tetel ar=”176”>eper</tetel>
</felsorolas>
<template match=”felsorolas”>
<apply-templates><sort select=”@ar”/></apply-templates>
</template>
A „sort” elem többszöri alkalmazásával több rendezési kulcsot is megadhatunk. Az alábbi példa először vezetéknév, majd azon belül keresztnév szerint rendezi a sorokat:
<template match=”nev”>
<apply-templates>
<sort select=”vezeteknev”/>
<sort select=”keresztnev”/>
</apply-templates>
</template>
A rendezés iránya is megadható az „order” jellemzővel, melynek a következő értékei lehetnek:
- ascending: növekvő (ez az alapértelmezés)
- descending: csökkenő
<template match=”felsorolas”>
<apply-templates><sort order=”descending”/></apply-templates>
</template>
A dokumentumokban létrehozhatunk egyszerű, vagy többszintű számozott listákat.
<template match=”tetel”>
<number/><apply-templates/>
</template>
Ha a „number” utasítás „level” jellemzőjének értéke „single”, akkor a sorszámozás minden listában elölről kezdődik (ez az alapértelmezés), míg az „any” érték esetén az összes tétel a dokumentumban lévő pozíciójának megfelelő sorszámot kap. Ez utóbbi esetben a „from” jellemzővel megadhatjuk, hogy melyik elemtől kell a sorszámozást elölről kezdeni.
Többszintű sorszámozást úgy adhatunk meg, hogy a „level” jellemzőnek „multiple” értéket adunk. A Count jellemzőben adhatjuk meg a sorszámozni kívánt szintekhez tartozó elemek nevét „|” jellel elválasztva. Ekkor a sorszám több részből állhat, aminek formátumát a „format” jellemzővel határozhatjuk meg. Ha ennek értéke „1.A.”, akkor az elsődleges sorszám számjeggyel, a másodlagos pedig betűvel lesz jelölve, és mindkettő után „.” áll. Ha csak „A”-t adunk meg, akkor betűvel lesznek jelölve a sorok („A”, „B”, …, „Z”, „AA”, „AB”, …). Ha a számjegyes formátumot bevezető nullákkal adjuk meg, akkor a sorszám ennek megfelelően lesz megjelenítve, vagyis a „001” formátum esetében a következőképpen sorszámoz: „001”, „002”, …, „099”. Sorszámozhatunk római számokkal is, akkor „I”-t vagy „i”-t kell megadni attól függően, hogy kis- vagy nagybetűs alakot szeretnénk-e.
Nagyobb sorszámok esetében lehetőség van a tagolásra. A „grouping-separator” jellemzővel megadhatjuk a számjegy csoportokat elválasztó karaktert, míg a „grouping-size” jellemzővel azt, hogy egy csoport hány számjegyből áll (általában 3).
Ha a rendezést és a sorszámozást együtt alkalmazzuk, akkor valószínűleg nem kapunk kielégítő eredményt, mivel először a sorszámozás történik meg, és csak utána a rendezés. Ebből következik, hogy a számok nem sorrendben fogják követni egymást. Ebben az esetben használhatjuk a „value” jellemzőt, amit általában a position() függvénnyel együtt használunk:
<number value=”position()” />