tags:

views:

46

answers:

1

I have an existing xslt script which creates a PDF with FOP, problem is that its running out of memory when doing apply-template on a specific nodetype when the node count exceeds a certain limit. In order to fix the memory issue I need to break up the result derived from that template call into several <fo:page-sequence>, but I dont want a page-sequence for each node, more like for each 100 node.

My first thought was to use position() and simply add new sequence tags every 100th, but as xslt needs to be well formed I cant have open tags like that.

So, my question is what would be the best alternative to iterate all nodes of a specific type in chunks of 100?

Example of how the XML source looks like

 <var ID="V1"><subnodes/></var>  
 ..
 <var ID="V1000"><subnodes/></var>

Currently processed with

<fo:page-sequence>
  <xsl:apply-templates select="ns:var"/>
</fo:page-sequence>

The wanted FOP XML result would be something which created several page-sequences with (for example) 100 of processed var nodes in each instead of having the result of all 1000 in óne page-sequence.

Current result

<fo:page-sequence>
  <formatted V1>
  ..
  <formatted V1000>
</fo:page-sequence>

Wanted result

<fo:page-sequence>
   <formatted V1>
    ..
   <formatted V100>
</fo:page-sequence>

<fo:page-sequence>
  <formatted V101>
   ..
  <formatted V200>
 </fo:page-sequence>

..

<fo:page-sequence>
  <formatted V901>
   ..
  <formatted V1000>
</fo:page-sequence>   
+2  A: 

Edit: Sorry for typo. Miss node test after following-sibling axis

With this input:

<root>
    <var ID="V1">
        <subnodes/>
    </var>
    <var ID="V2">
        <subnodes/>
    </var>
    <var ID="V3">
        <subnodes/>
    </var>
    <var ID="V4">
        <subnodes/>
    </var>
    <var ID="V5">
        <subnodes/>
    </var>
    <var ID="V6">
        <subnodes/>
    </var>
    <var ID="V7">
        <subnodes/>
    </var>
    <var ID="V8">
        <subnodes/>
    </var>
</root>

This styleshet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"&gt;
    <xsl:template match="root">
        <xsl:copy>
            <xsl:copy-of select="document('')/*/namespace::*[name()!='xsl']"/>
            <!-- Forget above. It's just to prettify namespace fixup -->
            <xsl:for-each select="var[position() mod 3 = 1]">
                <fo:page-sequence>
                    <xsl:apply-templates
             select=".|following-sibling::var[3 > position()]"/>
                </fo:page-sequence>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="var">
        <formatted id="{@ID}"/>
    </xsl:template>
</xsl:stylesheet>

Output:

<root xmlns:fo="http://www.w3.org/1999/XSL/Format"&gt;
    <fo:page-sequence>
        <formatted id="V1" />
        <formatted id="V2" />
        <formatted id="V3" />
    </fo:page-sequence>
    <fo:page-sequence>
        <formatted id="V4" />
        <formatted id="V5" />
        <formatted id="V6" />
    </fo:page-sequence>
    <fo:page-sequence>
        <formatted id="V7" />
        <formatted id="V8" />
    </fo:page-sequence>
</root>
Alejandro
Thanks, this works well!
Duveit