gpt4 book ai didi

java - 带有嵌入式 HTML 的 PDF 报告

转载 作者:太空狗 更新时间:2023-10-29 13:14:16 24 4
gpt4 key购买 nike

我们有一个基于 Java 的系统,它从数据库中读取数据,将各个数据字段与预设 XSL-FO 合并标记并将结果转换为 PDFApache FOP .

XSL-FO格式如下:

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE Html [
<!ENTITY nbsp "&#160;">
<!-- all other entities -->
]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">

<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg" font-family="..." font-size="...">
<fo:layout-master-set>
<fo:simple-page-master master-name="Letter Page" page-width="8.500in" page-height="11.000in">

<!-- appropriate settings -->

</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="Letter Page">

<!-- some static content -->

<fo:flow flow-name="xsl-region-body">
<fo:block>
<fo:table ...>
<fo:table-column ... />
<fo:table-body>
<fo:table-row>
<fo:table-cell ...>
<fo:block text-align="...">
<fo:inline font-size="..." font-weight="...">
<!-- Header / Title -->
</fo:inline>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>

<fo:block>

<fo:table ...>
<fo:table-column ... />
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block ...>
<!-- Field A -->
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>

<!-- Other fields in a very similar fashion as the above "Field A" -->

</fo:block>

</fo:flow>

</fo:page-sequence>

</fo:root>

</xsl:template>

</xsl:stylesheet>

现在我正在寻找一种允许某些字段包含静态HTML 格式 内容的方法。此内容将由我们支持 HTML 的编辑器生成(类似于 CLEditorCKEditor 等)或从外部粘贴。

我的计划是遵循食谱 from this JavaWorld article :

  • 使用JTidy将 HTML 格式的字符串转换为正确的 XHTML
  • 进一步修改xhtml2fo.xsl从 Antenna House 删除所有文档范围和页面范围的转换
  • 将修改后的 XSLT 应用于我的 XHTML 字符串 (javax.xml.transform)
  • 用XPath (javax.xml.xpath) 提取根目录下的所有节点
  • 将结果直接输入现有的 XSL-FO 文档

我有此类代码的基本版本,但出现以下错误:

(Location of error unknown)org.apache.fop1.fo.ValidationException: "{http://www.w3.org/1999/XSL/Format}table-body" is not a valid child of "fo:block"! (No context info available)

我的问题:

  1. 解决此问题的方法是什么?
  2. 可以<fo:block>充当通用容器,其中嵌套了其他对象(包括表格)?
  3. 这是解决任务的总体合理方法吗?

如果有人“在那里做过那件事”,请分享您的经验。

最佳答案

  1. 如果您在 oXygen 或 XML Spy 中使用 XSLT 调试器,则可以逐步完成转换。使用 oXygen——不确定 XML Spy 或其他编辑器——如果您单击调试器输出中的标记,oXygen 会突出显示来自源代码和生成该节点的样式表的标记。

    一旦您拥有 FO,focheck 框架 ( https://github.com/AntennaHouse/focheck ) 就拥有目前可用的最完整的 FO 验证。

  2. fo:block可以包含表格等。在 XSL 1.1 规范中,每个 FO 的定义都包含一个“内容”小节,其中列出了其允许的内容。参见,例如 http://www.w3.org/TR/xsl11/#fo_block .内容模型中“参数实体”的定义位于 http://www.w3.org/TR/xsl11/#d0e6532。 , 但一些 FO 在其定义的文本中有额外的限制。

  3. 您引用的文章似乎没有“使用 XPath 提取根下的所有节点”步骤,我不确定您为什么需要它。除此之外,它看起来是使用 Java 完成这项工作的合理方法。


不是将从 JTidy 编辑的 HTML 转换而来的 FO 插入静态 FO,而是可以替换 <!-- Field A -->使用非 FO 标记提供足够的信息来引用要插入的字段。然后,您可以制作一个 XSLT 样式表,通过对 FO 部分进行恒等变换,将模板+引用文档转换为直接 FO——正如@kevin-brown 的回答——并使用引用标记中的信息构建与 document() 一起使用的 URI函数 ( http://www.w3.org/TR/xslt#document ) 查找要插入的标记。

如果字段内容的 FO 位于磁盘上,则使用 document()很简单。如果不是,那么您必须执行一些操作,例如覆盖 XSLT 处理器使用的 URIResolver,这样它就可以正确地检索内容,而不是在磁盘上查找。您甚至可以让 JTidying 作为 URIResolver 检索 HTML 的一部分发生。您也可以在 URIResolver“内部”对 FO 进行转换,或者也像@kevin-brown 建议的那样,将其作为单独的模式进行。如果转换是在 URIResolver 检索 FO 之前或期间完成的,那么模板+对 FO 的引用的“主要”转换只需要提取 FO 子文档的正确部分,例如document('constructed-URI')/fo:root/fo:page-sequence/* .但是,如果您从 Antenna House 修改样式表,那么您应该能够修改它以不生成外部 fo:root。等等。

几年前我做了类似的事情,为基于 XSLT 的服务器覆盖了 libxslt XSLT 处理器的 URI 解析器:内部 XSLT 处理器连续运行的上下文被保存为特殊 URI 的文档,不一定写入到文件系统。

相反,您可以编写一个扩展函数来查找对字段的引用。例如,Print and Page Layout Community Group @ W3C 已经为多个 XSLT 处理器生成了扩展函数,这些处理器在 XSLT 转换的中间运行一个 FO 处理器,以获取格式化结果的区域树的 XML。参见 http://www.w3.org/community/ppl/wiki/XSLTExtensions

关于java - 带有嵌入式 HTML 的 PDF 报告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32789541/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com