590 likes | 741 Views
XSLT 3. Elektronisk publicering. XSLT 3. Repetition Genomgång av övningsuppgifter Importering av XML- och XSL-filer i ett (X)HTML-dokument Variabler Parametrar Number Funktioner Dynamik. Operatorer. A=A (A är ekvivalent med A) A!=B (A är inte ekvivalent med B)
E N D
XSLT 3 Elektronisk publicering david.gunnarsson@hb.se
XSLT 3 • Repetition • Genomgång av övningsuppgifter • Importering av XML- och XSL-filer i ett (X)HTML-dokument • Variabler • Parametrar • Number • Funktioner • Dynamik
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 • + addition 5+2 • - subtraktion 7-2 • * multiplikation 8*3 • div division 6 div 3 • mod modulus 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
Sortering i for-each <xsl:template match="receptsamling"> <div> <ul id="index"> <xsl:for-each select="//recept/namn"> <xsl:sort select="."/> <li> <a href="#{../@id}"> <xsl:value-of select="."/> </a> </li> </xsl:for-each> </ul> <xsl:apply-templates/> </div> </xsl:template>
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 är ekvivalent med A • A!=B A är inte ekvivalent med B • 8 > 6 8 är större än 6 • 6 < 8 6 är mindre än 8 • A >= B A är större än eller lika med B • B <= A B är mindre än eller lika med A
Operatorer i XSLT • AND, OR och AND…! • pris < 10 and kategori = 'Deckare’ • pris < 10 or kategori = 'Deckare’ • pris < 10 and kategori != 'Deckare’
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"/>  (<xsl:value-of select="ingrediens/kategori"/>)<br /> <xsl:value-of select="ingrediens/mangd"/>  <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 sista övning • Klicka här…
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 < 10 and kategori != 'Deckare'"> <xsl:value-of select="forfattare/eNamn"/>:  <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"/>,  är en deckare </xsl:when> <xsl:otherwise> <xsl:value-of select="titel"/>,  är inte en deckare </xsl:otherwise> </xsl:choose>
Inläsning av XSLT- och XML-dokument i XHTML-dokument • Vi kan med ett (hyfsat) enkelt JavaScript läsa in XSLT- och XML-dokument i XHTML-dokument • Vi utgår från en skapad .htm-fil • Vi skriver sedan ett JavaScript som läser in bägge filerna
bok.htm <body> <script type="text/javascript"> </script> ...lite kod... </body> </html> (följande exempel är omarbetat efter http://msdn2.microsoft.com/en-gb/library/ms763742.aspx)
bok.htm <body> <script type="text/javascript"> </script> ...lite kod... </body> </html> (följande exempel är omarbetat efter http://msdn2.microsoft.com/en-gb/library/ms763742.aspx)
Skapa variabler och tilldela värden <script type="text/javascript"> var xslt = new ActiveXObject("Msxml2.XSLTemplate.3.0"); var xsldoc = new ActiveXObject ("Msxml2.FreeThreadedDOMDocument.3.0"); var xslproc;
Ladda filer xsldoc.async = false; xsldoc.load("bok.xsl"); xslt.stylesheet = xsldoc; var xmldoc = new ActiveXObject("Msxml2.DOMDocument.3.0"); xmldoc.async = false; xmldoc.validateOnParse = false; xmldoc.load("bok.xml"); Lägg in denna rad ifall resultatet uteblir (detta beror sannolikt på att validering gentemot DTD:n misslyckas)
Utför transformation xslproc = xslt.createProcessor(); xslproc.input = xmldoc; xslproc.transform(); document.write(xslproc.output); </script> Resultatet av transformationen skrivs ut här
Variabler • En behållare som innehåller information av något slag • Kan vara av olika datatyper, till exempel sträng, heltal, decimaltal etc • Namnges förslagsvis med ett beskrivande ord
Variabler i XSLT • Syntax: <xsl:variable name="namn"> <!-- innehåll --> </xsl:variable> • Eller: <xsl:variable name="namn" select="uttryck"/> • name=variabelns namn (måste anges) • select=variabelns värde (valfritt)
Variabler, exempel från w3schools <xsl:variable name="color" select="'red'" /> <xsl:variable name="header"> <tr> <th>Element</th> <th>Description</th> </tr> </xsl:variable>
Behandla variabler • Utskrift • <xsl:copy-of select="$header" /> • <xsl:value-of select="$header" /> • Beräkning och utskrift • <xsl:copy-of select="$value*7" /> • <xsl:value-of select="$value*7" /> • En variabels värde kan inte ändras efter att den tilldelats ett värde
Variabler ska deklareras • Global variabel • Deklareras före dokumentets första template <xsl:variable name="sort"/> <xsl:template match="/"> … </xsl:template> • Är åtkomlig överallt • Lokal variabel • Deklareras i aktuellt template <xsl:template match="value"> <xsl:variable name="value" select="."/> … </xsl:template> • Är åtkomlig endast inom templatet
Hopkoppling av olika objekt • Motsvarande join-operation i en relationsdatabas • Två olika objekt kopplas ihop med hjälp av en gemensam nämnare • I en databas: • bok.forfattarid=forfattare.id • I en XML-fil: <bok> <forfattarid>1</forfattarid> <titel>…</titel> </bok> <forfattare> <id>1</id> <namn>…</namn> </forfattare>
Exempel <player> <name> <first>Andres</first> <last>D'Alessandro</last> </name> <clubid>1</clubid> <position>Midfielder</position> <side>Left</side> <side>Centre</side> <value currency="gbp">4</value> </player> … <club> <clubname>Zaragoza</clubname> <id>1</id> <location>Zaragoza</location> <country>Spain</country> </club>
Jämför <player> <name> <first>Andres</first> <last>D'Alessandro</last> </name> <club> <clubname>Zaragoza</clubname> <location>Zaragoza</location> <country>Spain</country> </club> <position>Midfielder</position> <side>Left</side> <side>Centre</side> <value currency="gbp">4</value> </player> …
Matchning med gemensam nämnare <xsl:template match="player"> ... <xsl:apply-templates select="clubid"/> ... </xsl:template> <xsl:template match="clubid"> <xsl:variable name="clubid" select="."/> <xsl:for-each select="//players/club"> <xsl:if test="id=$clubid"> <xsl:value-of select="clubname"/> </xsl:if> </xsl:for-each> </xsl:template>
Parametrar • Ungefär samma som variabler… • …men till skillnad från variabler kan parametrar skickas med ett template • Parametrar kan också ta emot värden som skickas in till xls-filen
Parametrar • Syntax: <xsl:param name="namn"> <!-- innehåll --> </xsl:param> • Eller: <xsl:param name="namn" select="uttryck"/> • name är obligatoriskt… • …men inte select
Parametrar ska också deklareras • Global parameter • Deklareras före dokumentets första template <xsl:param name="sort"/> <xsl:template match="/"> … </xsl:template> • Är åtkomlig överallt • Lokal parameter • Deklareras i aktuellt template <xsl:template match="value"> <xsl:param name="value" select="."/> … </xsl:template> • Är åtkomlig endast inom templatet men kan skickas med till ett annat template
Template-anrop med parametrar <xsl:template match="player"> <xsl:param name="clubid" select="clubid"/> <xsl:apply-templates select="//players/club"> <xsl:with-param name="clubid" select="$clubid"/> </xsl:apply-templates> </xsl:template> <xsl:template match="//players/club"> <xsl:param name="clubid"/> <xsl:if test="id=$clubid"> <xsl:value-of select="clubname"/> </xsl:if> </xsl:template>
Parametrar utanför X-PATH • Parametrar kan även användas i attribut som inte är X-PATH-attribut • Krullparenteser omsluter då parametern: <a href="{$file}">Next page</a>
Number • Används för att bestämma en nods position i XML-dokumentet • Kan också formatera ett nummer • Syntax: <xsl:number count="uttryck" level="single|multiple|any" from="uttryck" value="uttryck" format="formatsträng" lang="språkkod" letter-value="alphabetic|traditional" grouping-separator="tecken" grouping-size="siffra"/> • Samtliga attribut är valfria • Exempel: <xsl:number count="player" format="i. "/>
Lite funktioner… • sum – räknar summan av noder med numeriska värden <xsl:value-of select="sum(value)"/> <xsl:if test="sum(value)>50)"> … </xsl:if> • count – räknar antalet noder <xsl:value-of select="count(player)"/> <xsl:if test="count(player)>10)"> … </xsl:if>
Funktionen position() • Återger ett numeriskt värde på en nods position <xsl:if test="position()!=last()"> <xsl:text>, </xsl:text> </xsl:if> <xsl:choose> <xsl:when test="position() mod 2 = 0"> <span class="rowA">…innehåll…</span> </xsl:when> <xsl:otherwise> <span class="rowB">…innehåll…</span> </xsl:otherwise> </xsl:choose>