使用单个 XSLT 样式表发布 HTML 和 PDF 格式的 XML 数据

轻松且快速地将 XML 数据转换为 HTML 和 PDF

学习如何使用 css2xslfo 实用工具在 HTML 和 PDF 中发布 XML 文档。

Claudius Teodorescu, XML Consultant, 独立作家

Photo of Claudius TeodorescuClaudius Teodorescu is an XML consultant based in Bucharest, Romania. He has more than 7 years of experience with XML, XForms, XPath, XSLT, and XSD. You can contact him at claudius.teodorescu@gmail.com.



2012 年 1 月 30 日

前提条件

熟悉 XML 和其他 W3C 标准非常有用。要运行本文中的示例,需要安装 eXist XML 数据库及其用于数字发布的 XQuery 扩展。请参见 参考资料

存储数据,比如,存储为 XForms/REST/XQuery [XRX] 架构的一部分(参见 参考资料)在如今很常见。您可以查询、检索以这种方式存储的数据并将其序列化为想要的格式。对于 Web 应用程序,开发人员可能希望允许用户以 HTML 格式(以便在其 Web 浏览器中查看)或以 PDF 文件的形式(以便下载供以后使用)检索数据。

本文介绍如何借助一个基于 CSSToXSLFO 工具的 XQuery 扩展函数,将 XML 数据转换为 HTML,从该 HTML 转换为 XSL-FO,以及从 XSL-FO 转换为 PDF(参见 参考资料)。

将 XML 数据转换为其他格式

常用缩略语

  • CSS:级联样式表
  • HTTP:超文本传输协议
  • JAR:Java 存档文件
  • LDAP:轻型目录访问协议
  • SQL:结构化查询语言
  • W3C:万维网联盟
  • XSL-FO:可扩展样式表语言格式对象
  • XSLT:可扩展样式表语言转换

通常,您需要两个 XSL 样式表来将数据从 XML 转换为 HTML 和 XSL-FO:一个将 XML 转换为 HTML,另一个 XSL-FO 样式表将 HTML 转换为 XSL-FO 文档,然后可以使用 XSL-FO 处理器将该文档转换为 PDF。这个过程表明,在以 HTML 和 PDF 格式生成报告的 Web 应用程序等环境中,您必须编写一个新 XSLT 样式表来将数据转换为 HTML,然后编写、调试和维护相应的 XSL-FO 样式表。这些样式表可能很难掌握,而且 XSL-FO 也不那么容易使用。幸运的是,因为报告不需要很复杂,所以您可以在 CSS 文件中轻松表达布局。然后,可以使用 CSSToXSLFO 实用工具进一步处理 CSS 文件,该实用工具只需少量编码即可生成 XSL-FO 文档。

这个过程和其他类似场景是本文所提供方法的完美用例,即,编写一个将 XML 转换为 HTML 的 XSLT 样式表,然后再向其添加些额外的 CSS 指令,以便它可将 HTML 转换为 XSL-FO,然后再转换为 PDF。


CSSToXSLFO 实用工具

CSSToXSLFO 实用工具允许将 XML 文档连同一个 CSS version 2 (CSS2) 样式表转换为 XSL-FO 文档。为了使用此实用工具,我为 eXist XML 数据库开发了一个 XQuery 扩展函数,作为 XQuery 扩展模块中用于数字发布的一部分。

此实用工具可处理大部分 CSS2 规范。为了处理特定的 XSL-FO 功能,它提供了通常被浏览器忽略的多个 CSS 扩展指令。可在 CSS 样式表的 @media 打印部分的 @page 规则中使用这些属性。这些属性与页面区域、页码、引用、引导符、命名字符串、连字符、脚注、外部图形和外部元素相关。一定要查看 CSSToXSLFO 实用工具的收藏(参见 参考资料),了解该工具的更多信息和完善您设计的 XSLT 样式表的技巧。


eXist XML 数据库

eXist-db 是一个开源的数据库管理系统,完全使用 XML 技术构建。除了其他标准,它还支持 XQuery、XPath 和 XSLT。eXist 依据 XML 数据模型来存储数据,高度遵守 XQuery 标准。存储的数据使用 XQuery 通过基于索引的方式来处理。该数据库还有一个基于 Apache Lucene 的全文索引。

