XML

Dokumentum formázása



Dokumentum formázása

Az XML-formátumban szereplő információ publikálásakor szükség van arra, hogy a jelölőelemeket a megfelelő szövegstílusokkal helyettesítsük. Az XSL, az XSLT szabvánnyal kiegészülve arra készült, hogy megfeleljen ezen követelményeknek. Egy XML elem tartalma alapvetően nem rendelkezik stílussal. A megjelenítéshez stíluslapokat használhatunk.

Ugyanazt a stíluslapot több dokumentumnál is felhasználhatjuk. A DTD a stíluslapszerkesztő számára olyan, mint egy követendő specifikáció. Egy XML dokumentumhoz több stíluslapot is rendelhetünk. Az XSL szabvány nem más, mint olyan formázó objektumok halmaza, mint a blokk- és soros elemek, vagy a táblázatcellák. Ezek mindegyike számos jellemzővel rendelkezik annak érdekében, hogy a dokumentum tartalmát professzionális módon lehessen formázni, megjeleníteni. Az XSL egy absztrakt szabvány. Az objektumtípusoknak elemeknek felelnek meg, a tulajdonságoknak pedig azok jellemzői. A szabvány definiál e célra egy DTD-t ez a Formatting Objects DTD vagy FO DTD. Ebben a DTD-ben olyan elemek szerepelnek, mint például a „block”, vagy olyan jellemzők, mint a „text-align”. Ennek a DTD-nek megfelelő dokumentumokban ezekkel az elemekkel kell körülvenni a formázásra szánt objektumokat.

Az XSL feldolgozónak érteni kell az FO DTD-nek megfelelő dokumentumokat. Az XSLT szabály azt a mechanizmust írja le, amellyel a forrás XML dokumentumot publikálásra alkalmas formára hozhatjuk. Az XSLT képes:

·        elő és utótagokkal kiegészíteni a tartalmat

·        elemeket törölni, létrehozni, átsorolni, és sorba rendezni

·        újrafelhasználni az elemeket az objektum egy másik részén

·        az adatokat egyik XML formáról egy másikra, vagy HTML formára alakítani

Az XSLT feldolgozó kész XML dokumentumból állít elő egy másik XML dokumentumot. A kimeneti dokumentum sokszor egy másik DTD-nek felel meg, mint a bemeneti dokumentum. Ezt az átalakítást az XSLT szabványnak megfelelő stíluslappal végzi az XSLT feldolgozó. Az átalakítás a stíluslapban megadott mintaillesztő szabályoknak (template) megfelelően történik.

Az FO elemeket tartalmazó XSL állományok mellett a másik legnépszerűbb kimeneti formátum a HTML..

A tutorial konkrét példán keresztül mutatja be a formázást.

Az XSLT felhasználási területei

Míg a HTML nyelvben keverednek az adatok a formázási utasításokkal, a XSLT és XML nyelvek együttesen lehetőséget adnak az adatok és azok megjelenítésére vonatkozó információk teljes szétválasztására. Ennek különösen nagy hasznát vehetjük a webes alkalmazások készítésekor. Hiszen az oldal arculatának megváltoztatásához elég a XSLT fájlokat lecserélni, nincs szükséges az összes eddig elkészült HTML oldal módosítására. Sőt ez a módszer, jól megválasztott sablonok esetén garantálhatja az oldal egységes megjelenítését is. Ezért több CMS (Content Management System) is használja ezt a technológiát.

