9 XSL-muunnokset XML-dokumenttien keskeinen rooli on välittää tietoa sovellusten välillä. Yksinkertaisimmillaan tämä tarkoittaa sitä että tieto tuotetaan suoraan tietyn sovelluksen tekstiformaattiin. Lähestymistavan huono puoli on tekstiformaateista sopimisen vaiva ja pahimmassa tapauksessa sitoutuminen "köyhään" tietorakenteeseen. Yleisemmin parempi ratkaisu on tuottaa tietoa kohdesovellukseen muunnosten avulla. Tällöin tietoa kuvataan sovellusten välillä ohjelmallisesti, mikä helpottaa (XML-)sovellusten yhdistämistä. Yksinkertaisimmillaan muunnos on "tyylipohja" joka esittää tietyn tietosisällön esim. XHTML-sivuna. MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 157
9.1 Konseptiesimerkki A Tiedon ohjelmallinen kuvaaminen sanastosta toiseen on tyypillinen XML-sovellusten yhdistelyyn liittyvä tehtävä Case (huom. sis. monikanavajulkaisun ja käärimisen): - asiakashallintaohjelma A tuottaa tekstimuotoisia raportteja joita halutaan katsella/tulostaa/siirtää toisiin järjestelmiin raportti XSLTprosessori XHTML - sen sijaan että A ohjelmoitaisiin tuottamaan raporttinsa esim. XHTMLformaatissa, ohjelmoidaan tuloste omassa XML-formaatissa raportti - kirjoitetaan muunnos (tiedosto a2h.xsl) T: raportti XHTML a2h.xsl -...näin raportista voidaan helposti tuottaa muitakin esitystapoja, (raportin tietomallia ei tarvitse valita XHTML:n rajoitusten mukaan), jos XHTMLversio halutaan vaihtaa, muokataan vain muunnosta, kokonaan uusi kohdesovellus? ei edellytä A:n muokkaamista, vain uudentyyppisen muunnoksen kirjoittamista, jne. MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 158
9.2 Extensible Stylesheet Language: Transformations XML-perheen suositus XSLT (1.0) määrittelee ns. XSLT-prosessorin tai muuntimen toiminnallisuuden Muunnos on tietokoneohjelma joka kuvaa lähdedokumentin jäsennyspuun toiseen muotoon kohdedokumentin (tai tulosdokumentin) jäsennyspuuna - muunnos voi hyödyntää kaikkea XML-dokumentista löytyvää informaatiota (loogisen rakenteen osalta), mukaan lukien kommentit ja prosessointiohjeet MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 159
9.3 Esimerkki: yksinkertainen muunnos <?xml version="1.0" encoding="iso-8859-1"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform" version="1.0"> <xsl:output method="html" indent="yes" encoding="iso-8859-1" doctype-public="-//w3c//dtd HTML 4.0 Transitional//EN" /> <xsl:template match="/music"> <html> <head> <title>esimerkki</title> <style type="text/css"> body { background: yellow;} </style> </head> <body> <xsl:apply-templates/> </body> </html> </xsl:template> <xsl:template match="album"> <h2> <xsl:value-of select="@artist"/> </h2> <xsl:apply-templates/> </xsl:template> </xsl:stylesheet> MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 160
9.4 Tekniikkaa XSLT tarjoaa kielen muunnosten kuvaamiseen se ei vielä yksin riitä Suositus XPath (XML Path Language (XPath) 1.0) tarjoaa kielen jäsennyspuiden osiin viittaamiseksi - "osoitin- ja ohjelmointikieli" (vrt. CSS2-valitsimet) Kohdesovellus voi olla mikä tahansa XML-tekstiformaatti - nimiavaruuksia tarvitaan erottamaan XSL kohteesta - lähdedokumentti (puu) on mv. XML-dokumentti - tulosdokumentti (puu) on mv. XML/HTML/tekstidokumentti (tai tekstientiteetti) XSLT:tä voidaan luonnehtia mallipohjaiseksi tai funktionaaliseksi ohjelmointikieleksi MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 161
9.5 Muunnoksen yleisrakenne Kärjistäen, tyypillinen XSL-muunnos sisältää seuraavat osat: output-osa kertoo tulospuun sarjallistuksen (ja esim. kohdedokumentin tyypin) Säännöt (template) määrittelevät muunnoksen loogisen sisällön (tiedon kuvaus lähdepuusta tulospuuksi) Parametrit tarjoavat keinon ohjata muunnoksia ulkoapäin, lähdedokumenttien ohella (esim. kytkiminä XSLT-prosessorille) Muunnokseen voidaan myös sisällyttää (include ja import) osia toisista muunnostiedostoista (modulaariset muunnokset) Suurin osa opiskelusta on sääntöjen ja näihin liittyvien "lauserakenteiden" ja komentojen opiskelua (...ja kohdesovellusten opiskelua...) MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 162
9.6 Sääntöjen anatomia Säännöt kirjoitetaan mallipohjien (template) avulla Sääntö aktivoituu lähdepuun aktiivisen kontekstin perusteella, säännön hahmon (pattern) ohjaamana Aktivoitunut sääntö tuottaa tulospuun ko. kohtaan sisältönsä, komentojen ohjaamana Sääntöjen (rekursiivinen) ketjutus ja oletussäännöt MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 163
9.7 XSLT-jäsennyspuun osat Muunnos näkee lähdedokumentin esiintymäosan solmuista koostuvana puuna - juurisolmu - elementtisolmut, attribuuttisolmut, prosessointiohjesolmut, tekstisolmut, - kommenttisolmut, nimiavaruussolmut Jokaista loogista elementtiä kohti löytyy rakenteensa XPath-kielestä sekä komentoja ko. tyyppisen tiedon käsittelyyn ja generoimiseen Solmun (suhteellinen) sijainti puussa osoitetaan ns. akselin avulla (vrt. CSS) - ancestor, ancestor-or-self, attribute, child, descendant, descendant-or-self, following, following-sibling, namespace, parent, preceding, precedingsibling, self MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 164
9.8 Hahmojen kielioppi (XPath & lokaatiopolku) Lokaatioaskelten kolmiosainen rakenne (akseli::solmutesti[predikaatti]): child::kirja/child::luku[position()=5]/child::kappale[position()=2] Käytössä on lyhennemerkintöjä. Esimerkkejä: para matches any para element * matches any element chapter appendix matches any chapter element and any appendix element olist/item matches any item element with an olist parent appendix//para matches any para element with an appendix ancestor element / matches the root node text() matches any text node processing-instruction() matches any processing instruction node() matches any node other than an attribute node and the id("w11") para[1] root node matches the element with unique ID W11 matches any para element that is the first para child MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 165
element of its parent *[position()=1 and self::para] matches any para element that is the first child element of its parent para[last()=1] matches any para element that is the only para child element of its parent items/item[position()>1] matches any item element that has a items parent and that is not the first item child of its parent item[position() mod 2 = 1] would be true for any item element that is an odd-numbered item child of its parent. div[@class="appendix"]//p matches any p element with a div ancestor element that has a class attribute with value appendix @class matches any class attribute (not any element that has a class attribute) @* matches any attribute MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 166
Vastaavasti esimerkkejä täydellisten lausekkeiden avulla child::para selects the para element children of the context node child::* selects all element children of the context node child::text() selects all text node children of the context node child::node() selects all the children of the context node, whatever their node type attribute::name selects the name attribute of the context node attribute::* selects all the attributes of the context node descendant::para selects the para element descendants of the context node ancestor::div selects all div ancestors of the context node ancestor-or-self::div selects the div ancestors of the context node and, if the context node is a div element, the context node as well descendant-or-self::para selects the para element descendants of the context node and, if the context node is a para element, the context node as well MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 167
self::para selects the context node if it is a para element, and otherwise selects nothing child::chapter/descendant::para selects the para element descendants of the chapter element children of the context node child::*/child::para selects all para grandchildren of the context node / selects the document root (which is always the parent of the document element) /descendant::para selects all the para elements in the same document as the context node /descendant::olist/child::item selects all the item elements that have an olist parent and that are in the same document as the context node child::para[position()=1] selects the first para child of the context node MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 168
child::para[position()=last()] selects the last para child of the context node child::para[position()=last()-1] selects the last but one para child of the context node child::para[position()>1] selects all the para children of the context node other than the first para child of the context node following-sibling::chapter[position()=1] selects the next chapter sibling of the context node preceding-sibling::chapter[position()=1] selects the previous chapter sibling of the context node /descendant::figure[position()=42] selects the forty-second figure element in the document MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 169
/child::doc/child::chapter[position()=5]/child::section[position()=2] selects the second section of the fifth chapter of the doc document element child::para[attribute::type="warning"] selects all para children of the context node that have a type attribute with value warning child::para[attribute::type='warning'][position()=5] selects the fifth para child of the context node that has a type attribute with value warning child::para[position()=5][attribute::type="warning"] selects the fifth para child of the context node if that child has a type attribute with value warning child::chapter[child::title='introduction'] selects the chapter children of the context node that have one or more title children with stringvalue equal to Introduction MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 170
child::chapter[child::title] selects the chapter children of the context node that have one or more title children child::*[self::chapter or self::appendix] selects the chapter and appendix children of the context node child::*[self::chapter or self::appendix][position()=last()] selects the last chapter or appendix child of the context node MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 171
9.9 Laajempi esimerkki: music HTML(4) Tuotetaan musictiedoista Web-sivu Esimerkissä esille nousevia tyypillisiä pulmia/tehtäviä: - ohjelmoinnin pulmat idref id music.xml copy.xml bandinfo.xml XSLT-prosessori m2h.xsl - mallintamisen pulmat, erityisesti: miten tieto jaetaan eri dokumenttien kesken (normalisointi, avaimet, asiasisältö vs. tyyli, yms.) - teknisen kirjoittamisen pulmat out.html -...tyypitys, kieliversiointi, lokaalit, tiedon ylläpito, virhetilanteiden hallinta, suorituskyky, yms. MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 172
9.10 Takaisin perusteisiin: oletussäännöt Prosessoinnin jatkaminen (kaikilla moodeilla) <xsl:template match="* /"> <xsl:apply-templates/> </xsl:template> <xsl:template match="* /" mode="m"> <xsl:apply-templates mode="m"/> </xsl:template> Tekstin tuottaminen <xsl:template match="text() @*"> <xsl:value-of select="."/> </xsl:template> Prosessointiohjeiden ja kommenttien sivuuttaminen <xsl:template match="processing-instruction() comment()"/> Myös oletussäännöt voi määritellä uudelleen MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 173
9.11 Output XSL-muunnos käsittelee lähinnä tiedon loogista kuvaamista lähdepuusta kohdepuuksi, tiedon sarjallistus on kuitenkin useissa sovelluksissa keskeistä <!-- Category: top-level-element --> <xsl:output method = "xml" "html" "text" qname-but-not-ncname version = nmtoken encoding = string omit-xml-declaration = "yes" "no" standalone = "yes" "no" doctype-public = string doctype-system = string cdata-section-elements = qnames indent = "yes" "no" media-type = string /> Huomioita: XML vs. HTML vs. teksti MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 174
9.12 XSLT-komennot (1/2) Kohdesolmujen tuottaminen (ns. literaalien ohella): - xsl:element, xsl:attribute (ja xsl:attribute-set), xsl:text, xsl:processinginstruction, xsl:comment - vrt. erot literaalien kanssa (attribuutit ja kommentit!) Lähdepuun kopiointi - xsl:copy, xsl:copy-of Tekstin tuottaminen - xsl:value-of Numerointi - xsl:number MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 175
9.13 XSLT-komennot (2/2) Toistolauseet - xsl:for-each - vrt. sääntöjen suorittaminen Ehtolauseet - xsl:if, xsl:choose, xsl:when, xsl:otherwise Järjestäminen - xsl:sort Muuttujien käsittely - xsl:variable, xsl:param Muuta: Viestit ja laajennukset MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 176
9.14 Lausekkeet ja funktiot (XPath ja XSLT) XPath-kieli sisältää ohjelmoinnissa tyypillisesti tarvittavat rakenteet - tietotyypit (node-set, boolean, number, string) - muuttujat ($v), liukuluvuilla laskeminen (+, -, *, div, mod) ehtolausekkeet (or, and, =,!=, <=, <, >=, >) ja funktioiden kutsuminen (concat($v,$x)) - huomaa < ja '/""-merkkien käyttö merkkijonoissa (XML-tekstiä!) Kuten yleensä ohjelmoinnissa, lisäksi tarvitaan aliohjelmakirjastoja (joista osa olisi periaatteessa kuitenkin mahdollista kirjoittaa esim. sääntöinä) XSL-muunnosten yhteydessä käytössä ovat - Node Set Functions, String Functions, Boolean Functions, Number Functions, XSLT:n omat funktiot (erit. node-set document(object, nodeset?) ja node-set key(string, object)) Mahdolliset laajennukset MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 177
9.15 Muuttujien käsittelystä Funktionaalisen ohjelmoinnin hengessä muuttujat (muotoa $nimi) instantioidaan kerran ilman "päällekirjoittamisen" mahdollisuutta (tämä ei yleensä ole ongelma koska sääntöjä kutsutaan funktionaalisesti) Muuttujia tarvitaan esim. sääntöjen paloitteluun, merkkijonojen käsittelyyn (funktioiden käyttö) ja viittausrakenteiden kokoamiseen Keskeinen käyttö on myös parametrien välittäminen muunnoksille (päätason komentona) <xsl:param name="year" select="."/> Attribuuttien arvoina muuttujien evaluointi onnistuu myös sijoitusoperaation avulla ({ }-notaatio ja ns. attribute value template) <xsl:variable name="image-dir">/images</xsl:variable> <xsl:template match="photograph"> <img src="{$image-dir}/{href}" width="{size/@width}"/> </xsl:template> MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 178
9.16 XSLT ja nimiavaruudet (1/3): literaali oletusnimiavaruus XSL-muunnos voi tietenkin tuottaa myös tiettyyn nimiavaruuteen liittyviä kohdedokumentteja (tarvitaan aina jo esim. XHTML-sovelluksissa!) Helpoimmillaan tämä tarkoittaa vain xmlns-attribuutin käyttöä literaalina: <xsl:template match="/music"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>esimerkki</title> </head> <body> <h1>dokumentin tietoja</h1> <p><xsl:value-of select="album[1]/name" /> </p> </body> </html> </xsl:template> Oletusnimiavaruus ei kuitenkaan välity säännöstä toiseen (ts. asetettava joka säännössä erikseen) Mieti miksi mallipohja ja XSL-komennot tulkitaan oikein MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 179
9.17 XSLT ja nimiavaruudet (2/3): kvalifioidut literaalit Myös kvalifioitujen nimien käyttö on mahdollista: <!--... --> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform" version="1.0" xmlns:xh="http://www.w3.org/1999/xhtml"> <!--... --> <xsl:template match="/music"> <xh:html> <xh:head><xh:title>esimerkki</xh:title></xh:head> <!--... --> </xh:html> </xsl:template>...tällöin lopputulos ei kuitenkaan ole aina toivottu! (joskin se on "oikea") <?xml version="1.0" encoding="iso-8859-1"?> <xh:html xmlns:xh="http://www.w3.org/1999/xhtml"> <xh:head> <xh:title>xslt-komentodemo</xh:title> </xh:head> <!--... --> </xh:html> MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 180
9.18 XSLT ja nimiavaruudet (3/3): kvalifioidut hahmot Muunnoksen lähdedokumenttikin voi tietenkin kuulua tiettyyn nimiavaruuteen...tällöin XSLT sotkee merkkausprefiksit ja hahmojen sisällön, vrt. oheinen XHTML-dokumenttiin kohdistuva muunnos: <?xml version="1.0" encoding="iso-8859-1"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform" version="1.0" xmlns:xh="http://www.w3.org/1999/xhtml" exclude-result-prefixes="xh"> <!-- ei haluta kohteeseen! --> <xsl:output method="xml" indent="yes" encoding="iso-8859-1" /> <xsl:template match="/xh:html/xh:head"> <foo> <xsl:value-of select="xh:title" /> </foo> </xsl:template> <xsl:template match="text()" /> </xsl:stylesheet> MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 181
9.19 Lyhennemerkintä: literaalista koostuva XSL-muunnos XSLT määrittelee lyhennemerkinnän yksinkertaisten muunnosten kirjoittamiseen - perusidea: muunnosdokumentti vastaa yhden implisiittisen säännön mallipohjaa jossa hahmona on "/" <html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform" xmlns="http://www.w3.org/tr/xhtml1/strict"> <head> <title>expense Report Summary</title> </head> <body> <p>total Amount: <xsl:value-of select="expense-report/total"/></p> </body> </html> Muunnoksen syntaksi on tällöin kuitenkin rajoittunut (ei muita sääntöjä eikä päätason elementtejä) MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 182
9.20 Pari sanaa XSL-perheestä XSL-perhe sisältää (hieman määrittelytavasta riippuen) tekniikat XSLT, XPath ja XSL-FO (XSL Formatting Objects) XSL-FO määrittelee (ideatasolla) hieman Postscriptiä muistuttavan XMLpohjaisen formatointikielen -...taitollisesti ja sommitelmallisesti tarkkaa tulostusta silmälläpitäen (vrt. HTML toisena ääripäänä) -...XSL-FO-prosessori MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 183
9.21 XSL-FO, perusidea XSL-FO hyödyntää CSSkäsitteistöä (formatointiominaisuuksien osalta) mutta tarjoaa huomattavasti monipuolisemman formatointimallin (sis. esim. sivutuksen, ylä- ja alaotsikot, mallipohjan yms. käsitteet) XSL-FO:ta on (raskaasti) kritisoitu semantiikan puutteesta (vrt. HTML & font-elementti) MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 184
9.22 XSL-FO, esimerkki (ks. zvon.org) lähdedokumentti ja formatoitu tulosdokumentti (esim. PDF-muodossa) <fo:root xmlns:fo="http://www.w3.org/1999/xsl/format" > <fo:layout-master-set> <fo:simple-page-master mastername="simple" page-height="15cm" pagewidth="15cm"> <fo:region-body/> </fo:simple-page-master> </fo:layout-master-set> <fo:page-sequence master-reference="simple"> <fo:flow flow-name="xsl-region-body"> <fo:block>square page 15cm x 15cm</fo:block> </fo:flow> </fo:page-sequence> </fo:root> MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 185
9.23 Lopuksi Web-selaimet eivät tue XSL-muunnoksia luotettavasti -...käytännön vaihtoehtoja ovat muunnokset osana esim. sisällöntuotantojärjestelmiä tai palvelinpäässä Monimutkaiset muunnokset ovat kuitenkin melko hitaita ja saattavat kuluttaa paljon muistia - heikosti optimoitu muunnin pitää yhtä aikaa työmuistissa koko lähde- ja tulospuun yms. XPath ja XSLT -tekniikoista on kehitteillä kakkosversiot - XPath 2 kehittyy esim. XQueryn "suuntaan", XSLT 2 puolestaan mahdollistaa sääntöjen kohdistamisen myös tulospuuhun sekä usean tulospuun tuottamisen yhdellä ajolla (XSLT:tä on kritisoitu tämän ohella myös mm. sääntöjen kömpelöstä kirjoitusasusta) MATHM-47150 RAKENTEISET DOKUMENTIT (kevät 2006) - ON 186