不同於大多數的 XML 文檔,它包含表示信息 ― 想要這樣的可移植文檔嗎? 本文介紹 XSL-FO(XML 樣式表語言-格式化對象,即 XML Stylesheet Language-Formatting Objects),並解釋它如何解除危機。為了演示使用 XSL-FO 的優勢,本文包含了使用 Java 和 XML 代碼實現數據庫報表系統的實現示例。 page-height="297mm" page-width="210mm" margin-left="25mm" margin-right="25mm" margin-top="27mm" margin-bottom="20mm"> margin-bottom="0mm" /> ... 注:如果您打算按本文描述的那樣使用 Fop 的話,請明確指定列寬。
本文中,我將演示為什麼當您需要使用要打印的 XML 文檔時,可以使用 XML 樣式表語言-格式化對象,也就是 XSL-FO。我將描述在特定情況下在 XML 文檔中包含格式化信息的好處。本文是對 Portable database reporting using Java and XML一文的補充,那是前段時間我為 developerWorks 寫的一篇關於使用 Java 和 XML 生成數據庫報表的文章。
格式化對象基礎
XML 被設計成一種在不同應用程序間交換數據的可移植方式;數據表示則通常留給應用程序本身。XML 文檔通常按順序描述數據,其唯一格式就是縮進。在這一部分,我們來看看 XSL-FO 作為設計用來描述文檔外觀的專門的 XML 詞匯是如何使用。我還提供了一些有關如何使用 XSL-FO 的技巧。
FO 的定義及其在 XSL 中扮演的角色
您或許已經知道,XSL 代表“可擴展樣式表語言”。在定義語言組件時,W3C 工作組明確地指定 XSL 由兩個主要部分組成:
用於轉換 XML 文檔的語言
用於指定格式化語義的 XML 詞匯表
XSL 的第一個組件是 XSL 轉換或 XSLT。第二部分被稱做 XSL-FO,或者簡單地說,格式化對象(FO)。
XSLT 通過將帶標記的數據轉換成美觀的文檔來使 XML 文檔可讀。通過使用 XSLT 處理器,應用定義在樣式表中的規則來完成文檔轉換。這種方法需要一個 XML 文檔作為源文件,需要另一個帶格式化信息(樣式表)的文檔,還需要處理器。但是如果想使用 XML 而又不想對付兩個文檔,該怎麼辦呢?答案是:在文檔中包含格式化信息。
可以使用 FO 在文檔中包含格式化信息。盡管 FO 沒有 XSLT 使用廣泛,但它同樣很重要。XSL-FO 提供了一組標記,可以用這些標記來定義文檔如何顯現給用戶。使用 FO,您可定義頁面布局,字體風格,顏色,圖像顯示和許多其它設計特性。
如果您花時間閱讀 400 多頁的 XSL-FO 規范,您也許會對 W3C 工作組定義的格式化對象數量之大感到驚訝。FO 不只局限於打印的文檔,它還向多媒體文檔敞開大門。如果閱讀 400 頁對您來講太長的話,試試 Elliote Rusty Harold 的 62 頁長的精彩文摘。
有趣的是,在 XSL 規范中,W3C 沒有包含一個可用來驗證 FO 文檔的正式認可的 DTD(文檔類型定義)。幸運的是,RenderX 提出了一個實驗性 FO DTD,它可以幫助您進行文檔驗證。
現在,您可能會想到兩個難題:什麼時候應該使用 XSL-FO?為什麼?我將探討幾種可能性。
FO 的某些使用
在開始前,我想把 XML 文檔分為兩類:
僅用於在應用程序之間交換信息的純數據文檔
供人閱讀的文檔
關於第一類,僅僅在兩個不同應用程序之間傳送數據的 XML 文檔根本不需要格式化信息。計算機程序不在乎所處理的數據的感官如何。有時甚至包含在文檔中的縮進都被認為是多余。
屬於第二類的文檔通常在閱讀前用樣式表進行轉換,並且用同一樣式表准備過的文檔看起來都很類似。但有時您不想使用樣式表,因為您希望給同一類型的對象以不同的外觀。這就是 FO 的用途:可以用 FO 作為專門的 XML 詞匯表來編寫文檔。
要使用需要的格式來編寫文檔,您可以使用眾多可用字處理應用程序中的一個。然而,請記住其中每一個都以獨有格式存儲文檔。因此我可以在 Windows 下用 Microsoft Word 編寫文檔,在 Linux 下用 StarOffice 將它打開並閱讀,但格式一定和初始時的不同。但是,如果我的文檔可以存儲為使用 FO 的 XML 文檔,那麼不管我用的是什麼應用程序,我可以保留格式信息。使用 FO 的最大好處在於:不管在什麼平台下或使用什麼應用程序,您只需使用一種文檔格式。
字處理器和 XML
通過使用 XML 存儲文檔,字處理器可以在可移植性和兼容性方面得到提高。
AbiWord 是一種小型、快速、開放源碼的字處理器,以 XML 格式存儲文本文檔。它能夠從 XSL-FO 和 DocBook 導入或導出文本。AbiWord 將文檔從它自己的格式轉換成 DocBook 或 XSL-FO 的子集,反之亦然。通過這樣做 ― 加上來自外部程序的少許調整 ― 就可以從一個文檔源得到不同的輸出。
另一個用 XML 存儲文檔的字處理程序是 StarWriter,StarOffice 和 OpenOffice 的一個組件。可以在 OpenOffice 網站下載它的 DTD。
盡管 FO 看起來是字處理程序用來存儲文檔的極佳格式,但它並不是唯一的用於文檔存儲的 XML 選項。DocBook 是一個 OASIS 作為文檔寫作標准提倡的 DTD。我已經使用了幾次,並且喜歡它組織我的工作的方式。看過我用 DocBook 寫的技術材料的人從來沒有意識到我使用了 XML。他們收到的打印小冊子創建過程如下:首先用 Norman Walsh 提供的樣式表生成 FO 文件,然後由 Fop(Apache 的 FO 處理器)轉換成常規的 PDF 文件。
在我繼續以前,我必須說明的是許多人相信在 XML 文檔中包含格式信息本質上與 XML 的基本點相抵觸。從某種意義上說他們是對的:XML 被設計作為一種不受格式干擾的數據交換機制。但是上面提到過,FO 屬於另一種稱為 XSL 的技術,而 XSL同樣使用 XML 格式。我沒有看出這種混合有什麼麻煩。將 XSL-FO 視作用於布局描述的專門詞匯表 ― 恰如其份。
FO 示例
在這一部分裡,我向您演示如何編寫一個簡單的 FO 文檔。如果您打算掌握 FO,您應該自己學習如何使用構成 XSL-FO 的 56 個不同對象。
如何編寫 FO 文檔
在前面的 developerWorks 文章中,我描述了從存儲在數據庫的數據生成可打印數據報表的過程。現在我將向您演示如何使用 XSL-FO 以避免寫一個復雜的樣式表。
在第一篇文章中,我的目的是得到可打印報表。實現的方法是:用 Fop 生成可在屏幕上閱讀或打印的 PDF 文檔,同時保持在 XML 文檔中指定的格式。
圖 1 顯示了初始報表系統圖的修改版。
圖 1. 報表系統圖
在您看到 output.fo 的地方,必須在將一個中間的 XML 文檔發送到 Fop 以前使用樣式表將它轉換到 FO。實際上我做了手腳,因為在我解釋中間文檔的頭時,我寫了 這段代碼,該代碼用稍作更改的 FO 來寫的文檔的頭:FO 文檔始終以 fo:root 作為其根元素開頭。真正的頭應該這樣:
<?XML version="1.0" encoding="utf-8"?>
<fo:root XMLns:fo="http://www.w3.org/1999/XSL/Format">
FO 文件由以下各部分組成:
一個 XML 頭和名稱空間聲明
頁面布局信息
頁眉和頁腳內容
文本內容
結束標記 ― 永遠不要忘記它們!
我了解自己,我也確信編寫 XSL 樣式表來轉換中間文檔的任務會是一個沒完沒了的故事。MXReports 的計劃包含很多今後的升級,那也意味著對程序和樣式表的大量更改。我將試著僅依靠 Fop 轉換我的中間 FO 文檔來處理這個程序。
現在知道了頭看起來應該是什麼樣子,讓我們研究如何描述頁面布局。在我的第一篇文章包含的樣本程序中,我向您演示了如何從 report.XML 檢索下列數據:
頁高度
頁寬度
頁眉高度
頁腳高度
清單 1中的示例使用下列代碼片段中的那些變量來告訴 Fop 文檔所需的頁面布局。
當您執行清單 1,輸出看起來與清單 2 相似。
清單 2. 運行清單 1 的輸出
page-height="297mm"
page-width="210mm"
margin-left="25mm"
margin-right="25mm"
margin-top="27mm"
margin-bottom="20mm">
margin-bottom="0mm" /> ...
清單 2 中的文本定義了我想要一個標准 A4 頁大小(210mm x 297mm)和帶指定的頁邊距,該頁邊距由從 XML 報表定義中抽取的數據確定。頁面有五個部分,或 區域(regions):region-body、region-before、region-after、region-start 和 region-end。 圖 2顯示頁面中每個區域的位置。
圖 2. 頁面布局和區域位置
在本文所帶的 zip 文件中中,您可以找到 mxreports.Java,它包含了所有的樣本代碼。下載該樣本代碼並查看方法 writeHeader() 和 writeDetails() 。
在 writeHeader() 中,您將看到如何描述頁面布局以及如何將頁眉和頁腳內容定義為靜態對象。
方法 writeDetails() 將報表內容定義為類似 Html 風格的表。我在這個應用程序中使用表是因為細節區域包含固定數目的元素,這些元素應該為數據集中每行打印一次。換句話說,報表由一個表組成,這個表的行數和數據集的記錄數相同,而列數與細節區域中定義的元素數相同。但是請記住常規的 FO 文件通常由塊和內聯對象組成。
清單 3中的樣本演示了如何使用 FO 來定義有兩列的表。
注:如果您打算按本文描述的那樣使用 Fop 的話,請明確指定列寬。
如果曾經使用 Html 編寫過表的話,理解表對象的基礎就會容易些。請看清單 3。
表 1. FO 和 Html 表等同標記的比較
FO 標記 Html 標記 fo:table-body table fo:table-row tr fo:table-cell td如何處理 FO 文件並使其有用
到現在為止,您應該至少理解什麼是 FO 文件以及如何生成它。可能您還想知道如何使文件具有可讀性並且無標記。
目前,僅有少量的可選替代方法可以使 XSL-FO 文件有用。將 FO 文件轉換成可讀格式的最好選項是:
可移植文檔格式(Portable Document Format)
RTF(Rich Text Format)格式
網頁(Html)
您可以使用 Fop 或 XEP 生成 PDF 文件,Fop 是一個作為 apache XML 項目開發的免費開放源碼工具,而 XEP 是一個來自 RenderX 的商業產品。
在浏覽 Fop 的相關新聞組時,我發現了 StandaloneConverter,這是一個由 Bertrand Delacretaz 開發的實驗性的獨立的 FO 到 RTF 轉換器。我能夠編譯並運行該程序,您將在壓縮文件中找到 currency.fo 的 RTF 版本。由該工具生成的 RTF 文件不保留 currency.fo 中指定的頁邊距,但它提供了一個部署可編輯文檔的極佳方法。
正如本文前面所說的那樣,FO 文件是常規 XML 文件,您可以用任何 XSLT 工具(如 Xalan)將它從 FO 轉換到 Html。
FO 的現在和將來
隨著 XML 越來越受歡迎,我相信幾年以內 XML 將成為存儲和分發文檔的標准格式。很多軟件公司正在更新他們的產品以支持 XML。它們中的大部分使用專有的 XML 格式存儲文檔,但有些公司已經開始發布它們使用的 DTD。DTD 發布是對使用 XSLT 以達到異類系統兼容性的一個直接要求。
Adobe 的可移植文檔格式(PDF)標准得到全世界范圍的認可,使用 Fop 生成 PDF 文檔正變得非常流行。Fop 只用於 XSL-FO 文檔。隨著更多的人使用它,FO 作為表示描述的專門的詞匯表,Fop 可能會越來越多地使用它。
我並不認為 XSL-FO 會作為文檔編寫的已建立標准來使用,但其它 XML 詞匯表(象 DocBook)的一般化使用和 Java XSLT 工具的高可用性將吸引越來越多的人將 FO 作為輔助技術來使用。
結束語
我在本文中描述了 XSL-FO,這種可以用來創建包含格式化信息的 XML 文檔的專門 XML 詞匯表。我還提到了字處理器和使用 XML 存儲文檔的重要性的原因。我詳述了使用 Java 生成 FO 文件的方法。最後,我講解了轉換 FO 文件的選項。
本文不打算成為詳盡的 XSL-FO 教程。我僅僅在樣本代碼中使用了幾個的格式化對象,並且僅僅顯示了它們特性的一小部分。學習 XSL-FO 的基礎知識不需要太多時間。事實上,我在 Web 上搜索信息的時間多於花在理解主題基礎知識上的時間。