Ha az üzleti logikát megvalósító alkalmazás XML kimenetet generál, akkor akár teljes mértékben függetlenné válhat a megjelenítéstől. A megjelenítendő (X)HTML oldal egy következő lépésben egy XSLT transzformáció során készül el. Ez a transzformáció megtörténhet a kliens oldalon, hiszen a legelterjedtebb böngésző programok képesek a transzformáció végrehajtására. Ezzel a módszerrel nagy mértékben csökkenthető az alkalmazás használatakor az adatforgalom is, mert a formázási információkat tároló XSLT stíluslapot csak egyszer kell a kliensnek letöltenie a továbbiakban csak az XML adatokra van szüksége az oldal megjelenítéséhez. Ez a módszer lehetőséget ad továbbá arra is, hogy az web-szerveren futó alkalmazás szolgáltatásait egy kliens oldalon futó alkalmazás (nem böngésző program) egyszerűen érhesse el. Ezen előnyös tulajdonságok ellenére az XSLT technológiát használó webes alkalmazások többsége a transzformációt szerver oldalon végzi el (valószínűleg kompatibilitási okokból).

Az XSLT dokumentum felépítése

Az XMLT lényegében egy xsl kiterjesztésű XML fájl, amelynek a dokumentum eleme kötelezően  http://www.w3.org/1999/XSL/Transform névtérhez tartozik, a dokumentum elemben továbbá fel kell tüntetni a verziószámot is. A tovább elemeknek a xsl névtérhez kell tartozniuk.

Példa érvényes XSLT dokumentum elemre:

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

</xsl:sylesheet>

Az XSLT sablon

A dokumentum elem sablonokat (template) tartalmaz, ezek a sablonok a match tulajdonságban megadott elemekre fognak illeszkedni. Ezt a tulajdonságot egy XPATH kifejezéssel definiáljuk. A sablonok törzsében kerül definiálásra, hogy az illeszkedő XML elemek átalakítása hogyan történjen meg.

Példa egy az XML dokumentum gyökérelemére illeszkedő sablonra:

<xsl:template match="/">

A value-of utasítás

A template elem tartalma kerül a kimenetre minden illeszkedő elem előfordulása esetén. Az eredeti XML dokumentum megfelelő elemeinek a tartalmának beillesztésére a value-of elem szolgál. Amelynek a select tulajdonságában adhatjuk meg a megjelenítendő elem elérési útját.

Példa a catalog/cd/title elem taralmának megjelenítésére alkalmas value-of tag-re:

<xsl:value-of select="catalog/cd/title"/>

A for-each utasítás

Az adott típusú elemeken való végigiterálásra a for-each elem szolgál, amelynek select attribútumában adhatjuk meg az iterálni kíván elemek elérését, mivel az elemek elérését XPATH kifejezéssel adjuk meg. A for-each törzsében pedig az iterálandó feldolgozási utasításokat definiálhatjuk, ezek az utasítások kerülnek a kimenetre minden a select tulajdonságra illeszkedő elem előfordulásánál.

<xsl:for-each select="catalog/cd">

Az eddig tárgyalt XSLT tag-ek segítségével már összetettebb feladat is megoldható. A következő példában egy CD katalógust tároló XML file-t fogunk átalakítani HTML dokumentummá. A katalógus formátuma a következő:

<?xml version="1.0" encoding="ISO-8859-1"?>

<catalog>

  <cd>

    <title>Empire Burlesque</title>

    <artist>Bob Dylan</artist>

    <country>USA</country>

    <company>Columbia</company>

    <price>10.90</price>

    <year>1985</year>

  </cd>

.

.

.

</catalog>

Az XSLT transzformáció a fenti dokumentumból készít egy HTML táblázatot, amelybe a XML-ben tárolt CD-k címei és előadói kerülnek. Az átalakítást a következő XLST írja le:

<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

  <html>

  <body>

    <h2>My CD Collection</h2>

    <table border="1">

    <tr bgcolor="#9acd32">

      <th align="left">Title</th>

      <th align="left">Artist</th>

    </tr>

    <xsl:for-each select="catalog/cd">

    <tr>

      <td><xsl:value-of select="title"/></td>

      <td><xsl:value-of select="artist"/></td>

    </tr>

    </xsl:for-each>

    </table>

  </body>

  </html>