eXist 的 XQuery 引擎是可扩展的,所以 eXist 拥有各种各样的 XQuery 扩展模块。这些模块提供了 XQuery 扩展功能,比如:

  • 全局键-值缓存
  • 各种压缩操作
  • 对日期和时间类型的更多操作
  • 对文件和目录的各种操作
  • HTTP 请求(一个 XPath 模块)
  • 对存储在数据库中的图像的操作,包括检索图像维度,创建缩略图和调整图像大小
  • 访问和操作基于 Java™ 命名和目录接口的目录,比如 LDAP
  • 发送文本或 HTML 电子邮件
  • 计划作业和操作现有作业
  • 对关系数据库管理系统执行 SQL 操作
  • 确定 XML 节点之间的区别
  • XSL-FO 呈现
  • XProc 功能
  • 加密操作

eXist 和 CSSToXSLFO 都使用 Java 语言编写。在编写本文时,eXist 允许您使用 Apache 格式对象处理器 (Apache Formatting Objects, FOP) 或 RenderHouse XEP 作为 XSL-FO 处理器。请访问 eXist 网站,了解安装数据库的指令,以方便运行本文的示例。

eXist 数字发布模块

eXist 数字发布模块目前正在开发中,在未来将包含更多函数。现在它拥有 html-to-xslfo() 函数,该函数有助于实现本文提供的方法。

此模块背后的意图是为数字发布所需的所有 XQuery 扩展函数提供单一的来源,包括各种格式之间的转换,比如 DocBook、Open XML、DOC、DOCX、.html、PDF、TXT、RTF、PPT、PPTX 和 CSV。要在 eXist 内安装此模块:

  1. 下载 eXist 数字发布模块的 JAR 文件,将其复制到 $EXIST_HOME/lib/extensions 中。
  2. 下载 css2xslfo1_6_2.jar,将其复制到 $EXIST_HOME/lib/user 中。
  3. <module class="ro.kuberam.kPub.kPubModule" uri="http://kuberam.ro/k-Pub"/> 添加到 $EXIST_HOME/conf.xml 文件的内置模块部分中。

示例

本节分析 CSSToXSLFO 的用法,因为它是在 eXist 用于数字发布的 XQuery 扩展模块中实现的。对于此任务,使用 清单 1 中提供的 XML 数据,以及 下载 部分提供的代码示例中包含的 XSLT 样式表 (xml-to-html.xsl)。

备注:为了使本文更容易阅读,我没有包含所使用的 XSLT 样式表的完整内容。相反,我仅提供了那些使该样式表适合将 XML 转换为 HTML 和 PDF 的元素。

这些示例将上传到一个 eXist XML 数据库中,该数据库位于 eXist 根集合中的一个名为 html-and-pdf-single-stylesheet 的集合中,所以您可在浏览器中查看每个示例。例如,要查看示例 1,可在浏览器地址栏中键入以下地址(假设 eXist 安装在本地):

http://127.0.0.1:8080/rest/db/html-and-pdf-single-stylesheet/example%201/example1.xql

要使用 CSSToXSLFO 工具中的更多功能,您只需要 清单 2清单 3 中提供的 XQuery 代码,它们分别以 HTML 和 PDF 格式呈现代码。要获得更加完善的 PDF 文档,您必须向 XSLT 样式表的 CSS 部分添加 CSS 指令。

清单 1. 一个表示已开具发票的摘要的 XML 文档(示例代码中的文件 xml-data.xml)
<invoices-summary> 
  <invoice id=""> 
    <issue-date>2011-10-17</issue-date> 
    <amount>108</amount> 
    <vat>19.47</vat> 
    <vat-base>22</vat-base> 
    <currency>EURO</currency> 
    <customer-id>0001008</customer-id>
   </invoice> 
  <invoice id=""> 
    <issue-date>2011-10-17</issue-date> 
     <amount>40</amount> 
    <vat>7.21</vat> 
     <vat-base>22</vat-base> 
     <currency>EURO</currency> 
    <customer-id>0000017</customer-id> 
  </invoice> 
  <invoice id=""> 
    <issue-date>2011-10-17</issue-date> 
    <amount>1700</amount> 
    <vat>306.56</vat> 
    <vat-base>22</vat-base> 
    <currency>EURO</currency> 
     <customer-id>0000040</customer-id> 
  </invoice> 
</invoices-summary>

