I used Apache FOP 2.8 to convert Apache FOP Intermediate Format (IF) files into HTML files
with a self-written xslt stylesheet.
As an external library, I currently only have saxon12he installed.
In the source IF document, there is an image xml element as shown below:
<image xlink:href="files\Logo.png"/>
It would be easy to convert it to HTML
and get a similar output
<img src="files\Logo.png"/>
When using the following template:
<xsl:template match="image"> <xsl:variable name="file-path"><xsl:value-of select="@xlink:href"/></xsl:variable> <img src="{$file-path}"/> </xsl:template>
The problem here is that the generated HTML-file
cannot be "standalone"...meaning there must be files## in addition to
HTML-file< code> # Directory containing Logo.png so that
HTML-file finds the image path
files\Logo.png
< /p>But what I want to achieve is that
HTML files are "independent".
Logo.png to
Base64 , maybe with a simple function call like:
<xsl:template match="image"> <xsl:variable name="file-path"><xsl:value-of select="@xlink:href"/></xsl:variable> <img src="to-base64($file-path)"/> </xsl:template>Create the following output:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...."/>Question #2 (pdf to base64)
xlink:href can also generate
.pdf files...
<image xlink:href="files\Table_1234.pdf"/>It would be great if you could convert it to a Base64 image in the same way as above.
Or maybe there is another way to make the HTML document "standalone", but converting to base64 is the only idea I have so far.
Method 1 (Saxon Java extension function)
So I implemented an
ExtensionFunctionDefinition
import net.sf.saxon.expr.XPathContext; import net.sf.saxon.lib.ExtensionFunctionCall; import net.sf.saxon.lib.ExtensionFunctionDefinition; import net.sf.saxon.om.Sequence; import net.sf.saxon.om.StructuredQName; import net.sf.saxon.trans.XPathException; import net.sf.saxon.value.SequenceType; import net.sf.saxon.value.StringValue; public class ImageToBase64 extends ExtensionFunctionDefinition { @Override public StructuredQName getFunctionQName() { return new StructuredQName("ext", "http://example.com/saxon-extension", "imageToBase64"); } @Override public SequenceType[] getArgumentTypes() { return new SequenceType[]{SequenceType.SINGLE_STRING}; } @Override public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) { return SequenceType.SINGLE_STRING; } @Override public ExtensionFunctionCall makeCallExpression() { return new ExtensionFunctionCall() { @Override public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException { var filePath = ((StringValue)arguments[0]).getStringValue(); // open file and convert to base64 string var resultBase64 = "12345"; return StringValue.makeStringValue(resultBase64); } }; } }Because the documentation says: "
Classes that implement these extended functions must be registered in the configuration ", this can be " achieved by subclassing net.sf.saxon.Transform or net.sf .saxon.Query, override the method applyLocalOptions() so that it makes the appropriate call to config.registerExtensionFunction(); " I also added an extension net.sf.saxon.Transform: < /代码>
import net.sf.saxon.Transform; import net.sf.saxon.trans.CommandLineOptions; public class Configuration extends Transform { @Override protected void applyLocalOptions(CommandLineOptions options, net.sf.saxon.Configuration config) { config.registerExtensionFunction(new ImageToBase64()); super.applyLocalOptions(options, config); } }When I build the artifact to get the
jar file (I'm using
IntelliJ btw.) I just add the "compile output" so the jar ends up being 3kb .
saxon-he-12.2.jar of Apache FOP and added
xmlns:ext="http://example.com/saxon-extension" to
xsl:stylesheet.
<xsl:value-of select="ext:imageToBase64('my/file/path')"/>I get the error
net.sf.saxon.trans.XPathException: The 1-argument function named Q{http://example.com/saxon-extension}imageToBase64() cannot be found
P粉1285631402024-01-17 09:10:25
I did this with the help of @MartinHonnen who told me to create my own extension function.
So I created a new java program (important to use Java 8) and added two classes:
package ExtensionsPackage; import net.sf.saxon.expr.XPathContext; import net.sf.saxon.lib.ExtensionFunctionCall; import net.sf.saxon.lib.ExtensionFunctionDefinition; import net.sf.saxon.om.Sequence; import net.sf.saxon.om.StructuredQName; import net.sf.saxon.trans.XPathException; import net.sf.saxon.value.SequenceType; import net.sf.saxon.value.StringValue; public class ImageToBase64 extends ExtensionFunctionDefinition { @Override public StructuredQName getFunctionQName() { return new StructuredQName("ext", "http://example.com/saxon-extension", "imageToBase64"); } @Override public SequenceType[] getArgumentTypes() { return new SequenceType[]{SequenceType.SINGLE_STRING}; } @Override public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) { return SequenceType.SINGLE_STRING; } @Override public ExtensionFunctionCall makeCallExpression() { return new ExtensionFunctionCall() { @Override public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException { String filePath = ((StringValue)arguments[0]).getStringValue(); // open file and convert to base64 string String resultBase64 = "12345"; return StringValue.makeStringValue(resultBase64); } }; } }
And based on this stackoverflow-entryanother classMyTransformerFactory
:
package ExtensionsPackage; import net.sf.saxon.Configuration; import net.sf.saxon.TransformerFactoryImpl; import net.sf.saxon.lib.ExtensionFunctionDefinition; public class MyTransformerFactory extends TransformerFactoryImpl { public MyTransformerFactory() { super(); ExtensionFunctionDefinition imageToBase64Function = new ImageToBase64(); this.getProcessor().registerExtensionFunction(imageToBase64Function); } public MyTransformerFactory(Configuration config) { super(config); ExtensionFunctionDefinition imageToBase64Function = new ImageToBase64(); this.getProcessor().registerExtensionFunction(imageToBase64Function); } }
Now build a jar
file and place it into the lib
folder of the Apache FOP.
Then add set CUSTOMOPTS=-Djavax.xml.transform.TransformerFactory=ExtensionsPackage.MyTransformerFactory
Go to fop.bat
and add %CUSTOMOPTS%
to :runFop
.
Add the namespace to the stylesheet:
<xsl:stylesheet version="1.0" xmlns:ext="http://example.com/saxon-extension">
and use it like this:
<xsl:value-of select="ext:imageToBase64('my/file/path')"/>
If fop.bat is now executed via the console xsl:value-of
will provide 12345
.