english

Mithis kleine XSLT-Bastelei


... oder "Was kann man überhaupt mit diesem XML vom DVD-Profiler anfangen?"

Ein Wort der Warnung vorweg: Ich habe XSL nicht systematisch erlernt sondern mich lediglich an David Smiths XSL (siehe unten) gehalten und dieses sukzessive nach meinen Wünschen verändert. Für absolute Anfänger in Sachen HTML und Programmierung dürften diese Seite also ungeeignet sein.

Aufgabe

Die zum DVD-Profiler gehörige Onlineliste hat den Nachteil das man nicht z.B. nach Genre sortieren kann oder ähnliches. Dafür bietet der Profiler aber die Möglichkeit die Datenbank im XML-Format abzuspeichern und dieses habe ich mir zu Nutze gemacht für eigene DVD-Listen.

Grundlagen

Stark vereinfacht ausgedrückt verhalten sich XML und XSLT ähnlich wie HTML und CSS. Ersteres liefert den Inhalt, letzteres die Form. Um aus XML etwas schönes herauszubekommen muss es geparst werden, das kann an 3 Orten erfolgen:

Durchführung

Einfach
xsltproc.exe ungesehen-collection.xsl collection.xml > ungesehen-collection.html
oder
msxsl.exe collection.xml ungesehen-collection.xsl > ungesehen-collection.html
oder
java -jar saxon9he.jar -novw collection.xml ungesehen-collection.xsl > ungesehen-collection.html
ausführen und fertig. Wie? Das ging zu schnell? Dann versuche ich mal etwas genauer aufzuschlüsseln:

ungesehen-collection.xsl
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- ***************
     Programmed by David Smith 4 Mar 2003
     changed by Michael 'Mithi' Cordes 02.04.2006
     *************** -->
Welche XML-Version benutzen wir, und in welchen Encoding schreiben wir diese XSL.
Und ein paar Kommentare.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:include href="templates/template-genres.xsl"/>
  <xsl:include href="templates/template-regions.xsl"/>
  <xsl:include href="templates/template-credits.xsl"/>
Hier werden die Templates geladen.
<xsl:output method="html"
  encoding="ISO-8859-1"
  doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
  doctype-system="http://www.w3.org/TR/html401/loose.dtd"/>
Hier wird festgelegt das eine HTML-Datei der Version 4.01 erzeugt werden soll.
<xsl:template match="Collection">
So, jetzt geht es los, das erste XSL:Template. Es spricht auf alles innerhalb von <Collection> an, durchsucht also die gesamte XML-Datei.
<html>
  <head>
    <title>Mithis ungesehene DVDs</title>
    <meta name="author" content="Michael Cordes"/>
    <link rel="stylesheet" type="text/css" href="/privat/layout.css"/>
    <link rel="stylesheet" type="text/css" href="/privat/dvd-list.css"/>
    <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"/>
    <link rel="shortcut icon" href="/privat/favicon.ico" type="image/x-icon"/>
  </head>
  <body>
          <h1>Mithis ungesehene DVDs</h1>
    <br/><br/>
    <table class="box" cellpadding="0" align="center">
Der ganz normalen HTML-Code für die Website die ausgegeben werden soll. Einzige Besonderheit: Tags müssen immer geschlossen werden, alleinstehende Tags wie <br> müssen also einen Schrägstrich ans Ende bekommen. Beim ausgegebenen HTML sind sie bei HTML 4.01 weg.
        <xsl:apply-templates select="DVD"> 
        <xsl:sort select="RunningTime" data-type="number"/>
        </xsl:apply-templates>
Hier wird es spannend. Es wird das Template aufgerufen das auf <DVD> anspricht. Die Ergebnisse die von diesem Template hier reingestellt werden, werden sortiert, in diesem Falle nach der Laufzeit.
    </table>
  </body>
</html>
Wieder nur einfachers HTML, die untere Hälfte Seite.
</xsl:template>
Und hier ist auch schon wieder alles vorbei.
<xsl:template match="DVD">
<!-- Ungesehen Owned -->
  <xsl:if test="not(contains(Events, 'Watched')) and contains(CollectionType, 'Owned')">
Und hier werden jetzt alle <DVD>-Einträge durchsucht, ob sie auch in meiner 'Owned'-Liste sind und nicht den Vermerk 'gesehen' tragen.
       <tr>
         <td class="dvdTitle" colspan="2"><xsl:value-of select="Title"/>
           <xsl:if test="count(Description)>0">
             <br/><xsl:value-of select="Description"/>
           </xsl:if>
         </td>
       </tr>
       <tr>
         <td colspan="2">
           <table border="0" width="100%">
             <tr>
Wenn die Bedingungen oben zutreffen werden vom jeweiligen DVD-Datensatz der <Title> genommen und wenn vorhanden auch noch die <Description>
               <td colspan="2" class="dvdData">
               <xsl:apply-templates select="Credits"/></td> 
Das oben importierte Template "Credits" wird aufgerufen.
             </tr>
             <tr>
               <td width="50%" class="dvdData">
               <xsl:value-of select="RunningTime"/><xsl:text> min</xsl:text></td>
               <td class="dvdData"><xsl:apply-templates select="Regions"/></td>
             </tr>
             <tr>
               <td class="dvdData" colspan="2"><xsl:apply-templates select="Genres"/></td>
             </tr>
           </table>
         </td>
       </tr>
Hier wird die RunningTime eingefügt und nochmal dasselbe wie bei den Credits, nur eben für Regions und Genres.
  </xsl:if>
</xsl:template>
</xsl:stylesheet>
Sobald es keine Datensätze mehr gibt auf die die IF-Abfrage zutrifft wird wieder zurückgesprungen.
 
template-credits.xsl
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="Credits">
Es werden alle <Credits> des aktuellen <DVD> durchsucht.
  <xsl:if test="count(Credit[CreditSubtype = 'Director'])>0">
    <xsl:text>Director</xsl:text>
    <xsl:if test="count(Credit[CreditSubtype = 'Director'])>1">
      <xsl:text>s</xsl:text>
    </xsl:if>
    <xsl:text>: </xsl:text>
Hier entscheidet sich ob Director in der Ein- oder der Mehrzahl dastehen soll...
    <xsl:for-each select="Credit[CreditSubtype = 'Director']">
    <xsl:if test="position() <= 3">
      <xsl:value-of select="FirstName"/>
      <xsl:text> </xsl:text>
      <xsl:value-of select="LastName"/>
      <xsl:if test="not (position()=last())">
        <xsl:text>, </xsl:text>
      </xsl:if>
    </xsl:if>
    </xsl:for-each>
    <xsl:if test="count(Credit[CreditSubtype = 'Director'])>3">
    <xsl:text>other</xsl:text>
    </xsl:if>
  </xsl:if>
... und hier werden dann von den ersten 3 Directors Vor- und Nachname hintereinander gehängt. Wenn es mehr als 3 sind kommt noch ein lapidares 'other' dran.
</xsl:template>
</xsl:stylesheet>
Hier ist Schluss und es wird wieder zurückgesprungen.

Veränderung zu David Smiths XSL

Neben den offensichtlichen Unterschieden im Layout der erzeugten HTML-Datei habe ich nur wenige wesentliche Veränderungen vorgenommen:


Links


Last updated: 08. September 2012

zurück zur Hauptseite