</xsl:template>

</xsl:stylesheet>

Ebben a példában egyetlen sablon van amely az XML dokumentum gyökérelemére illeszkedik. A sablon törzsében felépítjük a HTML dokumentumot egészen a táblázat fejlécéig, a tábla sorainak előállítása során a végigiterálunk a katalógusunk cd elemein egy for-each XSLT tag segítségével, a tag belsejében hozzuk létre a táblázatunk egy sorát. Az iteráció közben az aktuális cd elem title és artist elemének értékét illesztjük be a táblázatunk soraiba egy value-of  utasítás segítségével. A for-each utasítás után pedig a HTML dokumentum lezárása készül el.

Vegyük észre, hogy a fenti példában a for-each select attribútumában egy X-PATH kifejezéssel adtuk meg az iterálandó elemeket. Az X-Path kifejezés megváltoztatásával lehetőségünk arra, hogy a feldolgozandó elemekre megszorításokat tegyünk.

Példa a csak egy meghatározott évben kiadott CD-k adatait feldolgozó for-each utasításra:

<xsl:for-each select="catalog/cd[year='1985']">

A sort utasítás

Az XSLT lehetőséget ad a lekért adatok rendezésére, melyet egy sort elem valósít meg a for-each illetve apply-templates elemeken belül. Megadhatunk egyidejűleg több rendezési kulcsot is a sort elem többszöri beillesztésével, s így azonosság esetén az alatta levő kulcs szerint lesz rendezve. Arra kell figyelnünk, hogy a sort elemek mindig a for-each vagy apply-templates elején szerepeljenek, megelőzve minden literált és XSLT elemet.

A sort elem select jellemzőjének adjuk meg az aktuális kontextus csomóponthoz viszonyított a rendezési kulcsot, vagyis azon elem elhelyezkedési útját, mely tartalma szerint rendezni szeretnénk. A rendezés irányát az order jellemző tartalma határozza meg, mely ascending (növekvő) vagy descending (csökkenő) értékek egyike lehet.

Példa a cd katalógus elemeit előadó szerint rendező sort utasításra:

<xsl:sort select="artist"/>

Az apply-templates utasítás

Egy sablon belsejében lehetőségünk van összes sablonunk újbóli felhasználására, ezzel lehetőségünk nyílik az XML dokumentum rekurzív feldolgozására. A sablonok ismételt felhasználására az apply-templates parancsal utasíthatjuk a feldolgozást végző programot. Azt, mely elemekre alkalmazzuk ismételten a sablonainkat a apply-templates XSLT tag select attribútumában adhatjuk meg.

Példa a cd katalógus előadóira vontkozó apply-templates utasításra:

<xsl:apply-templates select="catalog/cd/artist " />

A fenti parancs az artist elemekre illeszkedő sablonok alkalmazására utasítja a feldolgozó alkalmazást. Ezzel a megoldással az előadókat tartalmazó cellák lértehozását egy különálló artist elemekre illeszkedő sablonnal is elvégezhetjük. A következő példa ezt a megoldási lehetőséget mutatja be.

<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

<html>

<body>

<h2>My CD Collection</h2>

<xsl:apply-templates/>

</body>

</html>

</xsl:template>

<xsl:template match="cd">

<p>

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

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

</p>

</xsl:template>

<xsl:template match="title">

Title: <span style="color:#ff0000">

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

<br />

</xsl:template>

<xsl:template match="artist">

Artist: <span style="color:#00ff00">

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

<br />

</xsl:template>

</xsl:stylesheet>

Az if utasítás

A bizonyos tulajdonsággal rendelkező elemek eltérő feldolgozását az if utasítással végezhetjük el, az if elem belsejében lévő utasítások csak akkor hajtódnak végre, ha a test attribútumában megadott feltétel teljesül. Például az egy meghatározott év után megjelenő lemezek adatai más formában jeleníthetőek meg.

