DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> XML學習教程 >> XML詳解 >> 如何在程序中嵌入 FOP:FOP 簡介
如何在程序中嵌入 FOP:FOP 簡介
編輯:XML詳解     

 如何在程序中嵌入 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 等流行格式的功能無疑是令人興奮的。

  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文件效果如下

如何在程序中嵌入 FOP:FOP 簡介

  查看原圖(大圖)

  3. 顯示中文 
上面的演示程序段可以應付絕大部分轉換編程的需要,不過對於國內用戶來說,不可避免的需要產生中文PDF文件,讓我們把上述simple.fo的標題從"FOP 0.20.2"改成"支持中文的FOP 0.20.2",不改動程序的情況下執行結果顯示如下

如何在程序中嵌入 FOP:FOP 簡介

  查看原圖(大圖)
可以看到由於沒有加入相應的字體支持,漢字被顯示成了#。

  東方字符的顯示在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 簡介

  總結

  FOP從技術上說無疑是一個非常優秀的產品,但是目前它對用戶的開發支持顯然很欠缺。FOP的開發小組也意識到了這個問題,他們允諾在將來會建立一個專門的Web站點以及豐富它的文檔。如果現在就想使用更方便的產品的話,你也可以考慮一些商用產品,如RenderX和X2P。

  另外需要注意的是,今年8月推出的FOP 0.20.1版本非常的不好,不但一些范例無法運行,而且附帶的源代碼有若干錯誤,而這個9月29日推出的0.20.2RC版本有極大的改進,建議大家盡快升級到這個版本。


XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved