跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

如何在程序中嵌入 FOP

FOP 简介

马路,2000级清华大学计算机系研究生,目前在清华大学Java应用技术实验室学习。E-mail: stevema@263.net

简介: 如何在程序中嵌入 FOP。FOP 是由 James Tauber 发起的一个开源项目,最初的目的是利用 xsl-fo 将 xml 文件转换成 pdf 文件。目前最新的版本可以将 xml 文件转换成 pdf,mif,pcl,txt 等多种格式以及直接输出到打印机,并且支持使用 SVG 描述图形。XML 显然是最好的内容存储格式,而 PDF 是目前最流行的内容载体格式,FOP 显然希望借助这种必然的 XML to PDF 需求,来推动 xsl-fo 规范的发展。虽然 xsl-fo 规范停滞不前,但利用 FOP 能使自己的程序具有将 XML 内容输出成 PDF 等流行格式的功能无疑是令人兴奋的。

发布日期: 2001 年 11 月 01 日
级别: 初级
访问情况 : 1620 次浏览
评论: 


FOP使用方式

FOP有3种使用方式,分别为命令行,程序嵌入,XT 嵌入,这里将主要介绍如何在程序中嵌入FOP功能。将XML文件转换为PDF实际上分为2步,第1步是利用XSLT将XML转换为XSL-FO,第2步是将XSL-FO转换为PDF。这里不想讲述XSLT和XSL-FO有关的知识(这方面的文档相当多),而只将讲述如何进行第2步的转换编程。

在程序中嵌入FOP

1. 范例simple.fo文件

<?xml version="1.0" encoding="utf-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
  <fo:layout-master-set>
    <fo:simple-page-master master-name="simple"
                  page-height="29.7cm" 
                  page-width="21cm"
                  margin-top="1cm" 
                  margin-bottom="2cm" 
                  margin-left="2.5cm" 
                  margin-right="2.5cm">
      <fo:region-body margin-top="3cm"/>
      <fo:region-before extent="3cm"/>
      <fo:region-after extent="1.5cm"/>
    </fo:simple-page-master>
  </fo:layout-master-set>
  <fo:page-sequence master-name="simple">
    <fo:flow flow-name="xsl-region-body">
       <!-- Title -->
      <fo:block font-size="18pt" 
            font-family="sans-serif" 
            line-height="24pt"
            space-after.optimum="15pt"
            background-color="blue"
            color="white"
            text-align="center"
            padding-top="3pt">
            FOP 0.20.2
      </fo:block>
      <!-- Normal Text -->
      <fo:block font-size="12pt" 
                font-family="sans-serif" 
                line-height="15pt"
                space-after.optimum="3pt"
                text-align="justify">
FOP is the world's first print formatter driven by XSL formatting objects.
It is a Java application that reads a formatting object tree and then 
turns it into a PDF document.
      </fo:block>
    </fo:flow>
  </fo:page-sequence>
</fo:root>

上述是一个很简单的fo文件,将显示两块文字,具体的fo语法请读者自己查看相应资料。

2. 简单调用FOP
FOP提供的所有对外调用接口都在org.apache.fop.apps下,其下的AWTStarter.class是一个用AWT写的转换结果预览程序,CommandLineStarter.class提供命令行使用方式,PrintStarter.class提供打印接口,XTDriver.class提供XT嵌入方式接口,Driver.class则是我们要在这里讨论的程序接口。下面这个程序foptest.java演示了FOP的最简单也是最常用的使用方式。

import java.io.*;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.apache.fop.apps.*;
public class foptest {
    public static void main(String[] args) {
        try {
            Driver driver = new Driver();
            //设置要转换的fo文件名
            driver.setInputSource(new InputSource (args[0]));
            //设置输出文件名
            driver.setOutputStream(new FileOutputStream(args[1]));
            //设置转换类型
            //还可以为RENDER_PCL,RENDER_PS,RENDER_TXT,RENDER_MIF
            driver.setRenderer(Driver.RENDER_PDF);
            //开始转换
            driver.run();
        }
        catch( Exception e ){
            e.printStackTrace();
        }
    }
}

上述程序将接受两个命令行参数,第一个参数是需要转换的fo文件名,第二个参数是输出文件名。在CLASSPATH中添加下述jar文件: {FOP安装目录}\build\fop.jar
{FOP安装目录}\lib\batik.jar
{FOP安装目录}\lib\xalan-2.0.0.jar
{FOP安装目录}\lib\xerces-1.2.3.jar
{FOP安装目录}\lib\avalon-framework-4.0.jar
{FOP安装目录}\lib\logkit-1.0b4.jar
{FOP安装目录}\lib\jimi-1.0.jar
然后执行java foptest simple.fo simple.pdf

执行后产生的simple.pdf文件效果如下



3. 显示中文
上面的演示程序段可以应付绝大部分转换编程的需要,不过对于国内用户来说,不可避免的需要产生中文PDF文件,让我们把上述simple.fo的标题从"FOP 0.20.2"改成"支持中文的FOP 0.20.2",不改动程序的情况下执行结果显示如下



可以看到由于没有加入相应的字体支持,汉字被显示成了#。

