Using the following in our Apache FOP v2.2 server will fail in generating the PDF. I've downloaded the FOP 2.2 binary to debug locally and have the following proof of concept inputs. When I remove the call my:foobar()
, there are no issues. FOP 2.9 also fails, although with a little bit different error message.
Why can't I call xsl:function's?
XSLT - transform.xsl
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="http://example.com/namespace"
extension-element-prefixes="my">
<xsl:output method="xml" indent="yes"/>
<xsl:function name="my:numberFromMm" as="xs:string">
Foobar
</xsl:function>
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="A4-portrait" page-height="29.7cm" page-width="21.0cm" margin="2cm">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block>
Hello, <xsl:value-of select="name"/>! My converted: <xsl:value-of select="my:numberFromMm()" />
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
XML- source.xml
<?xml version="1.0" encoding="UTF-8"?>
<name>Frank</name>
Command to generate PDF:
fop.bat -xml "C:\PATH\TO\FILES\source.xml" -xsl "C:\PATH\TO\FILES\transform.xslt" -pdf ./output.pdf
Output (FOP2.2):
Oct 16, 2023 2:29:14 PM org.apache.fop.events.LoggingEventListener processEvent
INFO: Rendered page #1.
Oct 16, 2023 2:29:14 PM org.apache.fop.cli.Main startFOP
SEVERE: Exception
org.apache.fop.apps.FOPException: javax.xml.transform.TransformerException: Instance method call to method numberFromMm requires an Object instance as first argument
javax.xml.transform.TransformerException: javax.xml.transform.TransformerException: Instance method call to method numberFromMm requires an Object instance as first argument
at org.apache.fop.cli.InputHandler.transformTo(InputHandler.java:296)
at org.apache.fop.cli.InputHandler.renderTo(InputHandler.java:116)
at org.apache.fop.cli.Main.startFOP(Main.java:186)
at org.apache.fop.cli.Main.main(Main.java:217)
Caused by: javax.xml.transform.TransformerException: javax.xml.transform.TransformerException: Instance method call to method numberFromMm requires an Object instance as first argument
at org.apache.xalan.extensions.ExtensionHandlerJavaPackage.callFunction(ExtensionHandlerJavaPackage.java:422)
at org.apache.xalan.extensions.ExtensionHandlerJavaPackage.callFunction(ExtensionHandlerJavaPackage.java:440)
at org.apache.xalan.extensions.ExtensionsTable.extFunction(ExtensionsTable.java:222)
at org.apache.xalan.transformer.TransformerImpl.extFunction(TransformerImpl.java:475)
at org.apache.xpath.functions.FuncExtFunction.execute(FuncExtFunction.java:208)
at org.apache.xpath.Expression.executeCharsToContentHandler(Expression.java:313)
at org.apache.xalan.templates.ElemValueOf.execute(ElemValueOf.java:274)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
at org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(TransformerImpl.java:2272)
at org.apache.xalan.transformer.TransformerImpl.transformNode(TransformerImpl.java:1358)
at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:711)
at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1275)
at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1253)
at org.apache.fop.cli.InputHandler.transformTo(InputHandler.java:293)
... 3 more
Caused by: javax.xml.transform.TransformerException: Instance method call to method numberFromMm requires an Object instance as first argument
at org.apache.xalan.extensions.ExtensionHandlerJavaPackage.callFunction(ExtensionHandlerJavaPackage.java:350)
... 24 more
You're using an XSLT 2.0 stylesheet, and the default Apache FOP configuration is invoking Xalan which is XSLT 1.0. You need to persuade it to invoke Saxon. I'm pretty sure there's a way to do that but I've forgotten the detail.