Eine abgeschlossene HTML-Transformation erstellen

(Auszug aus "XSLT Kochbuch" von Sal Mangano)

Problem

Sie möchten XML-Daten gemeinsam mit einem Stylesheet für deren Umwandlung nach HTML in einer einzigen Datei zusammenfassen.

Lösung

Dieses Rezept setzt voraus, dass Sie über einen Browser verfügen, der clientseitige XSLT-Transformationen unterstützt (IE 6.0 oder höher, auch IE 5.x + MSXML 3.0, Netscape Navigator 6.1 oder höher, Mozilla, Firefox 1.0 oder höher, Apple Macintosh Safari (Tiger) usw.):

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="application/xml" href="selfcontained.xsl"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:pf="http://www.ora.com/XSLTCookbook/namespaces/portfolio">
  <portfolio xmlns="http://www.ora.com/XSLTCookbook/namespaces/portfolio">
    <investment>
      <symbol>IBM</symbol>
      <current>72.70</current>
      <paid>65.00</paid>
      <qty>1000</qty>
    </investment>
    <investment>
      <symbol>JMAR</symbol>
      <current>1.90</current>
      <paid>5.10</paid>
      <qty>5000</qty>
    </investment>
    <investment>
      <symbol>DELL</symbol>
      <current>24.50</current>
      <paid>18.00</paid>
      <qty>100000</qty>
    </investment>
    <investment>
      <symbol>P</symbol>
      <current>57.33</current>
      <paid>63</paid>
      <qty>100</qty>
    </investment>
  </portfolio>
  <xsl:output method="html" />
  <xsl:attribute-set name="gain-loss-font">
    <xsl:attribute name="color">
      <xsl:choose>
        <xsl:when test="(pf:current - pf:paid) * pf:qty &gt;= 0">black</xsl:when>
        <xsl:otherwise>red</xsl:otherwise>
      </xsl:choose>
    </xsl:attribute>
  </xsl:attribute-set>
  <xsl:template match="xsl:stylesheet">
    <xsl:apply-templates select="pf:portfolio"/>
  </xsl:template>
  <xsl:template match="pf:portfolio">
    <html>
      <head>
        <title>My Portfolio</title>
      </head>
      <body bgcolor="#FFFFFF" text="#000000">
        <h1>Portfolio</h1>
        <table border="1" cellpadding="2">
          <tbody>
            <tr>
              <th>Symbol</th>
              <th>Current</th>
              <th>Paid</th>
              <th>Qty</th>
              <th>Gain/Loss</th>
            </tr>
            <xsl:apply-templates/>
          </tbody>
        </table>
      </body>
    </html>
  </xsl:template>
  <xsl:template match="pf:investment">
    <tr>
      <td><xsl:value-of select="pf:symbol"/></td>
      <td><xsl:value-of select="pf:current"/></td>
      <td><xsl:value-of select="pf:paid"/></td>
      <td><xsl:value-of select="pf:qty"/></td>
      <td>
        <font xsl:use-attribute-sets="gain-loss-font">
          <xsl:value-of select="format-number((pf:current - pf:paid) * pf:qty, '#,##0.00')"/>
        </font>
      </td>
    </tr>
  </xsl:template>
</xsl:stylesheet>

Zwei Komponenten in diesem Stylesheet sorgen dafür, dass es funktioniert.

Die erste ist die Verarbeitungsanweisung xml-stylesheet, die den Browser darüber aufklärt, dass das Stylesheet identisch mit dem von ihm geladenen Dokument ist. Sie können das Dokument als sein eigenes Stylesheet referenzieren, indem Sie href="" verwenden, anstatt den Dateinamen anzugeben, was dann sehr hilfreich ist, wenn Sie es einmal umbenennen sollten.

Die zweite ist das Template, das mit dem xsl:stylesheet-Element übereinstimmt und die Stylesheet-Verarbeitung an die eingebetteten XML-Daten umleitet. In diesem Fall befinden sich die Elemente im Namensraum "http://www.ora.com/XSLTCookbook/namespaces/portfolio".

Diskussion

