Issue
I'm using XSL-T (v1.0) and XSL-FO (Apache FOP 1.0) to produce PDF (A4) reports using data from forms filled by user in a third-party software (that output XML).
The forms contains text areas users can fill as they want (no control over the content size). The text area content is then outputed in an XML as a node/text()
(<textArea> ** content: user input ** </textArea>
). To preserve users input formatting, I use linefeed-treatment = "preserve"
attribute at the block-level.
Problem is, whenever text areas are filled with enough data to cause a page break, I have a nullPointerException
with Apache FOP 1.0 when the page-break occurs on a line-break. I can't find any solution to the problem except using a keep-together.within-page = "always"
as a workaround (not a long-term solution as I loose data when text()
is longer than one page.
Tools
To develop XSL Stylesheet, I'm using:
- XSLT Engine: Altova (built-in RaptorXML XSLT engine) with XSLT v1.0
- FOP Processor: Apache FOP 1.0
I don't have a choice regarding what the software uses to generate PDF with the XSL Stylesheet (stuck with FOP 1.0 and XSLT 1.0).
Context
To produce reports based on user inputs within their forms, the software allows to link an XSL Stylesheet to each kind of form. It then uses Apache FOP 1.0 and an unknown XSLT engine to apply the XSL stylesheet to the XML output. I'm in charge of building those XSL Stylesheet for each kind of forms and I'm stuck with that issue.
Below is the error outputed by FOP and the XSL-FO (trimmed and complete) issuing the error.
Part of XSL-FO causing the issue
<fo:block space-before="5mm" text-align="justify">
<fo:block linefeed-treatment="preserve" keep-together.within-page="auto">
<fo:block>
<fo:inline/>
<fo:inline> TEST
END OF TEST </fo:inline>
</fo:block>
</fo:block>
</fo:block>
Error verbose
Standard Error
Jun 29, 2018 9:02:59 AM org.apache.fop.cli.Main startFOP
SEVERE: Exception
org.apache.fop.apps.FOPException
java.lang.NullPointerException
at org.apache.fop.cli.InputHandler.transformTo(InputHandler.java:302)
at org.apache.fop.cli.InputHandler.renderTo(InputHandler.java:130)
at org.apache.fop.cli.Main.startFOP(Main.java:174)
at org.apache.fop.cli.Main.main(Main.java:205)
Caused by: java.lang.NullPointerException
at org.apache.fop.layoutmgr.AbstractBreaker.doLayout(AbstractBreaker.java:434)
at org.apache.fop.layoutmgr.PageBreaker.doLayout(PageBreaker.java:85)
at org.apache.fop.layoutmgr.PageSequenceLayoutManager.activateLayout(PageSequenceLayoutManager.java:107)
at org.apache.fop.area.AreaTreeHandler.endPageSequence(AreaTreeHandler.java:238)
at org.apache.fop.fo.pagination.PageSequence.endOfNode(PageSequence.java:120)
at org.apache.fop.fo.FOTreeBuilder$MainFOHandler.endElement(FOTreeBuilder.java:349)
at org.apache.fop.fo.FOTreeBuilder.endElement(FOTreeBuilder.java:177)
at org.apache.xalan.transformer.TransformerIdentityImpl.endElement(TransformerIdentityImpl.java:1101)
at org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown Source)
at org.apache.xerces.xinclude.XIncludeHandler.endElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanEndElement(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:484)
at org.apache.fop.cli.InputHandler.transformTo(InputHandler.java:299)
... 3 more
---------
java.lang.NullPointerException
at org.apache.fop.layoutmgr.AbstractBreaker.doLayout(AbstractBreaker.java:434)
at org.apache.fop.layoutmgr.PageBreaker.doLayout(PageBreaker.java:85)
at org.apache.fop.layoutmgr.PageSequenceLayoutManager.activateLayout(PageSequenceLayoutManager.java:107)
at org.apache.fop.area.AreaTreeHandler.endPageSequence(AreaTreeHandler.java:238)
at org.apache.fop.fo.pagination.PageSequence.endOfNode(PageSequence.java:120)
at org.apache.fop.fo.FOTreeBuilder$MainFOHandler.endElement(FOTreeBuilder.java:349)
at org.apache.fop.fo.FOTreeBuilder.endElement(FOTreeBuilder.java:177)
at org.apache.xalan.transformer.TransformerIdentityImpl.endElement(TransformerIdentityImpl.java:1101)
at org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown Source)
at org.apache.xerces.xinclude.XIncludeHandler.endElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanEndElement(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:484)
at org.apache.fop.cli.InputHandler.transformTo(InputHandler.java:299)
at org.apache.fop.cli.InputHandler.renderTo(InputHandler.java:130)
at org.apache.fop.cli.Main.startFOP(Main.java:174)
at org.apache.fop.cli.Main.main(Main.java:205)
Complete XSL-FO before FOP
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="coverPage" margin="5mm" page-height="297mm" page-width="210mm" reference-orientation="0" writing-mode="lr-tb">
<fo:region-body margin-top="25mm" margin-bottom="25mm" margin-left="45mm" margin-right="5mm"/>
<fo:region-after extent="20mm" precedence="true" display-align="before"/>
<fo:region-start extent="40mm"/>
</fo:simple-page-master>
<fo:simple-page-master master-name="repeatablePage" margin="5mm" page-height="297mm" page-width="210mm" reference-orientation="0" writing-mode="lr-tb">
<fo:region-body margin-top="30mm" margin-bottom="25mm" margin-left="20mm" margin-right="20mm"/>
<fo:region-after extent="20mm" precedence="true" display-align="before"/>
</fo:simple-page-master>
<fo:page-sequence-master master-name="pageSequence">
<fo:single-page-master-reference master-reference="coverPage"/>
<fo:repeatable-page-master-reference master-reference="repeatablePage" maximum-repeats="no-limit"/>
</fo:page-sequence-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="pageSequence" font-family="sans-serif" font-weight="normal">
<fo:static-content flow-name="xsl-region-after">
<fo:block text-align="right" font-size="10" color="#083E70">
Page <fo:page-number/> de <fo:page-number-citation ref-id="endDoc"/></fo:block>
<fo:block text-align="center" font-size="8" color="#083E70" space-before="8mm">
<fo:block>ADRESSE LINE 1</fo:block>
<fo:block>ADRESSE LINE 2</fo:block>
</fo:block>
</fo:static-content>
<fo:static-content flow-name="xsl-region-start">
<fo:block>
<fo:external-graphic src="Logo.jpg" content-width="40mm" scaling="uniform"/>
</fo:block>
<fo:block-container color="#083E70" border-end-color="#083E70" border-end-width="1pt" border-end-style="solid" block-progression-dimension="235mm">
<fo:block/>
<fo:block space-before="10mm" space-after="10mm" font-weight="bold" text-decoration="underline"/>
</fo:block-container>
</fo:static-content>
<fo:flow flow-name="xsl-region-body" font-size="10pt">
<fo:block text-align="right" space-after="5mm">
<fo:inline>Bruxelles, le </fo:inline>
<fo:inline>19/06/2018</fo:inline>.
</fo:block>
<fo:block space-after="10mm" border="0pt solid black" padding="2mm 0">
<fo:table start-indent="3mm" space-after="10mm" table-layout="fixed" width="147mm">
<fo:table-column column-number="1" column-width="35mm"/>
<fo:table-column column-number="2" column-width="112mm"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block>
<fo:inline font-weight="bold">
<fo:inline>Destinataire:</fo:inline>
</fo:inline>
</fo:block>
</fo:table-cell>
<fo:table-cell display-align="center">
<fo:block start-indent="40mm">Mara Kristen<fo:block/>5911 Maple Blvd<fo:block/>1400 NIVELLES<fo:block/>B<fo:block/></fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
<fo:table start-indent="3mm" table-layout="fixed" width="147mm">
<fo:table-column column-number="1" column-width="35mm"/>
<fo:table-column column-number="2" column-width="112mm"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block>
<fo:inline font-weight="bold">
<fo:inline>Copie:</fo:inline>
</fo:inline>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<fo:inline>Gold Denis</fo:inline>
<fo:inline font-style="italic"> (Merci Denis !, 3001 HEVERLEE, B)</fo:inline>
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block/>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<fo:inline>Gold Denis</fo:inline>
<fo:inline font-style="italic"> (Merci Denis !, 3001 HEVERLEE, B)</fo:inline>
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block/>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<fo:inline>Gold Denis</fo:inline>
<fo:inline font-style="italic"> (Merci Denis !, 3001 HEVERLEE, B)</fo:inline>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
<fo:block text-align="left" space-after="10mm">
Ref.: 002956347</fo:block>
<fo:block space-after="10mm" text-align="center" text-decoration="underline" font-weight="bold">
<fo:inline>Lettre de consultation - </fo:inline>Psychiatrie</fo:block>
<fo:block>
<fo:inline>Concerne: </fo:inline>
</fo:block>
<fo:block space-after="10mm" border="1pt solid black" padding="2mm 0">
<fo:table table-layout="fixed" start-indent="3mm" width="147mm">
<fo:table-column column-number="1" column-width="35mm"/>
<fo:table-column column-number="2" column-width="112mm"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block font-weight="bold">
<fo:inline>Nom, Prénom:</fo:inline>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>Quigley, Jules</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block font-weight="bold">
<fo:inline>Adresse:</fo:inline>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>9816 Main Street,
1402 LOOL,
B</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block font-weight="bold">
<fo:inline>Nr. national:</fo:inline>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>31035622101</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
<fo:block text-align="left">
<fo:inline font-weight="bold" text-decoration="underline">
<fo:inline>Sujet:</fo:inline>
</fo:inline> <fo:inline>
<fo:inline>Exemple</fo:inline>
</fo:inline>
</fo:block>
<fo:block space-before="5mm" text-align="justify">
<fo:block linefeed-treatment="preserve" keep-together.within-page="auto">
<fo:block>
<fo:inline/>
<fo:inline>TEST
TEST</fo:inline>
</fo:block>
</fo:block>
</fo:block>
<fo:block keep-together.within-page="always">
<fo:block space-before="10mm" text-align="right">
<fo:inline text-decoration="underline">
<fo:inline>Signataire</fo:inline>
</fo:inline>
<fo:block/>
<fo:block>
<fo:inline>John SMITH</fo:inline>
</fo:block>
<fo:block>
<fo:inline>
<fo:inline>Nr. INAMI: </fo:inline>
</fo:inline>
<fo:inline>45632163140</fo:inline>
</fo:block>
</fo:block>
</fo:block>
<fo:block id="endDoc"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
EDIT
I've found a way to replace all the line-breaks with  <fo:block/>
as suggested by @lfurini but it still produce de same NPE error.
Code used is shown below:
<xsl:template name="gReplaceLineBreak">
<xsl:param name="pString"/>
<xsl:choose>
<xsl:when test="substring-before($pString,'
')">
<xsl:value-of select="substring-before($pString,'
')"/> <fo:block/>
<xsl:call-template name="gReplaceLineBreak">
<xsl:with-param name="pString" select="substring-after($pString,'
')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$pString"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
EDIT-2
Ok I've finally found why it wasn't working with the above code. There was a <fo:inline>
node enclosing all the <fo:block/>
. Now that I removed it, it works as @lfurini said it would. Thanks a lot.