xsl:apply-templates
Om vi skriver program i ett "normalt" programmeringsspråk blir
det fort en ruskig "spagettikod" om man inte använder subrutiner
(Sub och Function för VB programmerare - riktiga programmerare har bara
function). Motsvarande gäller även för XSL. Man måste få
någon form av subrutiner för att strukturera koden.
Nedan kommer ett exempel på apply-templates.
XML filen:
xml24_2.xml
<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet type="text/xsl" href="xml24_2.xsl"?>
<!DOCTYPE racers [
<!ELEMENT racers (driver*) >
<!ELEMENT driver (name, nationality,description?) >
<!ATTLIST driver type (F1 | rally) #REQUIRED>
<!ELEMENT name (#PCDATA) >
<!ELEMENT nationality (#PCDATA) >
<!ELEMENT description (#PCDATA) >
]>
<racers>
<driver type="F1">
<name>Mika Häkkinen</name>
<nationality>Finn</nationality>
<description>
Tvåfaldig värlsdmästare och
pappa till Hugo. Bättre än Schumi!
</description>
</driver>
<driver type="rally">
<name>Marcus Grönholm</name>
<nationality>Finn</nationality>
<description>Finlandssvensk</description>
</driver>
<driver type="rally">
<name>Colin McRae</name>
<nationality />
<description>Pratar en ruskig dialekt</description>
</driver>
<driver type="F1">
<name>David Coulthard</name>
<nationality>Scottish</nationality>
</driver>
</racers>
Öppna XML filen Öppna XML konverterad till HTML (Även NS)
XSL filen
xml24_2.xsl
<?xml version='1.0' encoding="iso-8859-1" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<html>
<head>
<title>Racing</title>
<style type="text/css">
h4 {font-family:verdana,arial,sans-serif; color:#666666;}
</style>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h4>Förare</h4>
<table cellspacing="0" cellpadding="1" bgcolor="#0000FF"><tr><td>
<table cellspacing="0" bgcolor="#FFFFFF">
<tr bgcolor="#EEEEEE">
<td>Namn</td>
<td> Nationalitet</td>
<td>Kommentarer</td>
</tr>
<!-- loopa genom alla förare. Sortera efter namn -->
<xsl:for-each select="racers/driver" order-by="name">
<tr>
<!-- kör apply-templates -->
<xsl:apply-templates />
</tr>
</xsl:for-each>
</table>
</td></tr></table>
</body>
</html>
</xsl:template>
<!-- template som används för name taggarna -->
<xsl:template match="name">
<td valign="top">
<xsl:if test=".[.='Marcus Grönholm']">
<!-- sätt bgcolor för Bosses tabellcell -->
<xsl:attribute name="bgcolor">#FFFFcc</xsl:attribute>
</xsl:if>
<xsl:value-of select="."/></td>
</xsl:template>
<!-- template som används för nationality taggarna -->
<xsl:template match="nationality">
<td valign="top"><xsl:value-of select="."/></td>
</xsl:template>
<!-- template som används för description taggarna -->
<xsl:template match="description">
<td valign="top"><i><xsl:value-of select="."/></i></td>
</xsl:template>
</xsl:stylesheet>
Om du har IE 5.0 eller nyare kan du klicka här för att se filen i praktiken
Detta fungerar så att man kör apply-templates "i blindo".
XSL kommer då att titta på vilken tagg (nod) som gäller för
tillfället. Om noden är <name> kör tolken den template
som finns för name. Om noden är <nationality> körs en annan
template.
Vid första anblicken verkar detta inte så impunerande men tänk
igenom hur det skulle se ut i ett "vanligt" programmeringsspråk.
Något i den här stilen skulle behövas:
If typeOf node is name Then
doName
elseIf TypeOf node is description then
doDescription
Else
doNationality
End If
Programlogiken i XSL är snarare:
Här har du någonting. Se efter om det finns någonting att
göra av det, tack.
Man kan även specificera vilken template som skall matchas genom att sätta
select="pattern" i apply-templates satsen.
Mer avancerat exempel på apply-templates
Nedan har jag ett exempel. För att göra livet lite mer spännande
har jag använt en rekursiv XML fil som då även kräver en
rekursiv XSL.
xml24_1.xml
<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet type="text/xsl" href="xml24_1.xsl"?>
<!DOCTYPE xmlcourse [
<!ELEMENT xmlcourse ( chapter* )>
<!ELEMENT chapter ( title* , chapter* )>
<!ELEMENT title ( #PCDATA )>
]>
<!-- observera det rekursiva datat -->
<!--
en begränsning som jag satt in för att göra
det lättare är att title alltid måste komma före chapter
-->
<xmlcourse>
<chapter>
<title>1. Grunderna</title>
<chapter>
<title>1.1. Intro till XML</title>
<chapter>
<title>1.1.1. Filens konstruktion</title>
<title>1.1.2. Validering av filen</title>
<chapter>
<title>1.1.2.1. Well-formed</title>
<title>1.1.2.2. DTD</title>
</chapter>
</chapter>
</chapter>
<chapter>
<title>1.2. XSL</title>
<title>1.3. Xpath</title>
<title>1.4. XTransformations</title>
<title>1.5. Xrated</title>
</chapter>
</chapter>
<chapter>
<title>2.DOM</title>
<chapter>
<title>2.1. DOM Benedictini</title>
<title>2.2. DOM de Louise</title>
<title>2.3. DOM andra</title>
<title>2.4. DOM Dummaste</title>
</chapter>
</chapter>
</xmlcourse>
Öppna XML filen Öppna XML konverterad till HTML (Även NS)
xml24_1.xsl
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<!-- vi skapar en template för rotnoden -->
<xsl:template match="/">
<!-- helt ordinär html kod -->
<html>
<head>
<title>TEST</title>
</head>
<body>
<!-- loopa genom huvudkapitlen -->
<xsl:for-each select="xmlcourse/chapter">
<!-- sätt in dem i en unordered (ul) html lista -->
<ul>
<!-- sätt in en rad med title -->
<li><xsl:value-of select="title" /></li>
<!-- se om det finns nån lämplig template -->
<xsl:apply-templates />
</ul>
</xsl:for-each>
</body>
</html>
</xsl:template>
<!-- denna template används för chapter noder -->
<xsl:template match="chapter">
<!-- sätt in en ny ul -->
<ul>
<!-- loopa sen genom alla titlar -->
<xsl:for-each select="title">
<li><xsl:value-of select="." /></li>
</xsl:for-each>
<!-- och åberopa templaten på nytt för chapters -->
<xsl:apply-templates />
</ul>
</xsl:template>
</xsl:stylesheet>
Om du har IE 5.0 eller nyare kan du klicka här för att se filen i praktiken