Tijdschrift voor webwerkers » Artikel #56
XSL (eXtensible Stylesheet Language) is de verzamelnaam voor een aantal specificaties van het W3C (World Wide Web Consortium). Allemaal hebben ze te maken hebben met het omzetten en visueel weergeven van XML documenten:
XSL Transformations (XSL-T)
Een taal om XML documenten te transformeren naar een ander XML formaat. Van XML naar XHTML bijvoorbeeld. XSL-T is het hoofdonderwerp van dit artikel. Een voorbeeld van zo’n transformatie zou kunnen zijn dat je een RSS feed neemt en die in een layout gooit.
XML Path Language (XPath)
XPath is een syntax die je kunt gebruiken om delen van een XML document aan te spreken. XSL-T gebruikt deze expressies om te beslissen welk stukje inhoud als volgende getoond moet worden.
XSL Formatting Objects (XSL-FO)
Wil je van XML naar een PDF document (Portable Data Format), dan kun je dat doen door je XML eerst om te zetten naar een ander XML document met zogenaamde formatting objects. Daarna kun je via een tool als FOP (Formatting Objects Processor) een PDF document genereren.
Eerst en vooral: Waarom zou iemand nu een XML document willen transformeren? Hebben we niet genoeg aan CSS (Cascading Style Sheets)? Even vergelijken:
CSS is op zich heel simpel. Het enige dat je kunt doen is een tag aanduiden en er enkele eigenschappen van aanpassen.
.example {
display: block;
color: #000;
background-color: #eee;
padding: 5px;
border: 2px solid #bbb;
}
XSL-T daarentegen biedt heel wat meer mogelijkheden:
Net als CSS kun je de presentatievorm wijzigen, zonder het originele XML-document te moeten aanpassen. Daarnaast kun je nog met de volgorde van de informatie spelen, bepaalde informatie volledig verbergen of meerdere keren weergeven. Je kunt zelfs nieuwe inhoud toevoegen.
Enkele voorbeelden van mogelijk gebruik:
Genoeg theorie, tijd voor het echte werk nu...
In dit artikel gebruiken we een eenvoudig XML-document om de basiswerking van XSL-T te illustreren. Laten we er van uitgaan dat Naar Voren beschikt over een XML-databank met informatie over alle reeds verschenen artikels. Een extract vind je hier: (bekijk volledig bestand)
<website>
<titel>Naar Voren</titel>
<inhoud>
<artikel id="1">
<titel>De eerste 9 seconden</titel>
<auteur>Robert Jan Verkade</auteur>
<abstract>Angst voor de onuitwisbare eerste
indruk? [...]</abstract>
</artikel>
<artikel id="2">
<titel>We gaan van linkestein</titel>
<auteur>Remco Sikkema</auteur>
<abstract>Als je een beetje verder kijkt
dan je neus lang is,[...]</abstract>
</artikel>
</inhoud>
<url>http://www.naarvoren.nl/</url>
</website>
Het belangrijkste wat je moet begrijpen bij het verstaan van XSL-T, is dat elk XML-document gezien kan worden als een boom. XSL-T zet de bronboom om in een doelboom. De bronboom die bij ons voorbeeld hoort zou er dan als volgt uitzien:
Laten we vanuit onze XML databank de Naar Voren archiefpagina proberen na te bouwen. We willen dus een HTML document met ergens een tabel, die voor elk artikel een rij bevat. Een simplistische weergave van deze uitvoerboom hieronder:
Allereerst geven we de volledige XSL-T transformatie die we zullen gebruiken (althans, het stuk waar XSL aan te pas komt). De XSL-elementen worden vet weergegeven. (bekijk volledige bestand)
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.1"
XMLns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="/website">
<html>
<head>
<title><xsl:value-of select="titel" />
archief</title>
...
</head>
<body>
...
<table cellspacing="0" id="archief">
<tr>
<th id="kop1">nr.</th>
<th id="kop2">titel & auteur</th>
<th id="kop3">het gaat over...</th>
</tr>
<xsl:for-each select="inhoud/artikel">
<xsl:sort order="descending"
select="number(@id)" data-type="number" />
<tr>
<td headers="kop1">
<strong><xsl:value-of
select="@id" /></strong>
</td>
<td headers="kop2">
<xsl:element name="a">
<xsl:attribute name="href">
/artikel/<xsl:value-of select="@id" />
</xsl:attribute>
<xsl:value-of select="titel" />
</xsl:element>
<br />
<xsl:value-of select="auteur" />
</td>
<td headers="kop3">
<xsl:value-of select="abstract" />
</td>
</tr>
</xsl:for-each>
</table>
...
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Als je goed kijkt, merk je dat dit als het ware een skelet is voor de archiefpagina die we willen bereiken.
Bekijken we eerst het root-element van de transformatie:
<xsl:stylesheet version="1.1"
XMLns:xsl="http://www.w3.org/1999/XSL/Transform"
>
De xmlns:xsl
namespace declaratie is uiterst belangrijk. Het komt er op neer dat binnen het stylesheet document alle elementen waarvan de naam begint met de xsl:
prefix gelinkt worden aan de URL http://www.w3.org/1999/XSL/Transform
. De meeste XSL-T verwerkers weigeren actie als hier een andere URL wordt vermeld.
Het xsl:stylesheet
element bevat de volledige logica van de stylesheet, net zoals een html
element een volledige webpagina bevat.
Zo’n XSL stylesheet bestaat uit één of meerdere templates. Een template komt overeen met een deel van de invoerboom als het match
attribuut voldoet.
<xsl:template match="/website">
...
</xsl:template>
Het match attribuut is in feite een XPath expressie. Via zo’n expressie kan je een of meer elementen aanduiden in een XML-boom. De syntax is zoals die van bestandssystemen: een slash (/) duidt een lager niveau aan. Enkele voorbeelden van expressies vind je hieronder:
/website
: (zoals ons voorbeeld) website-element, direct onder de root van het documentinhoud/artikel
: artikel elementen, als kind van inhoud, wat dan weer een kind is van de huidige knoop@id
: id-attribuut van de huidige knoopartikel[@id=1]
: artikel-elementen waarvan het id attribuut gelijk is aan 1artikel[position()=last()]
: laaste artikel-elementancestor::website
: een voorouder-website-elementartikel|dossier
: artikel of dossier elementenXPath expressies kunnen dus heel krachtig zijn als het moet. Binnen XSL-T worden ze her en der gebruikt, zoals we verder zullen merken.
Terug naar het template nu. Wanneer XSL-T een document omzet, kiest het eerst de root-knoop van de bronboom, en gaat op zoek naar een geschikt template om het te behandelen. Tijdens het behandelen van een template kunnen andere templates opgeroepen worden (via xsl:apply-templates
). De huidige knoop wordt dan de basis voor het kiezen van nieuwe templates. In ons voorbeeld zullen we het echter bij één template houden.
Wanneer een template wordt uitgevoerd, wordt z’n inhoud naar de uitvoer gekopieerd. Tenzij er xsl:
elementen voorkomen, want dan komt XSLT terug in actie. In ons voorbeeld wordt de uitvoer een HTML pagina.
Invoegen van waarden uit het XML document gebeurt via <xsl:value-of select="..." />
. Het select
-attribuut is alweer een XPath expressie, en vertelt de XSL-T processor wat precies moet worden ingevoegd. Zo voegt het volgende voorbeeld de website-titel toe wanneer uitgevoerd in de context van het website
element, of de titel van een artikel wanneer de context een artikel
element is.
<xsl:value-of select="titel" />
Voor onze archieflijst moeten we itereren over alle artikels, en voor elk artikel een tabelrij uitvoeren. Voor de iteratie heeft XSL-T het xsl:for-each
element klaar. We willen ook een andere volgorde dan in de XML versie (we willen het nieuwste artikel — met hoogste id — eerst zien). Hiervoor kunnen we xsl:sort
gebruiken.
<xsl:for-each select="inhoud/artikel">
<xsl:sort order="descending" select="number(@id)"
data-type="number" />
<tr>
<td headers="kop1">
<strong><xsl:value-of select="@id" /></strong>
</td>
<td headers="kop2">
<xsl:element name="a">
<xsl:attribute name="href">
/artikel/<xsl:value-of select="@id" />
</xsl:attribute>
<xsl:value-of select="titel" />
</xsl:element>
<br />
<xsl:value-of select="auteur" />
</td>
<td headers="kop3">
<xsl:value-of select="abstract" />
</td>
</tr>
</xsl:for-each>
Het select
attribuut bij het for-each element is opnieuw een XPath expressie. Ze geeft aan dat we over alle artikels willen itereren. Omdat de huidige knoop /website is, zullen we dus alle /website/inhoud/artikel elementen overlopen. Het lichaam van het for-each element wordt herhaald voor elk zo’n element.
De xsl:sort
instructie komt binnen de for-each
terecht. We willen aflopend (descending) sorteren op het id-attribuut (@id
) van de artikels. Het is ook noodzakelijk om number
te vermelden als data-type
, omdat anders alfabetisch gesorteerd wordt en ‘19’ voor ‘9’ zou komen.
Voor elk artikel plaatsen we een tabelrij met id, titel, auteur en abstract. Rond de titel plaatsen we een link. Dit gaat echter niet zo eenvoudig in XSL-T: volgend voorbeeld zou immers een XML parse error geven:
<a href="/artikel/<xsl:value-of select="@id">"></a>
Daarom moeten we werken via de xsl:element
en xsl:attribute
elementen.
We hebben nu een XML document en een transformatie. Nu rest ons alleen nog de transformatie uit te voeren.
Een eerste mogelijkheid is de transformatie door de webbrowser te laten uitvoeren. Moderne browsers zoals Mozilla-varianten en Internet Explorer hebben immers een XSL-T processor aan boord. Je hoeft enkel een regel toe te voegen bovenaan het XML document:
<?xml-stylesheet type="text/xsl"
href="archief.xsl" ?>
Nadelig aan deze methode is dat je slechts één stylesheet aan een XML document kan koppelen, en dat de client de ruwe inhoud van het XML document kan bekijken.
Ons voorbeeld van hierboven, met zo’n instructie: naarvoren-browser.xml
Manueel omzetten kan met Instant Saxon van Michael Kay. Vanuit de command line kan je als volgt transformeren:
saxon -o artikel/ naarvoren.xml archief.xsl
Vanuit een programmeertaal is het al helemaal geen probleem. Er zijn tal van libraries beschikbaar en heel wat talen komen tegenwoordig met ingebouwde XSL-T ondersteuning. Voor Java is er bijvoorbeeld de Xalan processor, en PHP beschikt over een stel xslt_
functies
Het resultaat van de transformatie uit ons voorbeeld kan je zien op deze pagina (naarvoren.xml + archief.xsl).
let op: de in het voorbeeld gebruikte links leiden niet naar de juiste pagina, ze dienen slechts als voorbeeld.
Dit voorbeeld illustreerde slechts enkele van de mogelijkheden van XSL-T. Er is echter meer mogelijk. Veel meer. Voor de lezer die wat meer wil is er een alternatieve stylesheet beschikbaar die de artikels groepeert per auteur. Resultaat daarvan vind je hier.
is in het dagelijkse leven software-ontwikkelaar. Sinds begin 2000 houdt hij het weblog Karma Universe bij.
Verder ontwikkelt hij in z’n vrije tijd ook nog Nucleus
Publicatiedatum: 03 september 2003
Naar Voren is op 18 juli 2010 gestopt met publiceren. De artikelen staan als een soort archief online. Het kan dus zijn dat de informatie verouderd is en dat er inmiddels veel betere of makkelijkere manieren zijn om je doel te bereiken.
Copyright © 2002-heden » NAAR VOREN en de auteurs