东方字符的显示在FOP的早期版本中并不被支持,最早尝试对FOP打补丁以解决显示东方字符的是日本人。从FOP 0.16版本开始,他们在sourceforge上建立了一个jpfop项目来解决日文字符的显示问题,使用相同的方法也可以被用来显示中文字符。幸运的是,当前的FOP版本已经能很好的解决中文显示的问题,不再需要我们打补丁,下面是在FOP中使用中文的步骤:

  • 第一步,建立font metrics文件 对于后缀为ttf的TrueType字体文件,我们可以执行以下命令来产生font metrics文件 java org.apache.fop.fonts.apps.TTFReader C:\WINNT\Fonts\simkai.ttf simkai.xml
    这里simkai.xml就是我们为楷体产生的font metrics文件。 对于Windows下的宋体来说,存在的是后缀为ttc的TrueType Collection文件,即包含多个TrueType的文件,这时首先要做的是得到这个Collection中所有TrueType的名字,执行以下命令(这个命令其实有错误):
    java org.apache.fop.fonts.apps.TTFReader C:\WINNT\Fonts\simsun.ttc simsun.xml

    产生输出如下:

    This is a TrueType collection file with2 fonts
    Containing the following fonts:
    SimSun
    NSimSun
    java.io.IOException: Failed to read font
            at org.apache.fop.fonts.TTFFile.readFont(TTFFile.java:388)
            at org.apache.fop.fonts.apps.TTFReader.loadTTF(TTFReader.java:181)
            at org.apache.fop.fonts.apps.TTFReader.main(TTFReader.java:143)
    

    后面的异常是由于我们给的参数不对(因为ttc不是ttf字体文件)造成的,FOP开发小组知道这个问题,但是可能觉得无关痛痒而没去修正它。无论怎样,我们得到了我们要得到的结果,里面含的字体名为SimSun和NSimSun,通过以下命令为其中的SimSun字体产生font metrics文件: java org.apache.fop.fonts.apps.TTFReader -ttcname "SimSun" C:\WINNT\Fonts\simsun.ttc simsun.xml -ttcname后面指定需要从ttc文件中提取的字体名称

  • 第二步,登记上述字体

    在FOP主目录下的conf子目录下有一个userconfig.xml文件,为了方便,我们将它和上一步产生的simsun.xml,simkai.xml都拷贝到与我们的演示程序同一目录下。在userconfig.xml的最后几行有一个<fonts></fonts>标记区,我们在其中加入以下项:

    <font metrics-file="simsun.xml" kerning="yes" 
    embed-file="c:\WINNT\fonts\simsun.ttc">
        <font-triplet name="mysimsun" style="normal" 
        weight="normal"/>
     </font>
     <font metrics-file="simkai.xml" kerning="yes" 
     embed-file="c:\WINNT\fonts\simkai.ttf">
        <font-triplet name="mysimkai" style="normal" 
        weight="normal"/>
     </font>
    

    其中metrics-file里可以设相对路径或绝对路径(因为我们这里在同一目录下,所以只需写文件名即可),font-triplet里的name可以自己自由设定,并不要求与字体名一样。设定这个名字后,在fo里就只能通过这个名字引用这个字体。

    为了演示中文显示,范例simplecn.fo文件为

    <?xml version="1.0" encoding="gb2312"?>
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
      <fo:layout-master-set>
        <fo:simple-page-master master-name="simple"
                      page-height="29.7cm" 
                      page-width="21cm"
                      margin-top="1cm" 
                      margin-bottom="2cm" 
                      margin-left="2.5cm" 
                      margin-right="2.5cm">
          <fo:region-body margin-top="3cm"/>
          <fo:region-before extent="3cm"/>
          <fo:region-after extent="1.5cm"/>
        </fo:simple-page-master>
      </fo:layout-master-set>
      <fo:page-sequence master-name="simple">
        <fo:flow flow-name="xsl-region-body">
          <fo:block font-size="18pt" 
                font-family="mysimsun" 
                line-height="24pt"
                text-align="center"
                padding-top="3pt">
                这是宋体
          </fo:block>
          <fo:block font-size="18pt" 
                font-family="mysimkai" 
                line-height="24pt"
                text-align="center"
                padding-top="3pt">
                这是楷体
          </fo:block>
        </fo:flow>
      </fo:page-sequence>
    </fo:root>
    

    上述fo文件使用两种字体分别显示一行文字,注意在<fo:block>的属性中的font-family被我们设成userconfig.xml中相应的名字。

    由于需要读入userconfig.xml来得到字体信息,程序主体修改如下:

    Driver driver = new Driver();
    driver.setInputSource(new InputSource (args[0]));
    driver.setOutputStream(new FileOutputStream(args[1]));
    driver.setRenderer(Driver.RENDER_PDF);
    //读入配置(在Options的构造函数中完成)
    Options options = new Options(new File("userconfig.xml"));
    driver.run();

    这里在run之前一行读入配置(产生的Options的实例在以后没有用处),执行结果为:




总结

FOP从技术上说无疑是一个非常优秀的产品,但是目前它对用户的开发支持显然很欠缺。FOP的开发小组也意识到了这个问题,他们允诺在将来会建立一个专门的Web站点以及丰富它的文档。如果现在就想使用更方便的产品的话,你也可以考虑一些商用产品,如RenderX和X2P。

另外需要注意的是,今年8月推出的FOP 0.20.1版本非常的不好,不但一些范例无法运行,而且附带的源代码有若干错误,而这个9月29日推出的0.20.2RC版本有极大的改进,建议大家尽快升级到这个版本。


参考资料

学习

获得产品和技术

  • IBM 试用版软件:使用 IBM 试用版软件构建您的下 一个开发项目,这些试用版软件可直接从 developerWorks 下载获得。

讨论

关于作者

马路,2000级清华大学计算机系研究生,目前在清华大学Java应用技术实验室学习。E-mail: stevema@263.net

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=XML
ArticleID=21500
ArticleTitle=如何在程序中嵌入 FOP
publish-date=11012001
author1-email=stevema@263.net
author1-email-cc=stevema@263.net

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。