XSL-FO: Tabellenumbruch auf nächste Seite
Tobi
- xsl
Hi Leute,
Nach stundenlangem quälen verschiedener Suchmaschinen bin ich nun hier gelandet. Mir scheint dieses Problem hat sonst niemand ausser mir. Vielleicht könnt Ihr mir helfen.
Ich habe folgendes Problem:
Ich möchte mittels XML und XSLT/XSL-FO ein PDF erzeugen. Die Daten stehen in der XML Datei und das Layout kommt aus einem XSL stylesheet. Eigentlich ist das Layout nichts Spektakuläres. Es soll eine große Tabelle (ca. 20 Seiten lang) auf mehrere Seiten verteilt werden. Auf der ersten Seite soll ein etwas größerer Header stehen (mit Firmenname usw). Darunter folgt dann die Tabelle, die auf den Folgeseiten fortgesetzt werden soll. Auf den Folgeseiten soll aber nur ein etwas kleinerer Header angezeigt werden. Ich habe dann 2 simple-page-master Seiten definiert (eine für die erste Seite, die andere für die restlichen).
Zudem habe ich noch ein page-sequence-master definiert:
<fo:page-sequence-master master-name="document">
fo:repeatable-page-master-alternatives
<fo:conditional-page-master-reference page-position="first" master-reference="erste"/>
<fo:conditional-page-master-reference page-position="rest" master-reference="restliche"/>
</fo:repeatable-page-master-alternatives>
</fo:page-sequence-master>
Die Tabelle wird auch dargestellt, allerdings wird für die komplette Tabelle der Header der ersten Seite benutzt. Erst wenn die Tabelle zu Ende ist, folgen fast 300 !Huh leere Seiten mit dem kleinen Header für die Folgeseiten.
Zudem wird der untere Rand der Tabelle (also der Border) erst am Ende der kompletten Tabelle (nach 20 Seiten) dargestellt.
Wäre nett wenn mir jemand bei diesem Problem behilflich sein könnte.
Vielen Dank im Vorraus,
Tobi
Hi, du machst es zur Zeit so:
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
fo:layout-master-set
<fo:simple-page-master master-name="titel">
<fo:region-body margin="3cm" />
</fo:simple-page-master>
<fo:simple-page-master master-name="text">
<fo:region-body margin="2cm" />
</fo:simple-page-master>
<fo:page-sequence-master master-name="buch">
<fo:repeatable-page-master-reference master-reference="text" />
</fo:page-sequence-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="titel">
<!-- Inhalt der Titelseite -->
</fo:page-sequence>
<fo:page-sequence master-reference="buch">
<!-- Inhalt der Kapitel -->
</fo:page-sequence>
</fo:root>
dass ist aber, wenn die erste Seite eine eigenen Titelseite sein soll. Du musst es aber so machen.
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
fo:layout-master-set
<fo:simple-page-master master-name="erste">
<fo:region-body margin="3cm" border-width="2pt" padding="6pt" />
</fo:simple-page-master>
<fo:simple-page-master master-name="rest">
<fo:region-body margin="2.5cm" />
</fo:simple-page-master>
<fo:page-sequence-master master-name="buch">
<fo:single-page-master-reference master-reference="erste" />
<fo:repeatable-page-master-reference master-reference="rest" />
</fo:page-sequence-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="buch">
...
</fo:page-sequence>
</fo:root>
Kannst du nachlesen hier:
http://www2.informatik.hu-berlin.de/~obecker/Lehre/WS2002/FHP-XML/07-xslfo.html
Viele Grüße und Erfolg,
Holger
Vielen, vielen Dank für die schnelle Antwort. Dann kann ich meinem Chef heute doch noch etwas brauchbares präsentieren :)
Werd mich gleich mal ans Werk machen und deine Tips einbauen.
Danke nochmal !
So, ich habe deine Anregungen mal ausprobiert. Nun habe ich immerhin Text auf den restlichen Seiten. Allerdings wird nach wie vor die der Header der ersten Seite für etwa 11 Seiten (komplette Tabelle) benutzt, und danach folgen nochmal soviele Seiten mit dem kleineren Header der restlichen Seiten.
Ich weiss auch in etwa an was das liegt. Da die Tabelle zu groß für eine Seite ist, nimmt er die Vorlage für die erste Seite so lange, bis die Tabelle komplett ist. Danach wird erst die Vorlage für die restlichen Seiten benutzt.
Das Problem ist, dass ich nicht berechnen Kann, wie groß die Tabelle auf der ersten Seite sein wird, um Sie dann auf eine bestimmte Zeilenanzahl zu beschränken. Die Tabelle wird mittels XSLT automatisch aus einer XML Datei ausgelesen.
Gibt es da eventuell noch eine andere Lösung, außer die größe der Tabelle auf der ersten Seite zu berechnen ?
Habe das übrigens auch mal mit normalem Text ausprobiert. Aber da besteht das selbe Problem. Sobald der Text mehr Platz braucht, als auf der ersten Seite vorhanden ist, wird immer wieder die Vorlage der ersten Seite benutzt, bis der Text komplett ist.
Nachfolgend habe ich mal mein Template gepostet. Vielleicht habe ich ja auch nur einen groben Denkfehler gemacht, und seh in nicht :) :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
fo:layout-master-set
<fo:simple-page-master master-name="erste" page-width="210mm" page-height="297mm">
<fo:region-body region-name="xsl-region-body" margin-top="63mm" margin-bottom="1cm"/>
<fo:region-before region-name="bigheader" margin-left="1cm"/>
</fo:simple-page-master>
<fo:simple-page-master master-name="restliche" page-width="210mm" page-height="297mm">
<fo:region-body region-name="xsl-region-body" margin-top="25mm" margin-bottom="1cm"/>
<fo:region-before region-name="smallheader" margin-left="1cm"/>
</fo:simple-page-master>
<fo:page-sequence-master master-name="document">
<fo:single-page-master-reference page-position="first" master-reference="erste"/>
<fo:repeatable-page-master-reference page-position="rest" master-reference="restliche"/>
</fo:page-sequence-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="erste">
<fo:static-content flow-name="bigheader">
<fo:block margin-left="5mm" margin-bottom="5mm" margin-top="10mm" font-size="28pt" font-weight="bold">
<fo:external-graphic src="pix/globe_50.GIF" margin-right="3mm"/><xsl:value-of select="xml/bigpageheader/h1"/>
</fo:block>
<fo:block margin-left="22mm" margin-bottom="3mm" font-size="12pt" font-weight="bold">
<fo:inline color="rgb(0,100,255)"><xsl:value-of select="xml/bigpageheader/sub1"/></fo:inline>
</fo:block>
<fo:block margin-left="22mm" margin-bottom="5mm" font-size="12pt">
<fo:inline color="rgb(0,100,255)"><xsl:value-of select="xml/bigpageheader/sub2"/></fo:inline>
</fo:block>
<fo:block margin-left="22mm" font-size="12pt">
<fo:inline color="rgb(0,100,255)"><xsl:value-of select="xml/bigpageheader/sub3"/></fo:inline>
</fo:block>
<fo:block margin-left="22mm" font-size="12pt">
<fo:inline color="rgb(0,100,255)"><xsl:value-of select="xml/bigpageheader/sub4"/></fo:inline>
</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:table border-style="solid" border-width="1pt">
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt" background-color="grey"/>
<fo:table-column border-style="solid" border-width="1pt" background-color="grey"/>
<fo:table-column border-style="solid" border-width="1pt" background-color="grey"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
fo:table-header
<fo:table-row background-color="black" color="white">
<xsl:for-each select="xml/tableheader/tableheadercol">
<fo:table-cell border-style="solid" border-width="1pt">
<fo:block font-weight="bold"><xsl:value-of select="name"/></fo:block>
</fo:table-cell>
</xsl:for-each>
</fo:table-row>
</fo:table-header>
fo:table-body
<xsl:for-each select="xml/body/bodyrow">
fo:table-row
<xsl:for-each select="bodycol">
fo:table-cell
fo:block<xsl:value-of select="name"/></fo:block>
</fo:table-cell>
</xsl:for-each>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
</fo:flow>
</fo:page-sequence>
<fo:page-sequence master-reference="restliche">
<fo:static-content flow-name="smallheader">
<fo:block margin-left="5mm" margin-top="10mm" font-size="10pt" font-weight="bold">
<fo:external-graphic src="pix/globe_20.gif" margin-right="33mm"/>
<xsl:value-of select="xml/smallpageheader/sub1"/>
</fo:block>
<fo:block margin-left="44mm" margin-bottom="3mm" font-size="10pt">
<xsl:value-of select="xml/smallpageheader/sub2"/> fo:page-number/
</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:table border-style="solid" border-width="1pt">
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
fo:table-header
<fo:table-row background-color="rgb(0,128,255)">
<xsl:for-each select="xml/tableheader/tableheadercol">
<fo:table-cell border-style="solid" border-width="1pt">
<fo:block font-weight="bold"><xsl:value-of select="name"/></fo:block>
</fo:table-cell>
</xsl:for-each>
</fo:table-row>
</fo:table-header>
fo:table-body
<xsl:for-each select="xml/body/bodyrow">
fo:table-row
<xsl:for-each select="bodycol">
fo:table-cell
fo:block<xsl:value-of select="name"/></fo:block>
</fo:table-cell>
</xsl:for-each>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
hm, werde das mal testen aber so beim schnellen überfliegen von deinem code ist mir aufgefallen, dass du nicht document benutzt, siehe nachfolgenden verweis mit <-------- gekennzeichnet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
fo:layout-master-set
<fo:simple-page-master master-name="erste" page-width="210mm" page-height="297mm">
<fo:region-body region-name="xsl-region-body" margin-top="63mm" margin-bottom="1cm"/>
<fo:region-before region-name="bigheader" margin-left="1cm"/>
</fo:simple-page-master>
<fo:simple-page-master master-name="restliche" page-width="210mm" page-height="297mm">
<fo:region-body region-name="xsl-region-body" margin-top="25mm" margin-bottom="1cm"/>
<fo:region-before region-name="smallheader" margin-left="1cm"/>
</fo:simple-page-master>
<fo:page-sequence-master master-name="document">
<fo:single-page-master-reference page-position="first" master-reference="erste"/>
<fo:repeatable-page-master-reference page-position="rest" master-reference="restliche"/>
</fo:page-sequence-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="erste"> <------ muesste da nicht "document" anstatt "erste" stehen
Du hast recht. Mit document anstatt "erste" taucht der header nur noch auf der ersten Seite auf. Mir leuchtet auch ein warum. Allerdings fehlt auf den nachfolgenden Seiten nun noch der kleinere Header. Dieser taucht dann 11 Seiten weiter hinten wieder auf, wenn die komplette Tabelle nochmals dargestellt wird.
Ich kann mir denken wie das funktionieren soll, kann mir aber nicht vorstellen wie ich das umsetzten soll.
Also, der <fo:page-sequence-master master-name="document"> fungiert jetzt als Vorlage für das gesammte Dokument. Hier wird die Seitenfolge festgelegt. Also brauche ich doch für jede Seite (die erste und die restlichen) jeweils eine Vorlage. In diesen Vorlagen sollte eigentlich nur der Header stehen, und die Tabelle sollte ausgegliedert werden, sonst ist klar dass die Tabelle doppelt auftaucht (da ja in jeder Vorlage die Tabelle drinsteht).
Kann ich die Tabelle in document Schreiben und die verschiedenen Header in erste und restliche ausgliedern (und zwar nur die header) ? Und dann in document auf die Header verweisen?
Habe das jetzt mal folgendermassen versucht, aber jetzt tauchen die Header gar nicht mehr auf:
fo:layout-master-set
<fo:simple-page-master master-name="erste" page-width="210mm" page-height="297mm">
<fo:region-body region-name="xsl-region-body" margin-top="63mm" margin-bottom="1cm"/>
<fo:region-before region-name="xsl-region-before" margin-left="1cm"/>
</fo:simple-page-master>
<fo:simple-page-master master-name="restliche" page-width="210mm" page-height="297mm">
<fo:region-body region-name="xsl-region-body" margin-top="25mm" margin-bottom="1cm"/>
<fo:region-before region-name="xsl-region-before" margin-left="1cm"/>
</fo:simple-page-master>
<fo:page-sequence-master master-name="document">
<fo:single-page-master-reference page-position="first" master-reference="erste"/>
<fo:repeatable-page-master-reference page-position="rest" master-reference="restliche"/>
</fo:page-sequence-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="document">
<fo:flow flow-name="xsl-region-body">
<fo:table border-style="solid" border-width="1pt">
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt" background-color="grey"/>
<fo:table-column border-style="solid" border-width="1pt" background-color="grey"/>
<fo:table-column border-style="solid" border-width="1pt" background-color="grey"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
<fo:table-column border-style="solid" border-width="1pt"/>
fo:table-header
<fo:table-row background-color="black" color="white">
<xsl:for-each select="xml/tableheader/tableheadercol">
<fo:table-cell border-style="solid" border-width="1pt">
<fo:block font-weight="bold"><xsl:value-of select="name"/></fo:block>
</fo:table-cell>
</xsl:for-each>
</fo:table-row>
</fo:table-header>
fo:table-body
<xsl:for-each select="xml/body/bodyrow">
fo:table-row
<xsl:for-each select="bodycol">
fo:table-cell
fo:block<xsl:value-of select="name"/></fo:block>
</fo:table-cell>
</xsl:for-each>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
</fo:flow>
</fo:page-sequence>
<fo:page-sequence master-reference="erste">
<fo:static-content flow-name="xsl-region-before">
<fo:block margin-left="5mm" margin-bottom="5mm" margin-top="10mm" font-size="28pt" font-weight="bold">
<fo:external-graphic src="pix/globe_50.GIF" margin-right="3mm"/><xsl:value-of select="xml/bigpageheader/h1"/>
</fo:block>
<fo:block margin-left="22mm" margin-bottom="3mm" font-size="12pt" font-weight="bold">
<fo:inline color="rgb(0,100,255)"><xsl:value-of select="xml/bigpageheader/sub1"/></fo:inline>
</fo:block>
<fo:block margin-left="22mm" margin-bottom="5mm" font-size="12pt">
<fo:inline color="rgb(0,100,255)"><xsl:value-of select="xml/bigpageheader/sub2"/></fo:inline>
</fo:block>
<fo:block margin-left="22mm" font-size="12pt">
<fo:inline color="rgb(0,100,255)"><xsl:value-of select="xml/bigpageheader/sub3"/></fo:inline>
</fo:block>
<fo:block margin-left="22mm" font-size="12pt">
<fo:inline color="rgb(0,100,255)"><xsl:value-of select="xml/bigpageheader/sub4"/></fo:inline>
</fo:block>
</fo:static-content>
</fo:page-sequence>
<fo:page-sequence master-reference="restliche">
<fo:static-content flow-name="xsl-region-before">
<fo:block margin-left="5mm" margin-top="10mm" font-size="10pt" font-weight="bold">
<fo:external-graphic src="pix/globe_20.gif" margin-right="33mm"/>
<xsl:value-of select="xml/smallpageheader/sub1"/>
</fo:block>
<fo:block margin-left="44mm" margin-bottom="3mm" font-size="10pt">
<xsl:value-of select="xml/smallpageheader/sub2"/> fo:page-number/
</fo:block>
</fo:static-content>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
Musst du nur noch an deinen Bedarf anpassen:
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
fo:layout-master-set
<fo:simple-page-master master-name="erste">
<fo:region-body margin-top="63mm" margin-bottom="1cm"/>
<fo:region-before region-name="kopfersteseite" margin-left="1cm"/>
</fo:simple-page-master>
<fo:simple-page-master master-name="rest">
<fo:region-body margin-top="63mm" margin-bottom="1cm"/>
<fo:region-before region-name="kopfrestseiten" margin-left="1cm"/>
</fo:simple-page-master>
<fo:page-sequence-master master-name="buch">
<fo:single-page-master-reference master-reference="erste"/>
<fo:repeatable-page-master-reference master-reference="rest"/>
</fo:page-sequence-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="buch">
<fo:static-content flow-name="kopfersteseite">
<fo:block font-size="16pt">Hier der Inhalt für Kopf erste Seite eintragen bzw. aus der xml mit xsl:value-of holen</fo:block>
</fo:static-content>
<fo:static-content flow-name="kopfrestseiten">
<fo:block text-align="end" font-size="8pt">Hier der Inhalt für den Kopf der anderen Seiten eintragen oder mit xsl:value-of holen</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<!-- hier deine Tabelle -->
</fo:flow>
</fo:page-sequence>
</fo:root>
Geil, das funktioniert. Vielen Dank für deine Mühe, jetzt kann ich endlich dran weiterschaffen. Hab schon befürchtet sowas is gar nicht machbar :)