Dieses Rezept ist so etwas wie ein Trick, um Ihre Freunde zu beeindrucken. Die Vermengung von Inhalt und Stil verletzt in mancherlei Hinsicht die Idee hinter dieser Technologie. Auf der anderen Seite kann es sehr bequem sein, eine einzige Datei zu produzieren. Sie sollten daher keine Schuldgefühle haben, wenn Sie dieses Rezept benutzen, sofern Ihre Bedürfnisse es erfordern.

Die offizielle Art, diese Resultate zu erzielen, besteht darin, das Stylesheet in das Dokument einzubetten und nicht umgekehrt. Weitere Details finden Sie unter Embedding Stylesheets in der XSLT 1.0-Spezifikation oder unter Embedded Stylesheet Modules in der XSLT 2.0-Spezifikation. Trotzdem unterstützt IE eingebettete Stylesheets noch nicht, und insofern löst dieser Trick zumindest dieses Problem.

Sie können Inhalte in dieser Form übermitteln, ohne sie notwendigerweise direkt in dieser Form zu entwickeln. Das folgende Stylesheet verbindet ein Stylesheet mit einer XML-Datei zum abgeschlossenen Format. Die einzigen erforderlichen Voraussetzungen hierfür sind, dass das XML in einem Namensraum sein muss, und das Stylesheet mit der Verarbeitung nicht beim Wurzelknoten (/) beginnen sollte:

<!-- generate-selfcontained.xslt -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xso="dummy">
  <!-- Wiederverwendung der Identitätstransformation -->
  <xsl:import href="../util/copy.xslt"/>
  <!-- Dieses Stylesheet wird den Stylesheet-Inhalt generieren, verwende daher xso als Alias für xsl -->
  <xsl:namespace-alias stylesheet-prefix="xso" result-prefix="xsl"/>
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:strip-space elements="*"/>
  <!-- Es ist keine gute Idee, Leerraum aus Textknoten zu entfernen -->
  <xsl:preserve-space elements="xsl:text"/>
  <!-- Der Name der Datei, die die XML-Daten enthält -->
  <xsl:param name="datafile"/>
  <!-- Der Name der resultierenden Ausgabedatei -->
  <xsl:param name="outfile"/>
  <xsl:template match="/">
    <!-- Füge die Verarbeitungsanweisung ein, um dem Browser zu sagen, dass $outfile das Stylesheet ist. -->
    <xsl:processing-instruction name="xml-stylesheet">
      <xsl:text>type="application/xml" href="</xsl:text><xsl:value-of select="$outfile"/>"<xsl:text/>
    </xsl:processing-instruction>
    <xsl:apply-templates/>
  </xsl:template>
  <xsl:template match="xsl:stylesheet">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
      <!-- Erzeuge das XSLT -->
      <xso:template match="xsl:stylesheet">
        <xso:apply-templates select="{name(document($datafile)/*)}"/>
      </xso:template>
      <!-- Füge die Daten ein -->
      <xsl:copy-of select="document($datafile)"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Dieses Stylesheet können Sie dazu verwenden, ein anderes Stylesheet und seine Daten in eine eigenständige HTML-Transformation zu transformieren. Dabei ist das Stylesheet die Quelle und $datafile wird als Parameter übergeben. Einen weiteren Parameter, $outfile, benötigen Sie, um die xml-stylesheet-Verarbeitungsanweisung korrekt generieren zu können.

Unter Verwendung von Saxon auf der Kommandozeile könnte ein solcher Aufruf wie folgt aussehen:

saxon -o self-contained.xsl pf-portfolio.xslt generate-selfcontained.xslt
          datafile="pf-portfolio.xml" outfile="self-contained.xsl"

Dabei ist self-contained.xsl der Name des resultierenden Stylesheets und pf-portfolio.xslt ist das Stylesheet, das mit pf-portfolio.xml vereint wird.

  

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema XSLT bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

Copyright © 2006 O'Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "XSLT Kochbuch" denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

O'Reilly Verlag GmbH & Co. KG, Balthasarstraße 81, 50670 Köln, kommentar(at)oreilly.de