级别: 初级 Rodolfo M. Raya (rmraya@maxprograms.com), Socio gerente, Maxprograms
2001 年 11 月 01 日 不同于大多数的 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。我已经使用了几次,并且喜欢它组织我的工作的方式。(请参阅
参考资料来得到 OASIS 网站的链接)。看过我用 DocBook 写的技术材料的人从来没有意识到我使用了 XML。他们收到的打印小册子创建过程如下:首先用 Norman Walsh 提供的样式表生成 FO 文件,然后由 Fop(Apache 的 FO 处理器)转换成常规的 PDF 文件。
在我继续以前,我必须说明的是许多人相信在 XML 文档中包含格式信息本质上与 XML 的基本点相抵触。从某种意义上说他们是对的:XML 被设计作为一种不受格式干扰的数据交换机制。但是上面提到过,FO 属于另一种称为 XSL 的技术,而 XSL同样使用 XML 格式。我没有看出这种混合有什么麻烦。将 XSL-FO 视作用于布局描述的专门词汇表 ― 恰如其份。
FO 示例
在这一部分里,我向您演示如何编写一个简单的 FO 文档。如果您打算掌握 FO,您应该自己学习如何使用构成 XSL-FO 的 56 个不同对象。(试着链接到
参考资料中的
XML Bible第 18 章。)
如何编写 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 转换到 HTML 的演示,请参阅 Doug Tidwell 的
XSL Formatting Objects (XSL-FO) basics 和 XSL-FO advanced techniques。
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 教程。我仅仅在样本代码中使用了几个的格式化对象,并且仅仅显示了它们特性的一小部分。在
参考资料部分,您会找到指向很好的 FO 教程的链接。学习 XSL-FO 的基础知识不需要太多时间。事实上,我在 Web 上搜索信息的时间多于花在理解主题基础知识上的时间。
参考资料
关于作者  | 
|  | Rodolfo Raya 是 Maxprograms 的顾问、开发人员以及合伙人,他处理所有能使 IT 生动有趣的东西。本文是献给 Santiago,他的大儿子,他刚开始学习阅读并且对 XML 也丝毫不了解。可以通过
rmraya@maxprograms.com与 Rodolfo Raya 联系。
|
对本文的评价
|