Transcript Document

XSLT 2
Elektronisk publicering
[email protected]
XSLT 2
• Repetition
• Genomgång av övningsuppgifter
• Importering av XML- och XSL-filer i ett
(X)HTML-dokument
• Variabler
• Parametrar
• Number
• Funktioner
• Dynamik
XSL-språk
• XSLT
– Ett språk för att transformera XMLdokument
• X-PATH
– Ett språk för att navigera i XML-dokument
• XSL-FO
– Ett språk för att formatera XML-dokument
Vad är XSLT?
• Står för eXtensible Stylesheet Language
for Transformation
• Ett programmeringsspråk för att
transformera XML-dokument
• En W3C-standard
• XSLT transforms an XML sourcetree into an XML result-tree
Den röda tråden…
DATA
LOGIK
GRÄNSSNITT
XML
XSLT
XHTML(+CSS)
XML, XSLT, XHTML och CSS
XML
XSLT
CSS
Omvandling
XHTML
Hur fungerar XSLT?
<?xml version="1.0" encoding="iso8859-1"?>
<!DOCTYPE boksamling SYSTEM
"boksamling.dtd">
<?xml-stylesheet type="text/xsl"
href="boksamling.xsl"?>
<boksamling>
<bok/>
</boksamling>
En post i XML-filen
<bok>
<forfattare>
<fNamn>Sue</fNamn>
<eNamn>Grafton</eNamn>
</forfattare>
<titel>L som i laglös</titel>
<kategori>Deckare</kategori>
<pris valuta="gbp">20</pris>
</bok>
XSLT-kod
<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="boksamling"/>
</xsl:template>
<xsl:template match="boksamling">
<xsl:apply-templates select="bok"/>
</xsl:template>
<xsl:template match="bok">
Författare: <xsl:value-of select="forfattare/fNamn"/>
<xsl:text> </xsl:text>
<xsl:value-of select="forfattare/eNamn"/><br />
Titel: <xsl:value-of select="titel"/><br />
Kategori: <xsl:value-of select="kategori"/><hr />
</xsl:template>
</xsl:stylesheet>
XPath
• Ett språk för att navigera i XMLdokument
• En syntax för att definiera delar av ett
XML-dokument
• En W3C-standard
• XSLT använder XPath för att navigera i
XML-dokument
XPath - noder
<?xml version="1.0" encoding="iso-8859-1"?>
<boksamling>
Dokumentnod
<bok>
(rotelement)
<forfattare>
<fNamn>Sue</fNamn>
Elementnod
<eNamn>Grafton</eNamn>
</forfattare>
<titel>L som i laglös</titel>
<kategori>Deckare</kategori>
<pris valuta="gbp">20</pris>
</bok>
</boksamling>
Attributnod
Textnod
Exempel: XPath i ett templateanrop
<xsl:template match="boksamling">
<xsl:apply-templates
select="bok/forfattare/eNamn"/>
</xsl:template>
• Gör att vi är säkra på att rätt eNamn hämtas,
dvs det som är barn till forfattare som i sin
tur är barn till bok
En annan variant
<xsl:template match="boksamling">
<xsl:apply-templates
select="bok//eNamn"/>
</xsl:template>
• Gör att vi är säkra på att rätt eNamn
hämtas, dvs det som är ättling till bok
En tredje variant
<xsl:template match="boksamling">
<xsl:apply-templates
select="//forfattare/eNamn"/>
</xsl:template>
• Gör att vi är säkra på att rätt eNamn
hämtas, dvs det som är barn till
forfattare
En fjärde variant
<xsl:template match="boksamling">
<xsl:apply-templates
select="//eNamn"/>
</xsl:template>
• Fungerar om eNamn finns på endast en nivå
i trädet
• Skulle eNamn finnas på flera nivåer
förväxlar tolken noderna med varandra
• I receptexemplet tidigare har vi ju noden
namn på flera nivåer
Notera skillnaden:
<xsl:template match="receptsamling">
<xsl:apply-templates select="//namn"/>
</xsl:template>
<xsl:template match="receptsamling">
<xsl:apply-templates select="//recept/namn"/>
</xsl:template>
<xsl:template match="receptsamling">
<xsl:apply-templates
select="//ingrediens/namn"/>
</xsl:template>
Exempel
Exempel: anropat template
<xsl:template match="eNamn">
<xsl:value-of select="."/>
<xsl:value-of select="../fNamn"/>
<xsl:value-of select="../../titel"/>
<xsl:value-of select="../../kategori"/>
</xsl:template>
Pekar ut
aktuell nod
(eNamn)
Pekar ut eNamns
förälders (forfattare)
barn (fNamn)
(enkelt uttryckt:
eNamns syskon)
Pekar ut eNamns
förfäders barn
Operatorer
•
•
•
•
•
•
•
A=A
(A är ekvivalent med A)
A!=B
(A är inte ekvivalent med B)
A>B
(A är större än B)
A<C
(A är mindre än C)
A>=D (A är större än eller lika med D)
A<=E
(A är mindre än eller lika med E)
Ett uttryck av detta slaget är antingen sant
(true) eller falskt (false)
Operatorer
• A=A and B!=C
– Sant om och endast om A är ekvivalent med A och
B inte är ekvivalent med C
• A=A or B=C
– Sant om A är ekvivalent med A eller om B är
ekvivalent med C
– Om första påståendet är sant kollas inte fler
påståenden
• not (A=B)
– Sant om och endast om A inte är ekvivalent med B
Aritmetiska operatorer
•
•
•
•
•
+
*
div
mod
addition
subtraktion
multiplikation
division
modulus
5+2
7-2
8*3
6 div 3
9 mod 2
Rendering av XML-innehåll
•
•
•
•
Kopiera element
Utesluta element
Flytta element
bland annat…
En receptsamling
<!ELEMENT receptsamling (recept*)>
<!ELEMENT recept (namn, ingrediens+)>
<!ATTLIST recept id CDATA "">
<!ELEMENT namn (#PCDATA)>
<!ELEMENT ingrediens (namn, kategori, mangd)>
<!ELEMENT namn (#PCDATA)>
<!ELEMENT kategori (#PCDATA)>
<!ELEMENT mangd (#PCDATA)>
<!ATTLIST mangd enhet CDATA "st">
XML-filen
Kopiera element
• Navigationssystem
• Till exempel kan alla namn-element
som är barn till recept kopieras och
placeras i en lista i början av texten
• Listans element kan sedan länkas till
respektive namn-element
• För kopiering kan for-each användas
med fördel
Exempel: kopiera element
<xsl:template match="receptsamling">
<div>
<ul id="index">
<xsl:for-each select="//recept/namn">
<li>
<a href="#{../@id}">
<xsl:value-of select="."/>
</a>
</li>
</xsl:for-each>
</ul>
<xsl:apply-templates/>
</div>
</xsl:template>
Matchande template
<xsl:template match="recept">
<h1 id="{@id}">
<a href="#">
<xsl:apply-templates
select="namn"/>
</a>
</h1>
</xsl:template>
• Länkar varje namn-element tillbaka till
index
Exempel
Utesluta element
• Vi kanske inte vill visa all info om ett
recept?
• Eller vi kanske inte vill visa alla recept?
• Om vi utesluter ett element utesluter vi
också dess barn och ättlingar
• Vi skulle t ex kunna utesluta ett element
vars id är lika med carb
Utesluta element, exempel
<xsl:template match="X-PATH-uttryck"/>
<xsl:template match="ingrediens"/>
<xsl:template
match="ingrediens[kategori='Grönsak'"]/>
<xsl:template match="recept[@id='carb']"/>
Utesluta element, exempel
<ingrediens>
<namn>Vitlök</namn>
<kategori>Grönsak</kategori>
<mangd enhet="st">1-2
klyftor</mangd>
</ingrediens>
Exempel
Flytta element
• Template-anrop utförs i den ordning de
är skrivna i:
<xsl:apply-templates
select="mangd[@enhet]"/>
<xsl:apply-templates select="mangd"/>
<xsl:apply-templates select="kategori"/>
• Här kommer attributet enhet skrivas ut
först, sedan mangd och sist namn, t ex:
400 gram köttfärs
Sammanfattning: XSLT:s
notation
• Alla element i XSLT innehåller prefixet
xsl:
<xsl:choose>
</xsl:choose>
<xsl:sort select="name"/>
<xsl:value-of select="name"/>
Operatorer i XSLT skiljer sig
något från X-PATH
•
•
•
•
•
•
A=A
A!=B
8 &gt; 6
6 &lt; 8
A &gt;= B
B &lt;= A
A är ekvivalent med A
A är inte ekvivalent med B
8 är större än 6
6 är mindre än 8
A är större än eller lika med B
B är mindre än eller lika med A
Operatorer i XSLT
• AND, OR och AND…!
– pris &lt; 10 and kategori = 'Deckare’
– pris &lt; 10 or kategori = 'Deckare’
– pris &lt; 10 and kategori != 'Deckare’
Templates?
• Innehåller regler som appliceras vid
matchning av en specificerad nod
• Syntax:
<xsl:template name=”namn" match=”mönster"
mode=”form" priority=”siffra">
…
</xsl:template>
• Samtliga attribut är valfria, men minst ett av
attributen name och match måste återfinnas
Exempel, templates
<xsl:template match="boksamling">
<xsl:apply-templates
select="bok/forfattare/eNamn"/>
</xsl:template>
<xsl:template match="eNamn">
<xsl:value-of select="."/>
<xsl:value-of select="../fNamn"/>
<xsl:value-of select="../../titel"/>
<xsl:value-of select="../../kategori"/>
</xsl:template>
Exempel, templates med villkor
<xsl:template match="boksamling">
<xsl:apply-templates
select="bok/forfattare[eNamn='Grafton']"/>
</xsl:template>
<xsl:template match="forfattare">
<xsl:value-of select="eNamn"/>
<xsl:value-of select="fNamn"/>
<xsl:value-of select="../titel"/>
<xsl:value-of select="../kategori"/>
</xsl:template>
Repetitioner i XSLT: for-each
<xsl:for-each select=“X-PATH-uttryck”>
…kod som utförs på varje nod som
överensstämmer med X-PATHuttrycket
</xsl:for-each>
Exempel: for-each
<xsl:template match="/">
<xsl:for-each select="boksamling/bok">
<xsl:value-of
select="forfattare/eNamn"/>
<xsl:value-of
select="forfattare/fNamn"/>
<xsl:value-of select="titel"/>
<xsl:value-of select="kategori"/>
</xsl:for-each>
</xsl:template>
Exempel: for-each med villkor
<xsl:template match="/">
<xsl:for-each select
="boksamling/bok/forfattare[eNamn
='Grafton']">
<xsl:value-of select="eNamn"/>
<xsl:value-of select="fNamn"/>
<xsl:value-of select="../titel"/>
<xsl:value-of select="../kategori"/>
</xsl:for-each>
</xsl:template>
Styrstrukturer i XSLT
om (villkor a) utför a
annars om (villkor b) utför b
annars utför c
Med if
<xsl:if test=”villkor a">
…kod som utförs om villkor a är sant
</xsl:if>
<xsl:if test=”villkor b">
…kod som utförs om villkor b är sant
</xsl:if>
<xsl:if test=”villkor c">
…kod som utförs om villkor c är sant
</xsl:if>
Exempel: if
<xsl:if test="pris &lt; 10 and
kategori != 'Deckare'">
<xsl:value-of
select="forfattare/eNamn"/>:&#32;
<xsl:value-of select="titel"/>
</xsl:if>
Med choose
<xsl:choose>
<xsl:when test=”villkor a">
...kod som utförs om villkor a är sant
</xsl:when>
<xsl:when test=”villkor b">
...kod som utförs om villkor b är sant
</xsl:when>
<xsl:otherwise>
…kod som utförs om varken villkor a eller b är sant
</xsl:otherwise>
</xsl:choose>
Exempel: choose
<xsl:choose>
<xsl:when test="kategori='Deckare'">
<xsl:value-of select="titel"/>,&#32;
är en deckare
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="titel"/>,&#32;
är inte en deckare
</xsl:otherwise>
</xsl:choose>
Transformera XML-filen
<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml">
<xsl:output method="xml" indent="yes" doctype-public="//W3C//DTD XHTML 1.0 Strict//EN" doctypesystem="http://www.w3.org/TR/xhtml1/DTD/xhtml1strict.dtd" />
<xsl:template match="/">
<html>
<head>
<title>Receptsamling</title>
</head>
<body>
<xsl:apply-templates select="receptsamling"/>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Ett första steg…
</xsl:template>
<xsl:template
match="receptsamling">
<xsl:apply-templates
select="recept"/>
</xsl:template>
</xsl:stylesheet>
Kunde se bättre ut…
• Vi behöver fler templates!
<xsl:template match="recept">
<h2><xsl:value-of select="namn"/></h2>
<xsl:apply-templates select="ingrediens"/>
</xsl:template>
Liten förbättring…
• …men bra nog är det minsann inte!
• Fler templates!
<xsl:template match="ingrediens">
<xsl:value-of select="namn"/>&#32;
(<xsl:value-of select="kategori"/>)<br />
<xsl:value-of select="mangd"/>&#32;
<xsl:value-of select="mangd/@enhet"/><br />
</xsl:template>
Templates, templates,
templates…
• Finns det någon logik?
• Kan vi inte helt enkelt nöja oss med att
skriva ett antal value-of select-satser i
det obligatoriska templatet?
• Nej
• Vi måste ta oss ner på en nivå där
syskon inte finns
Nu då?
<xsl:template match="/">
<xsl:apply-templates select="receptsamling"/>
</xsl:template>
<xsl:template match="recept">
<h2 class="rubrik"><xsl:value-of
select="namn"/></h2>
<xsl:value-of select="ingrediens/namn"/>&#32;
(<xsl:value-of
select="ingrediens/kategori"/>)<br />
<xsl:value-of select="ingrediens/mangd"/>&#32;
<xsl:value-of
select="ingrediens/mangd/@enhet"/><br />
</xsl:template>
Exempel
Varför?
• template match matchar varje receptnod
en gång
• För varje gång en receptnod matchas
genomförs här fem value-of select satser
• Dessa satser genomförs noll eller en gång,
inte en gång för varje ingrediensnod
• Alltså skrivs bara första ingrediensen ut
Förra veckans övningar
• Klicka här…