Home
Über mich
Blog
Veröffentlichungen
IT-Trainings
Impressum


Arbeiten mit XSL 2.0 und FOP

Die Standard-Verarbeitung von XSL-FO mit Apache's 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 bereit stehen. Das heißt aber keineswegs, daß wir nun auf die enorme Leistungsfähigkeit von XSL 2.0 / XSL 3.0 verzichten müßten, im Gegenteil. Da XSL-FO eine Konvertierungsstrecke startet, die von einem XML Input Dokument via XSL in ein temporäres FO-Dokument führt, welches letztere 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 wir 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>
    <fo:simple-page-master 
        margin-right="15mm"
        margin-left="2cm" 
        margin-bottom="1cm" 
        margin-top="2cm" 
        page-width="21cm"
        page-height="297mm" 
        master-name="layout1">
     <fo:region-body 
         margin-right="5cm" 
         margin-bottom="15mm"
         margin-top="35mm" 
         margin-left="10mm" 
         background-color="white" />
    </fo:simple-page-master>
   </fo:layout-master-set>

Nun beginnt die Generierung der Einzelseiten auf der Basis der (nach einem gruppierten Schlüssel "concat(bez, ' ', ../../name)") gruppierten Einzelwerte. Mit der Anweisung

<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, also eine eigene PDF-Seite.

   <xsl:for-each-group select="//Ort/Mensch/Kauf"
        group-by="concat(bez, ' ', ../../name)">
    <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>

Mit <xsl:for-each select="current-group()"> wird die aktuelle Gruppierung weiter ausgewertet: sie wird sortiert, numeriert, formatiert, es werden Bezüge zum Parentnode "Mensch" (<xsl:value-of select="../vorname" /> etc. ) hergestellt, und jede zweite Zeile bekommt eine andere Hintergrundfarbe.

        <xsl:for-each select="current-group()">
         <xsl:sort 
              select="anzahl" 
              data-type="number" 
              order="ascending" />
         <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>
       </fo:table-body>
      </fo:table>
     </fo:flow>
    </fo:page-sequence>
   </xsl:for-each-group>
  </fo:root>
 </xsl:template>
</xsl:stylesheet>

Beispielhaft führ mehrere andere PDF-Seiten finden wir hier eines ("Schuhe Kapstadt") der generierten Ergebnisse:

pic/foreachgroup_schluessel2_FO.jpg

Aufrufbar ist dieser Prozeß beispielsweise wiederum mit ANT:

  <antcall target="runxsltransformation">
   <param name="poutput" 
          value="${wgpath}/output/XSLFO2.fo" />
   <param name="pinput" 
          value="${wgpath}/input/Ort_Elemente" />   
   <param name="pstyle" 
          value="C:/wg/XSLFO2" />
   <param name="pprocessor" 
          value="saxon9ee" />
  </antcall>
  <antcall target="runSingleFOP">
   <param name="fodatei" 
          value="${wgpath}/output/XSLFO2.fo" />
   <param name="out" 
          value="${wgpath}/output/XSLFO2.pdf" />
  </antcall>

qrpic/FO1_4.jpg

wg / 9. Oktober 2017




Fragen? Anmerkungen? Tips?

Bitte nehmen Sie Kontakt zu mir auf (info10@wilfried-grupe.de).



Vielen Dank für Ihr Interesse an meiner Arbeit.


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

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