aspose file tools*
The moose likes XML and Related Technologies and the fly likes Mulitple fo:page-sequence Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Engineering » XML and Related Technologies
Bookmark "Mulitple fo:page-sequence" Watch "Mulitple fo:page-sequence" New topic
Author

Mulitple fo:page-sequence

Monty Guppy
Ranch Hand

Joined: Sep 15, 2001
Posts: 49
Due to the fact that my PDF runs into 100's of pages, I get outOFMemory exception. I have already taken care of the JVM memory sizes on my machine having 512MB RAM, till this is not enough.
Based on apache's recomendation, I am trying to figure out a way by which I can use multiple page sequence. Basically, my report has the same look and feel on all pages. I can have multiple sequences in one of 2 ways:
- call for a fresh page sequence after, say every 20 records (preferable, since the data volume varies for each record).
- call for a page sequence per new page, wherein I specify that the number of records per page is, say, 5
A simplified version of my XML looks like:
<ROWSET>
<ROW>
<SSN></SSN>
<NAME></NAME>
<ADDRESS></ADDRESS>
<PHONE></PHONE>
</ROW>
</ROWSET>
Here is a very simplified version of XSL that I am currently using:
<fo age-sequence master-reference="default-master">
<fo:static-content flow-name="xsl-region-before">
---------
</fo:static-content>
<fo:static-content flow-name="xsl-region-after">
----------
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:table table-layout="fixed">
<fo:table-column column-width="20mm" background-color="white"/>
<fo:table-column column-width="43mm" background-color="white"/>
<fo:table-column column-width="20mm" background-color="white"/>
<fo:table-column column-width="43mm" background-color="white"/>
<fo:table-header>
--------
</fo:table-header>
<fo:table-body>
<xsl:apply-templates select="document('AllEmployees.xml')/ROWSET/ROW">
</xsl:apply-templates>
</fo:table-body>
</fo:table>
</fo:flow>
</fo age-sequence>
<xsl:template match="ROW">
<fo:table-row keep-with-next="always">
<fo:table-cell>
<fo:block><xsl:value-of select="SSN"/></fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block><fo:block><xsl:value-of select="Name"/></fo:block>
</fo:table-cell>
<fo:table-cell padding="1.0pt">
<fo:block><xsl:value-of select="Address"/></fo:block>
</fo:table-cell>
<fo:table-cell padding="1.0pt">
<fo:block><xsl:value-of select="Phone"/></fo:block>
</fo:table-cell>
</fo:table-row>
</template>
Any help would be greatly appreciated.
Balaji Loganathan
author and deputy
Bartender

Joined: Jul 13, 2001
Posts: 3150
Why u r loading the AllEmployees.xml using document() function.
you can supply xml directly to FOP using -XML option.

One idea could be to preprocess your xml and break them into a group of 5 records using xslt for xml,
this is possible with xsl for-each
<ROWSET>
<break> 5 <ROW></ROW> elements</break>
<break> 5 <ROW></ROW> elements</break>
<break> 5 <ROW></ROW> elements</break>
</ROWSET>
now use a new xsl for FO which will apply a new page sequence for every break element
some thing like this
<xsl:template match="break">
<fo age-sequence master-reference="default-master">
<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates/>
</fo:flow>
</fo age-sequence>
</xsl:template>
Give a try.
rgds
balaji


Spritle Software Blogs
Monty Guppy
Ranch Hand

Joined: Sep 15, 2001
Posts: 49
I don't have control over the XML, which is delivered to me from elsewhere. So, I can't get additional tags.
However, I have been able to make some progress, and now get one record per page. I know that using MOD and position(), I can send 5 records per page sequence, but I am not sure how to implement it in the code.
Following is the XSL for the XML noted above, which generates 1 record per page-sequence while I want it to generate 5 records per page-sequence.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">

<xsl utput method="xml" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<!-- Define a body (or default) page. -->
<fo:simple-page-master master-name="default-master">
<!-- Central part of page -->
<fo:region-body/>
<fo:region-before/>
<fo:region-after/>
</fo:simple-page-master>
</fo:layout-master-set>
<xsl:apply-templates select="/ROWSET/ROW">
</xsl:apply-templates>
</fo:root>
</xsl:template>