Az if utasítás felépítése:

<xsl:if test="feltétel">

  ...

  ...kimenet abban az esetben ha a feltétel teljesül...

  ...

</xsl:if>

A choose utasítás

Abban az esetben ha nem csak egyetlen feltétel teljesülését szeretnénk megvizsgálni az if használata nagy mértékben ronthatja a XSLT fájl olvashatóságát, ebben az esetben célszerű a choose utasítást használni. A choose elem belsejében when utasítások törzsében adhatjuk meg a test tulajdonságban megadott feltétel teljesülése esetén szükséges kimenetet. Az overwise elemben pedig azt a kimenetet definiálhatjuk, amelyet akkor szeretnénk kapni, ha egyetlen when utasítás feltétele sem teljesül. A choose utasítás végrehajtásakor a feltételek kiértékelése a megadásuk sorrendjében történik. Amennyiben az egyik feltétel teljesül a feldolgozás a choose elemen kívül folytatódik, tehát a végrehajtás nem „csorog” végig az ágakon, a további ágak utasítási akkor sem hajtódnak végre, ha a feltételük teljesül.

A choose utasítás felépítése:

<xsl:choose>

  <xsl:when test="kif1">

    ... kimenet abban ez estben ha kif1 teljesül ...

  </xsl:when>

  <xsl:when test="kif2">

    ... kimenet abban ez estben ha kif1 nem teljesül de kif2 teljesül ...

  </xsl:when>

  <xsl:otherwise>

    ... kimenet abban az esetben ha egyik feltétel sem telesül ....

  </xsl:otherwise>

</xsl:choose>

Attribútumok

XSLT-vel van lehetőségünk nem csak tagok, hanem attribútumok dinamikus létrehozására is. Ehhez kétfajta lehetőséget különböztetünk meg:

Értékadás kapcsos zárójelekkel

Amennyiben az attribútum nevét fixen tudjuk, lehetőségünk van kapcsos zárójelek segítségével dinamikus értéket adni neki. A kapcsoszárójelek közé tetszőleges XPath kifejezést írhatunk.

<xsl:template match="artist">

  <artist name="{value}" />

</xsl:template>

Az xsl:attribute utasítás

Amennyiben teljesen dinamikusan szeretnénk attribútumokat létrehozni, erre lehetőségünk van az xsl:attribute utasítás segítségével, aminek egy nevet adhatunk meg paraméterül, tartalma pedig az attribútum értéke lesz.

<xsl:attribute name="attributum_neve">

  attributum értéke

</xsl:attribute>

Priorítások

Ideális esetben a sablonaink végrehajtási sorrendje egyértelmű, azonban ez nem mindig igaz. A sorrend meghatározásához az XSLT szabvány a következő szabályokat használják:

  1. Az importált sablonok priorítása alacsonyabb
  2. Azok, aminek nagyobb a priority attribútumuk, előrébb vannak
  3. Amennyiben nincs megadva, egy alapértelmezettet kapnak a bonyolultságuk alapján, -1 és 1 között
  4. Ha ezek után van két azonos értékű, és nem lehet eldönteni a sorrendjüket, az hibának vehető

A gyakorlatban az XSLT-implementációk általában nem hibának veszik az azonos priorítást, hanem a definíció sorrendjében használják őket. Bővebben lásd a példák között.

Változók

Lehetőségünk van változók használatára. Ezek a funkcionális nyelvekből megszokott módon működnek, azaz értéket csak egyszer adhatunk nekik, azonban lehetnek lokálisak, ez esetben az adott környezetben mindig kiértékelődnek.

Az xsl:variable utasítás segítségével hozhatjuk létre őket, aminek a name attribútuma határozza meg nevüket, tartalmukat pedig a select attribútumban található XPath kifejezés, vagy belső tartalmuk határozza meg.

Parametrikus sablonok

A sablonoknak adhatunk kötelező, illetve opcionális paramétereket, az xsl:param utasítás segítségével. Az utasításnak egy name, valamint egy select attribútuma van, amivel nevét, illetve az értékét adó XPath kifejezést lehet megadni.

A paramétereknek különösen az xsl:call-template utasítás esetén van szerepe, aminek a segítségével a sablonokat nem mintaillesztéssel, hanem név szerint hívjuk meg.

Módok

A sablonoknál alapesetben egy elemre csak egy szabály értékelődik ki, és csak egyszer. Néha szeretnénk, hogy ez ne így legyen, például amikor egy XML szerkezetét szeretnénk dinamikusan átalakítani. Jó példa erre a sorban lévő adatok fix szélességű HTML-táblázattá alakítása, amiben bizonyos feltételek teljesülése esetén szülőtagokat (tr) kell "beszúrnunk".

Ilyen esetbekben adható meg a "mode" attribútum a sablonoknak, valamint az appy-templates utasításnak. Ez tetszőleges szöveg lehet. Alapértelmezettben a mód nélküli template hajtódik végre (ha nem adunk meg mode attribútumot az appy-templates utasításnak). Amennyiben adunk meg módot, a megfelelő attribútumu sablon fog végrehajtódni.

Whitespace

Az XSLT szabály az alábbi, általában megfelelő szabályokat definiálja a szóközszerű karakterekre:

Az XSLT dokumentum hozzákapcsolása az XML dokumentumhoz

Az XSLT transzformáció elvégzésére XML dokumentumot megjelenítő programot a

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

feldolgozási elemmel utasíthatjuk.

XSLT 2.0

Az eddig ismertetett információk mind szerepeltek az XSLT eredeti, 1.0-s specifikációjában. A további pontokban olyan utasításokról lesz szó, amik csak a későbbi, 2.0-s verzióban kerültek bele a nyelvbe, azonban fontos, sok esetet egyszerűsítő funkciók.

A for-each-group utasítás

Az XSLT első verziójában csak bonyolult körülírással lehetett csoportosítani: például listázni egy CD gyűjteményt az előadók, vagy a kiadás éve szerint. A probléma megoldására az implementációk bevezettek implementáció-specifikus utasításokat, majd a szabvány 2.0-s verziójában átvették ezek egyikét, ez a for-each-group.

Az utasítás nagyon hasonlít a sima for-each-re, az eltérés minimális: A select attribútum mellett kapott egy "group-by" attribútumot is, aminek a segítségével megadható a csoportosítás alapját képező XPath kifejezés, valamint a ciklusonmagon belül használható két új XPath kifejezés. A ciklusmaga maga csoportonként egyszer hívódik meg.

A current-grouping-key() a csoportosítási kifejezés mező aktuális értékét adja meg.

A current-group() pedig visszaadja a csoporthoz tartozó rekordokat, ezt általában egy xsl:for-each select attribútumának adják át.

A példák között szerepel egy csoportosító program, XSLT 1.0, valamint 2.0 alatt, xsl:for-each-group segítségével megvalósítva is.

Számláló ciklus

XSLT 1.0 nem volt lehetőségünk dinamikusan elemeket létrehozni a semmiből, így egyszerű A-tól B-ig számláló ciklust sem tudtunk megvalósítani, ahol garantáltan nem akartunk kihagyni számokat.

XSLT 2.0 alatt erre a legegyszerűbben az XPath 2.0 segítségével van módunk, ami már jóval bonyolultabb utasításokat is megenged, mint elődje.

A bonyolultabb utasítások egyike a for ciklus, aminek segítségével írhatunk olyanokat, mint:

for $i in 1970 to 2000 return $i

Vagy ugyanez akár még egyszerűbben:

1970 to 2000

Az ilyen módon felírt XPath kifejezések ugyanúgy megadhatóak egy xsl:for-each select attribútumának, mint a dokumentumot ténylegesen használó társaik.

