我使用 Apache FOP 2.8 将 Apache FOP 中间格式 (IF) 文件转换为带有自行编写的 xslt 样式表的 HTML 文件
。
作为外部库,我目前只安装了 saxon12he。
在源 IF 文档中,有如下所示的图像 xml 元素:
<image xlink:href="files\Logo.png"/>
将其转换为 HTML
并获得类似的输出会很容易
<img src="files\Logo.png"/>
当使用如下模板时:
<xsl:template match="image"> <xsl:variable name="file-path"><xsl:value-of select="@xlink:href"/></xsl:variable> <img src="{$file-path}"/> </xsl:template>
这里的问题是生成的 HTML-file
不能是“独立的”...意味着除了 HTML-file
之外还必须有 < code>files 目录,其中包含 Logo.png
,以便 HTML-file
找到图像路径 files\Logo.png
< /p>
但我想要实现的是 HTML 文件
是“独立的”。
有没有办法将 Logo.png
转换为 Base64
,也许可以通过简单的函数调用,例如:
<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>
创建如下输出:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...."/>
另一个棘手的部分是,在中间格式中,xlink:href
也可以生成 .pdf
文件...
<image xlink:href="files\Table_1234.pdf"/>
如果能够以与上面相同的方式将其转换为 Base64 图像,那就太好了。
或者也许还有另一种方法可以使 HTML 文档变得“独立”,但转换为 base64 是我迄今为止唯一的想法。
我尝试按照本文档为 Saxon 12 HE 创建 Java 扩展函数
所以我实现了一个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); } }; } }
因为文档说:“实现这些扩展功能的类必须在配置中注册”,这可以“通过子类化 net.sf.saxon.Transform 或 net 来实现.sf.saxon.Query,重写方法 applyLocalOptions() 以便它对 config.registerExtensionFunction() 进行适当的调用;”我还添加了一个扩展 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); } }
当我构建工件以获取 jar
文件时(我使用 IntelliJ
顺便说一句。)我只添加了“编译输出”,所以 jar 最后是 3kb .
然后我将 jar 放入 Apache FOP 的 saxon-he-12.2.jar
旁边的 lib 文件夹中,并添加
xmlns:ext="http://example.com/saxon-extension"
到 xsl:stylesheet
。
但是当我现在打电话时
<xsl:value-of select="ext:imageToBase64('my/file/path')"/>
我收到错误net.sf.saxon.trans.XPathException:找不到名为 Q{http://example.com/saxon-extension}imageToBase64() 的 1 参数函数
< /p>
我在 @MartinHonnen 的帮助下完成了这个工作,他告诉我创建自己的扩展函数。
所以我创建了一个新的java程序(使用Java 8很重要)并添加了两个类:
并根据此stackoverflow-entry另一个类
MyTransformerFactory
:现在构建一个
jar
文件并将其放入 Apache FOP 的lib
文件夹中。然后添加
set CUSTOMOPTS=-Djavax.xml.transform.TransformerFactory=ExtensionsPackage.MyTransformerFactory
到fop.bat
并将%CUSTOMOPTS%
添加到:runFop
。将命名空间添加到样式表中:
并像这样使用它:
如果现在通过控制台执行 fop.bat
xsl:value-of
将提供12345
。