<xsl:template match="ROW">
<!-- Page Sequence -->
<fo age-sequence master-reference="default-master">
<fo:static-content flow-name="xsl-region-before">
<fo:block>
<!-- Define header. -->
</fo:block>
</fo:static-content>
<fo:static-content flow-name="xsl-region-after">
<fo:block>
<!-- Define footer. -->
</fo:block>
</fo:static-content>
<!-- The contents of the body page
entries -->
<fo:flow flow-name="xsl-region-body">
<fo:table table-layout="fixed">
<fo:table-column column-width="20mm"/>
<fo:table-column column-width="43mm"/>
<fo:table-column column-width="20mm"/>
<fo:table-column column-width="43mm"/>
<fo:table-header>
<fo:table-row>
<fo:table-cell number-columns-spanned="4" padding="4.0pt">
<fo:block><xsl:value-of select="ROWSET/REPORT_HEADER"/></fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-header>
<fo:table-body>
<fo:table-row>
<fo:table-cell padding="1.0pt">
<fo:block text-align="right">
<fo:inline>Name:</fo:inline>
</fo:block>
</fo:table-cell>
<fo:table-cell padding="1.0pt">
<fo:block text-align="left" font-size="6pt" font-weight="normal">
<xsl:value-of select="FIRST_NAME"/></fo:block>
</fo:table-cell>
<fo:table-cell padding="1.0pt">
<fo:block text-align="right" >
<xsl:text>SSN:</xsl:text>
</fo:block>
</fo:table-cell>
<fo:table-cell padding="1.0pt">
<fo:block text-align="left" font-size="6pt" font-weight="normal">
<xsl:value-of select="SSN"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
- - - - getting all other data - - - - - -
</fo:table-body>
</fo:table>
</fo:flow>
</fo age-sequence>
</xsl:template>
</xsl:stylesheet>
Balaji Loganathan
author and deputy
Bartender

Joined: Jul 13, 2001
Posts: 3150
Originally posted by Prateek Gupta:
I don't have control over the XML, which is

Prateek,
Even if it sent by someone else on a random basis,you still have control on it.All u r going to do is receive the incoming xml,group them, process them for pdf.
i guess this link will sure help you on grouping.
www.dpawson.co.uk/xsl/sect2/N4486.html
Just wondering how i received a related email tip, with files in your name. is that you ? below the main content of the email.
Balaji Loganathan
author and deputy
Bartender

Joined: Jul 13, 2001
Posts: 3150
Hope you solved problem,if not get back.
Monty Guppy
Ranch Hand

Joined: Sep 15, 2001
Posts: 49
Balaji,
Thanks to you and some others who helped me point to the right direction. I was able to write the XSL for multi-page-sequences, without altering the XML.
If you or any one else would be interested, please let me know and I would post it.\
One interesting thing that I did note is that it is better to render many pages at a time rather than necessarily one page at a time. The original problem I had was I was getting java.lang.outOfMemory. Apparently the PDF gets rendered at the end of each page sequence. So, one can increase the number of records in a page sequence such that it spans to say 50 PDF pages. Rendering 50 pages at a time (in a 2000 page PDF document that I have) is better than rendering 1 page at a time. It saved about 15% time in doing that.
Some of the other things that I did to overcome Memory problems is setting the JVM memory size and taking away "Page x of y" type of references.
Thanks
Prateek
Balaji Loganathan
author and deputy
Bartender

Joined: Jul 13, 2001
Posts: 3150
if you dont mind,please post ur solution (xsl)here, it will sure help others.
Monty Guppy
Ranch Hand

Joined: Sep 15, 2001
Posts: 49
Please pay special attention to:
<xsl:for-each select="ROW[position() mod 150 = 1]"> (Here I consider 150 records per sequence)
and
<xsl:for-each select="following-sibling::ROW[ position() < 150 ]"> (This is where template is applied to other 149 records)
XML:
<ROWSET>
<ROW num="1">
<SSN>100-00-2000</SSN>
<FIRST_NAME>Darren</FIRST_NAME>
<MIDDLE_NAME>S</MIDDLE_NAME>
<LAST_NAME>Adli</LAST_NAME>
<SEX>M</SEX>
<BIRTH_DATE>08/10/1955</BIRTH_DATE>
<HOME_PHONE>500-245-2000</HOME_PHONE>
<ADDR_LINE1>2422 Glenmary Avenue</ADDR_LINE1>
<CITY>New York</CITY>
<STATE>LA</STATE>
<ZIP_CD>65201</ZIP_CD>
<CLASS_DESCRIPTION>LOUISVILLE</CLASS_DESCRIPTION>
<DEPENDANTS>Lizzy Richard (Spouse)<DEPENDANTS>
</ROW>
<ROW num="2">>
.. . . .
</ROW>
XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">

