名词解释:FOP
FOP:Apache™ FOP (Formatting Objects Processor) is a print formatter driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java application that reads a formatting object (FO) tree and renders the resulting pages to a specified output. Output formats currently supported include PDF, PS, PCL, AFP, XML (area tree representation), Print, AWT and PNG, and to a lesser extent, RTF and TXT. The primary output target is PDF.
在docx4j里面,如果你想把WORD转换成PDF,目前是有两种方式。一种就是docx4j提供的远程SAS转换服务,另外就是基于FOP实现的WML到FO结构的转换。既然是映射,或多或少有些元素转换是存在问题。至少我目前碰到了几个问题,它的FOP的实现还是需要优化。
1 文档中表格的宽度超过文档的输入区域。如图
2 word的字体集到 pdf的字体集对应有问题,会存在某种字体库未加载
3 在做转换设置的时候,转换配置失效
4 一些特殊字符字体转换不成功
针对上面的四个问题,我结合实际情况来说明,大部分我自己已经解决。
第一个问题的原因:该word的默认为A4大小(21厘米*29.7厘米),但是主体的表格宽度超过了21厘米,达到25.1厘米。在转换FOP的过程中,首个绘制笔触是从文档宽度开始的,这样绘制的内容会少掉图片及印章的内容。变通的解决办法可以在转换之前将文档的宽度设置成合适的值。
其中,14230这个值是25.1厘米转换之后的值。这样,完整的WORD内容才会完全绘制。
第二个问题的原因:该word里面包含了方正小标宋简体,宋体,黑体,华文中宋等四种字体。其中华文中宋字体库一直未加载到fontMapper之中,具体原因还未知。后来定位在AbstractExporter类的export方法中,存在对设置的值进行重新设置(可能是BUG),我在export里面又再次重设才解决。
第三个问题的原因:这个是FOP的低层table对象转换约束,就是tablecell下面不能没有子元素,不然就会抛出missingChildElementError
仅仅通过strict-configuration为false,不能解决这个约束的问题,理论上这个是属于FO的结构体校验问题。
第四个问题的原因:该文档里面有选中的checkbox,在WML里面就会有 <w:sym w:font="Wingdings 2" w:char="0052"/>,在转换成PDF之后。如图
重点关注红框框的内容,这里转换失败,原因未知。在查阅了DOCX4J的论坛之后,https://www.docx4java.org/forums/pdf-output-f27/wingdings-and-pdf-conversion-t1902.html,但是这个帮助不大。目前想到是转换成PDF之后,再通过PDFBOX定位到0052的字符串,将其替换成选中的框,希望下次能再带来一次关于PDFBOX修改分享,这样就相当于曲线救国,完成了WORD到PDF的完美转换。
附各类之间的转换关系