第一个示例(如 清单 2 所示)是一段 XQuery 脚本,它将 清单 1 中给出的 XML 数据转换为 HTML。该脚本使用了 eXist 的 transform:transform() 函数,后者使用一个 XSLT 样式表和(可选的)转换参数来转换 XML 数据。您可以使用 XSLT 1.0(基于 Apache Xalan)或 XSLT 2.0(可选 Saxon)编写 XSLT 样式表。

清单 2. 将 XML 数据转换为 HTML 的 XQuery 脚本(示例代码中的文件 example-01.xql)
xquery version "1.0"; 
let $xml-data := doc('/db/html-and-pdf-single-stylesheet/xml-data.xml') 
let $xslt-stylesheet := doc( '/db/html-and-pdf-single-stylesheet/xml-to-html.xsl' ) 
let $html := transform:transform($xml-data, $xslt-stylesheet, ()) 
return $html

图 1 显示了结果 HTML 文档在浏览器中的呈现效果。该 HTML 文档以一种非 serif 字体显示 3 个发票的细节摘要。(参见 图 1 和 2 中的格式化内容的文本版本。)

图 1. 转换为 HTML 的结果
该屏幕截图显示了转换为 HTML 的结果

首先,与在上一个示例中一样,将 XML 数据转换为了 HTML。结果 HTML 文档包含按要求呈现 HTML 文档所需的所有 CSS 指令,以及特定于 CSSToXSLFO 并有助于使用更复杂的 XSL-FO 功能的 CSS 扩展指令。

对于如本文中所示的简单用例,您不需要这些扩展指令。CSSToXSLFO 实用工具将 HTML 文档转换为一个 XSL-FO 文档,后者进而生成一个将非常类似于 HTML 文档的 PDF 文档。

接下来,您使用 html-to-xslfo() 函数将结果 HTML 文档转换为一个 XSL-FO 文档,然后生成一个 PDF 文档,如 清单 3 中所示。要创建 PDF,可使用 xslfo eXist 模块的 render() 函数。

清单 3. 将 XML 数据转换为 PDF 格式的 XQuery 脚本(示例代码中的文件 example-02.xql)
xquery version "1.0"; 
declare namespace xslfo="http://exist-db.org/xquery/xslfo"; 
declare namespace k-Pub="http://kuberam.ro/k-Pub"; 
let $xml-data := doc('/db/html-and-pdf-single-stylesheet/xml-data.xml') 
let $xslt-stylesheet := doc('/db/html-and-pdf-single-stylesheet/xml-to-html.xsl') 
let $html := transform:transform($xml-data, $xslt-stylesheet, ()) 
let $fo := k-Pub:html-to-xslfo($html) 
let $pdf := xslfo:render($fo, "application/pdf", ()) 
return response:stream-binary( $pdf, "application/pdf", "output.pdf" )

图 2 显示了结果 PDF 文档在浏览器中的呈现效果。该 PDF 文档以一种 serif 格式显示 3 个发票的细节摘要。(请参见 图 1 和 2 中提供的格式化内容的文本版本。)

图 2. 转换成 PDF 格式的结果
该屏幕截图显示了结果 PDF 文档

清单 4 包含以 HTML 和 PDF 格式呈现 XML 所需的 CSS 指令。为了获得一个类似的 PDF 文件,我仅添加了一个 CSS 指令,将表标题加粗。

清单 4. 将 XML 呈现为具有类似外观的 HTML 和 PDF 的 CSS 指令
body { 
    font-family: arial; 
    font-size: 12px; 
    text-align: center; 
} 
table { 
    border-collapse: collapse; 
    width: 100%; 
    border: solid black 1px; 
} 
table th, td { 
    border: solid black 1px; 
} 
@media screen { 
    body { 
        width: 570px; 
    } 
} 
@media print { 
    table th { 
        font-weight: bold; 
    } 
}

结束语

在本文中,您使用了一个简单函数来将 XML 数据转换为 HTML 和 PDF 格式,利用 CSS 语法和一些扩展指令的强大性和简单性来处理更加复杂的 XSL-FO 功能。在报告或文档样式较简单的情形中,这种方法特别有用。


下载

描述名字大小
完整代码示例html-and-pdf-single-stylesheet.zip4KB

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


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


忘记密码?
更改您的密码

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

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

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

选择您的昵称



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

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

标有星(*)号的字段是必填字段。

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

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

 


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


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=XML, Web development
ArticleID=790156
ArticleTitle=使用单个 XSLT 样式表发布 HTML 和 PDF 格式的 XML 数据
publish-date=01302012