Pdf 解决方案——fop
一,概览
先对比一下itext和fop,以下摘抄自Read Sean大大(汗一个,转到该链接,我才发现博客园还有子站,虽然贴不如主站多,但是有当年主站群英会萃,琳琅满目的感觉)
[iText] (link)
iText我想大概不少人都有所耳闻,JasperReports默认的PDF支持就来自这个软件包,它处理速度快,支持很多PDF"高级"特性,如:Annotations、AcroForms、数字签名、加密等,支持对已有PDF的处理,通过iTextAsian.jar和iTextAsianCmaps.jar,它对中文的支持也不错。缺点是较为依赖Java代码,需要学习不少的专有API,当输入/输出格式有变化时,需要修改代码(除非手工写一些wrapper),不够灵活。
[FOP] (link)
FOP出自Apache,在各大Java网站、论坛出现相对较低,我也是从DocBook这条线摸进来的,DocBook主要提供了一个现成的、符合一般技术书籍要求的数据结构,而展现效果(如PDF),则是通过预定义好的XSL-FO来实现的。XSL-FO是W3C的标准,正式的名称是XSL,是XSL相关的三大组件/语言中的一个,另外两个是XSLT和XPath。Apache的FOP是处理FO的众多proecessor之一,相比iText,支持的输出格式更多,对W3C相关标准支持度高,格式定义可以完全脱离具体的Java代码,十分灵活,且控制力很强。缺点是大数据量时性能较差,默认中文支持不好。目前的版本是0.95。具体代码:
有意思的评论:
从对Java友好这个角度,iText确实不错,但正因为这个特点,脱离了手写的Java代码,操作起来也就不是那么方便了。不像FOP,虽然不是100%标准实现,但思路还是清晰的,基本按照XSL-FO定义就能够做出比较漂亮的排版,不需要写任何Java代码。文中的例子只是示意,其实FOP通过命令行就能玩转,就算通过Java代码去调用,这段Java也是写一次就好,不管你格式多复杂。
对于项目预算有限,或者由于其他原因不能或不希望采用商业解决方案的情况,iText和FOP都是不错的选择,看具体项目/工程需要吧。对于纯输出,以我实际使用看,FOP效果已经很好了,大不了多写点XML,多画点<fo:table/>,死不了。
牵涉到的名词以及它们的关系如图:
其中的xlst其实是xlst扩展出来的XSL-FO,请联想用xlst格式化xml输出xml或html的场景来便于理解它的功用。看w3school的解释:
什么是 XSL-FO?
- XSL-FO 是用于格式化 XML 数据的语言
- XSL-FO 指可扩展样式表语言格式化对象(Extensible Stylesheet Language Formatting Objects)
- XSL-FO 是一个 W3C 推荐标准
- XSL-FO 目前通常被称为 XSL
XSL-FO 和格式化有关
XSL-FO 是一种基于 XML 的标记语言,用于描述向屏幕、纸或者其他媒介输出 XML 数据的格式化(信息)。
XSL-FO 目前通常被称为 XSL
为什么会存在这样的混淆呢?XSL-FO 和 XSL 是一回事吗?
可以这么说,不过我们需要向您作一个解释:
样式化(Styling)是关于转换信息和格式化信息两方面的信息。在万维网联盟编写他们的首个 XSL 工作草案的时候,这个草案包括了有关转换和格式化 XML 文档的语言语法。
后来,XSL 工作组把这个原始的草案分为独立的标准:
- XSLT,用于转换 XML 文档的语言
- XSL 和 XSL-FO,用于格式化 XML 文档的语言
- XPath,是通过元素和属性在 XML 文档中进行导航的语言
整个流程大概是先准备格式说明文件和数据文件(1),然后2,3,4步 从xml和xls得到扩展名为.fo或fob的xls-fo文档(红五),这三个步骤的序列化有很多语言由其处理xml的库或方法都能做到,基本就是调用一个方法,javascript和java早于.net,.net到了2.0版本才有了XslCompiledTransform和Transform方法类。第六步FOP,从xls-fo文档生成pdf文档,需要特殊类库支持。所就职的公司遗留下来的系统1-5步都在asp.net上,到了第六步post fo文档到java web service 去生成pdf.
所以fop解决方案需要两方面知识1,XSL-FO标记语言2,fop类库知识。类库就那几个方法,容易学习,xls-fo标记语言需要更多时间去记,去调试,其实也就如同html标记一样易学难用(布局,美观)。w3school有Xls-fo很好的学习资料,不多说。接着讨论FOP库。
二,FOP库
java
java平台的同学总是很幸福的站在巨人的肩膀上。Apache™ FOP,成熟的fop库,成熟的实例-PDF Generation using XSLFO and FOP。先看第二个实例再看Apache fop可能会理解的更快,so easy的感觉。
.net
.net下有个库叫nfop,就包含一个dll,叫做ApacheFop.Net.dll。把Apache FOP 搬到了.net。有源码下载,非常奇葩 。从这个库,我了解到了原来在.net里,还可以用java的各种类库(添加vjslib引用后,从此世界更广大)。让我们来看一个demo:
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Xsl;
using System.IO;
using System.Net;
using System.Xml.XPath;
using org.apache.fop;
using org.apache.fop.apps;
using org.apache.fop.tools;
using org.xml.sax;
using java.io;
namespace CsharpFop
{
class Program
{
static void Main(string[] args)
{
// Load the style sheet.
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(@"d:\books.xsl");
// Execute the transform and output the results to a file.
xslt.Transform(@"d:\books.xml", @"d:\books.fo");
GeneratePDF(@"d:\books.fo", @"d:\books.pdf");
}
private static void GeneratePDF(string foFile, string pdfFile)
{
//混血儿代码
FileInputStream streamFO = new FileInputStream(foFile);
InputSource src = new InputSource(streamFO);
FileOutputStream streamOut = new FileOutputStream(pdfFile);
Driver driver = new Driver(src, streamOut);
driver.setRenderer(1);
driver.run();
streamOut.close();
}
}
}
比较郁闷的java io stream类和.net io stream以文件为媒介转来转去。
无论是itext还是FOP,java还是.net都会遇到汉字问题,后面再去研究。