Formatting Objects (FO) / Arbeiten mit XSL 3.0 und FOP

Arbeiten mit XSL 3.0 und FOP

Arbeiten mit XSL 3.0 und FOP

➪ Die Standard-Verarbeitung von XSL-FO mit Apaches FO-Framework arbeitet auf der Basis von XSL 1.1. Freilich sind hier zahlreiche Features nicht verfügbar, die erst unter XSLT 2.0 bzw. XSLT 3.0 bereitstehen. Das heißt aber keineswegs, dass Sie nun auf die enorme Leistungsfähigkeit von XSL 2.0 / XSL 3.0 verzichten müssten, im Gegenteil.

Da XSL-FO eine Konvertierungsstrecke startet, die von einem XML-Input Dokument via XSL in ein temporäres FO-Dokument führt, das wieder als Input für den FO-Prozessor in diverse Endformate dient, kann zur Verwendung der ersten Teilstrecke durchaus XSL 2.0 bzw. XSL 3.0 verwendet werden. Entscheidend ist, einen XSL-Prozessor zu verwenden, der diese Transformation bewältigen kann.

pic/FO5.jpg

Im folgenden Beispiel geht es darum, die Inhalte eines XML-Inputs nach bestimmten Kriterien zu gruppieren und für jeden gruppierten Wert eine eigene PDF-Seite (fo:page-sequence) zu generieren; diese Seite soll ausgewählte Einzelinformationen darstellen, die sich hinter den gruppierten Werten verbergen.

Zur besseren Übersicht verzichten ich auf die Deklaration der Regions fo:region-before, fo:region-after, fo:region-start, fo:region-end.


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:decimal-format 
      name="euro" 
      decimal-separator=","
      grouping-separator="." />
 <xsl:template match="/">
  <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
   <!--
   <fo:layout-master-set>
     wie vorher
   </fo:layout-master-set>
   -->
   <xsl:for-each-group 
        select="//Ort/Mensch/Kauf" 
        group-by="concat(bez, ' ', ../../name)">

Hier beginnt die Generierung der Einzelseiten auf der Basis der (nach dem Schlüssel concat(bez, ' ', ../../name)") gruppierten Einzelwerte. Mit den Anweisungen


<xsl:for-each-group 
     select="//Ort/Mensch/Kauf" 
     group-by="concat(bez, ' ', ../../name)">
   <fo:page-sequence master-reference="layout1">

generiert das XSL für jeden der folgenden Schlüsselkombinationen jeweils eine eigene fo:page-sequence, mithin eine eigene Seite in demselben PDF-Dokument: Es findet also ein Seitenumbruch statt.


    <fo:page-sequence 
        master-reference="layout1">
     <fo:flow 
         flow-name="xsl-region-body">
      <fo:block space-after="2cm" text-align="center">
       <xsl:value-of select="current-grouping-key()"/>
      </fo:block>
      <fo:table table-layout="fixed" width="100%">
       <fo:table-body>
        <xsl:for-each-group 
             select="current-group()" 
             group-by="concat(../vorname, ' ', ../name)">
         <xsl:sort 
              select="sum(current-group()/anzahl)" 
              data-type="number" 
              order="descending"/>

Mit <xsl:for-each-group select="current-group()" wird die aktuelle Gruppierung weiter nach den Elementen vorname und name des jeweiligen Kunden zusammengefasst, aufsteigend sortiert nach der Anzahl der Einkäufe. Im Folgenden wird die Ausgabe nummeriert, formatiert, und jede zweite Zeile bekommt eine andere Hintergrundfarbe.


         <fo:table-row>
          <xsl:if test="position() mod 2 = 0">
           <xsl:attribute name="background-color"
            >lightgrey</xsl:attribute>
          </xsl:if>
          <fo:table-cell>
           <fo:block>
            <xsl:number value="position()" format="I"/>
           </fo:block>
          </fo:table-cell>
          <fo:table-cell>
           <fo:block>
            <xsl:value-of select="../vorname"/>
           </fo:block>
          </fo:table-cell>
          <fo:table-cell>
           <fo:block>
            <xsl:value-of select="../name"/>
           </fo:block>
          </fo:table-cell>
          <fo:table-cell>
           <fo:block>
            <xsl:value-of select="anzahl"/>
           </fo:block>
          </fo:table-cell>
          <fo:table-cell>
           <fo:block text-align="right">
            <xsl:value-of
             select="
              format-number(../Gehalt,
              '#.###,00 &#8364;', 'euro')"/>
           </fo:block>
          </fo:table-cell>
         </fo:table-row>
        </xsl:for-each-group>
       </fo:table-body>
      </fo:table>
     </fo:flow>
    </fo:page-sequence>
   </xsl:for-each-group>
  </fo:root>
 </xsl:template>

Das Ergebnis (für eine der erzeugten Seiten im PDF-Dokument) shen Sie hier:

pic/FO_foreachgroup1.png

wg / 13. April 2018



Fragen? Anmerkungen? Tipps?

Bitte nehmen Sie Kontakt zu mir auf.






Vielen Dank für Ihr Interesse an meiner Arbeit.


V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn

☎ 0151. 750 360 61 * eMail: info10@wilfried-grupe.de

www.wilfried-grupe.de/FO1_3.html