<xslutput method="xml" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<!-- Define a body (or default) page. -->
<fo:simple-page-master master-name="default-master">
<!-- Central part of page -->
<fo:region-body/>
<fo:region-before/>
<fo:region-after/>
</fo:simple-page-master>
</fo:layout-master-set>
<xsl:apply-templates select="/ROWSET">
</xsl:apply-templates>
<!--xsl:template match="/ROWSET/ROW">
<xsl:apply-templates select="ROW[position() mod 4 = 1]" />
</xsl:template-->
</fo:root>
</xsl:template>
<xsl:template name="headerFooter">
<!-- Define the contents of the header. -->
<fo:static-content flow-name="xsl-region-before">
<fo:block >
<fo:table table-layout="fixed" height="13.2mm">
<fo:table-column column-width="40mm"/>
<fo:table-column column-width="85mm"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block>
<fo:external-graphic
src="url('C:/Humana/Reporting/pdfgeneration/images/logo.gif')" content-height="auto" content-width="1em"/>
</fo:block>
</fo:table-cell>
<fo:table-cell background-color="white" display-align="center">
<fo:table table-layout="fixed" height="7.2mm">
<fo:table-column column-width="80mm"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block>
<fo:inline>
<xsl:value-of
select="REPORT_NAME"/>
</fo:inline>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
</fo:static-content>
<!-- Define the contents of the footer. -->
<fo:static-content flow-name="xsl-region-after">
<fo:block>
<xsl:text>Page </xsl:text>
<fo:page-number/> of 
<!--fo:page-number-citation ref-id="{generate-id(/)}"/--></fo:block>
</fo:static-content>
</xsl:template>
<xsl:template match="ROWSET">
<xsl:for-each select="ROW[position() mod 150 = 1]">
<fo:page-sequence master-reference="default-master">
<xsl:call-template name="headerFooter"/>
<!-- Body of the page -->
<fo:flow flow-name="xsl-region-body">
<fo:table table-layout="fixed">
<fo:table-column column-width="20mm" background-color="white"/>
<fo:table-column column-width="43mm" background-color="white"/>
<fo:table-column column-width="20mm" background-color="white"/>
<fo:table-column column-width="43mm" background-color="white"/>
<fo:table-header>
<fo:table-row background-color="#CCCCCC">
<fo:table-cell number-columns-spanned="4" padding="4.0pt">
<fo:block>
<xsl:value-of select="REPORT_HEADER"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row background-color="white">
<fo:table-cell number-columns-spanned="4">
<fo:block> </fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-header>
<fo:table-body>
<xsl:call-template name="xyz"/>
<xsl:for-each select="following-sibling::ROW[ position() < 150 ]">
<xsl:call-template name="xyz"/>
</xsl:for-each>
</fo:table-body>
</fo:table>
</fo:flow>
</fo:page-sequence>
</xsl:for-each>
</xsl:template>

<xsl:template name="xyz">
<fo:table-row keep-with-next="always">
<fo:table-cell padding="1.0pt">
<fo:block text-align="right" font-style="italic" font-size="6pt" font-weight="normal">
<fo:inline>Name:</fo:inline>
</fo:block>
</fo:table-cell>
<fo:table-cell padding="1.0pt">
<fo:block text-align="left" font-size="6pt" font-weight="normal">
<xsl:value-of select="FIRST_NAME"/> <xsl:value-of
select="MIDDLE_NAME"/> <xsl:value-of select="LAST_NAME"/></fo:block>
</fo:table-cell>
<fo:table-cell padding="1.0pt">
<fo:block text-align="right" font-style="italic" font-size="6pt" font-weight="normal">
<xsl:text>SSN:</xsl:text>
</fo:block>
</fo:table-cell>
<fo:table-cell padding="1.0pt">
<fo:block text-align="left" font-size="6pt" font-weight="normal">
<xsl:value-of select="SSN"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
- - - - getting all other data - - - - - -
</xsl:template>
</xsl:stylesheet>
Kamohelo Mofokeng
Greenhorn

Joined: Oct 07, 2009
Posts: 8
This is a really old post - I understand.

Anyone know how to customize this solution for my environment?

My sample xsl file:



$ my sample xml file:



With the current state of this code, I get an exception at line:
<xsl:if select="ROOT/MEM-STMT/ACC/PROV[position() mod 30 = 1]">
& the exception is:
org.apache.fop.fo.FOTreeBuilder fatalError. SEVERE: java.lang.NullPointerException


Any help is immensely appreciated.


_______________________________________

SCJP 6
g tsuji
Ranch Hand

Joined: Jan 18, 2011
Posts: 535
    
    3
@Kamohelo Mofokeng
For xsl:if element, the attribute is test (for node test); select? never!

Kamohelo Mofokeng
Greenhorn

Joined: Oct 07, 2009
Posts: 8
Thanks g tsuji,

I have changed xsl:if accordingly i.e. changed select to test.

So, how do I implement Monty Guppy's example for my environment - I'm still trying create multiple page sequences because I'm running out of memory when I perform transormation for large files.

Regards
g tsuji
Ranch Hand

Joined: Jan 18, 2011
Posts: 535
    
    3
If that change takes out the error, what is not working? As it is a sacre long scrpt, I would suggest you open a new thread of your own so as not to mess up other people's concern. Further, I would suggest you give more precision on what errors or expectations etc... to provide more motivation for people to read it entirely critically.
Kamohelo Mofokeng
Greenhorn

Joined: Oct 07, 2009
Posts: 8
Thank you g tsuji for the suggestion, I have created a new thread: http://www.coderanch.com/t/559137/XML/XSL-FO-Multiple-Page-Sequences

 
jQuery in Action, 2nd edition
 
subject: Mulitple fo:page-sequence