Reguláris kifejezések

Az XSLT 1.0 stringműveletei igen szűkösek voltak, aminek kiegészítésére létrejött több függvénykönyvtár, amik még ma is megtalálhatóak a neten. XSLT 2.0 alatt a probléma nagyrészét megoldja a reguláris kifejezések támogatása, az xsl:analyze-string utasítás segítségével.

Az utasításnak megadhatunk egy XPath kifejezést a select attribútumként, valamint regex néven egy Perl kompatibilis reguláris kifejezést. A tagon belül két tagot helyezhetünk, illetve kell elhelyeznünk:

Az xsl:non-matching-substring tartalma akkor hajtódik végre, ha a szöveg nem illeszkedik a reguálir kifejezésünkre.

Az xsl:matching-substring pedig akkor, amikor illeszkedik. Ezen belül használható a regex-group(n) XPath függvény, ami az N. zárójellel határolt részkifejezés értékét adja vissza.

Több kimenet

Vannak esetek, amikor nem csak egy dokumentumot szeretnénk kimenetként visszaadni, hanem többet is. Ilyenre lehet példa, amikor az XSLT programunk várható futásideje igen hosszú, ezért a futása közben szeretnénk szöveges visszajelzést adni az állapotáról, vagy amikor egy dokumentumot szeretnénk sok kisebbre szétbontani

A megoldás az xsl:result-document utasítás, aminek href attribútumként adhatunk egy fájlnevet, valamint a method attribútummal megadhatjuk, hogy szöveget (text), vagy xml-t (xml) szeretnénk kiíratni vele.

Fontos korlátozás, hogy egy dokumentumot csak egyszer nyithatunk meg. Erre a korlátozásra azért van szükség, mert az XSLT-nek elég sok lehetősége van párhuzamosítással optimalizálni, így nem alapozhatunk az utasítások végrehajtási sorrendjére.

A korlátozás legszembetűnőbb megnyilvánulása, hogy nem tehetjük a result-document-et for-each, vagy egyéb, többször lefutó tagba úgy, hogy azonos fájlnévvel fusson le mégegyszer. Ennek kiküszöbölésére a tagot ki kell emelni külsőbb szintre, ami garantáltan csak egyszer fut le.

Függvények

A függvények, bár nevükből elsőre nem erre következtetnénk, az XPath-hoz kapcsolódnak. Lehetőséget adnak XSLT segítségével új XPath függvények létrehozására, amiket aztán XPath kifejezésekben használhatunk, például feltételekben.

A defínicióhoz az xsl:function utasítás használható, a name attribútumban a nevével, az as asttribútumban pedig a típusával (pl. xs:string vagy xs:bool). A paraméterei ugyanúgy az xsl:param utasítással sorolhatóak fel, mint sablonok esetén.

Az XLST specifikáció, kapcsolódó anyagok

Az XSLT szabvány a W3C konzorcium ajánlása. A fentiekben bemutatott utasítások mindegyike részét képezi a 2007-ben elkészült XSLT 2.0 specifikációnak, amely a http://www.w3.org/TR/xsl/ címen érhető el.

Jelenleg folyik az XSLT szabvány  3.0-ás verziójának  specifikációja  amely http://www.w3.org/TR/xslt30/ címen érhető el,.

A XSLT technológia megértését elősegítő tutorial-ok és leírások a következő címeken érhetőek el:

Magyarul:

·        http://www.prog.hu/cikkek/900/XML+dokumentumok+megjelenitese+stiluslapok+segitsegevel/oldal/1.html

·        http://www.zvon.org/xxl/XSLTutorial/Output_hun/contents.html

Angolul:

·        http://www.w3schools.com/xsl/xsl_intro.asp

·        http://nwalsh.com/docs/tutorials/xsl/xsl/slides.html

·        http://www.brics.dk/~amoeller/XML/transformation/index.html