XQuery/XSL-FO 表格
外观
< XQuery
您希望能够创建适合书籍出版的高质量表格输出。
为了实现这一目标,我们将把 XML 转换为 XSL-FO 表格。与 HTML 不同,XML-FO 允许您创建文本流,并且您可以设置有关对象跨越页面边界的方式的规则。
这是一个示例 XML 文件,其中包含一个有两列的表格。
<table heading="Department Phone Extensions">
<Person>
<Name>John Doe</Name>
<Extension>1234</Extension>
</Person>
<Person>
<Name>Sue Smith</Name>
<Extension>5678</Extension>
</Person>
<Person>
<Name>John Doe</Name>
<Extension>1234</Extension>
</Person>
<Person>
<Name>Sue Smith</Name>
<Extension>5678</Extension>
</Person>
<Person>
<Name>John Doe</Name>
<Extension>1234</Extension>
</Person>
<Person>
<Name>Sue Smith</Name>
<Extension>5678</Extension>
</Person>
<Person>
<Name>John Doe</Name>
<Extension>1234</Extension>
</Person>
<Person>
<Name>Sue Smith</Name>
<Extension>5678</Extension>
</Person>
<Person>
<Name>John Doe</Name>
<Extension>1234</Extension>
</Person>
<Person>
<Name>Sue Smith</Name>
<Extension>5678</Extension>
</Person>
<Person>
<Name>John Doe</Name>
<Extension>1234</Extension>
</Person>
<Person>
<Name>Sue Smith</Name>
<Extension>5678</Extension>
</Person>
<Person>
<Name>John Doe</Name>
<Extension>1234</Extension>
</Person>
<Person>
<Name>Sue Smith</Name>
<Extension>5678</Extension>
</Person>
<Person>
<Name>John Doe</Name>
<Extension>1234</Extension>
</Person>
<Person>
<Name>Sue Smith</Name>
<Extension>5678</Extension>
</Person>
<Person>
<Name>John Doe</Name>
<Extension>1234</Extension>
</Person>
<Person>
<Name>Sue Smith</Name>
<Extension>5678</Extension>
</Person>
<Person>
<Name>John Doe</Name>
<Extension>1234</Extension>
</Person>
<Person>
<Name>Sue Smith</Name>
<Extension>5678</Extension>
</Person>
<Person>
<Name>John Doe</Name>
<Extension>1234</Extension>
</Person>
<Person>
<Name>Sue Smith</Name>
<Extension>5678</Extension>
</Person>
</table>
我们希望这个 XML 文件以两列呈现,第一列包含姓名,第二列包含电话分机号。它应该看起来像这样。
姓名 | 分机号 |
---|---|
John Doe | 1234 |
Sue Smith | 5678 |
以下是您需要创建表格的 XML-FO 布局的核心(不控制列宽)。
<fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:block font-size="14pt" padding="10px" font-family="Verdana">Department Phone Extensions</fo:block>
<fo:block font-size="10pt">
<fo:table border="solid" border-collapse="collapse">
<fo:table-header>
<fo:table-row space-after="10px">
<fo:table-cell>
<fo:block font-weight="bold">Name</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block font-weight="bold">Extension</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-header>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block>John Doe</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>1234</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>John Doe</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>1234</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>John Doe</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>1234</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>John Doe</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>1234</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>John Doe</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>1234</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>John Doe</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>1234</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>John Doe</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>1234</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>John Doe</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>1234</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>John Doe</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>1234</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>John Doe</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>1234</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>John Doe</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>1234</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>John Doe</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>1234</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>John Doe</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>1234</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>John Doe</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>1234</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>John Doe</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>1234</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block>Sue Smith</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>5678</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
</fo:block>
注意:此示例应移至有关 XSLT 的书籍中。应使用 XQuery 类型切换转换来执行此操作。
我们可以使用 XSLT 脚本将 XML 结构转换为 XSL-FO。此通用脚本仅要求 XML 表格的根名为 table 并且具有 heading 属性。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fo="http://www.w3.org/1999/XSL/Format"
exclude-result-prefixes="xs" version="2.0">
<xsl:template match="/table">
<fo:block>
<fo:block font-size="14pt" padding="10px" font-family="Verdana">
<xsl:value-of select="@heading"/>
</fo:block>
<fo:block font-size="10pt">
<fo:table border="solid" border-collapse="collapse" >
<fo:table-header>
<fo:table-row>
<xsl:for-each select="*[1]/*">
<fo:table-cell>
<fo:block font-weight="bold">
<xsl:value-of select="name(.)"/>
</fo:block>
</fo:table-cell>
</xsl:for-each>
</fo:table-row>
</fo:table-header>
<fo:table-body>
<xsl:apply-templates select="*"/>
</fo:table-body>
</fo:table>
</fo:block>
</fo:block>
</xsl:template>
<xsl:template match="*">
<fo:table-row>
<xsl:for-each select="*">
<fo:table-cell>
<fo:block>
<xsl:value-of select="."/>
</fo:block>
</fo:table-cell>
</xsl:for-each>
</fo:table-row>
</xsl:template>
</xsl:stylesheet>
最后,我们可以使用 XQuery 脚本生成完整的 XSL-FO 文档并将其呈现为 PDF。我们使用 XSLT 来转换表格,然后将该 XSL-FO 片段嵌入 XSL-FO 主模板中,然后将其呈现为 PDF 并流式传输二进制文档。当然,还有其他方法来组装完整的 XSLT-FO 文档。
xquery version "1.0";
import module namespace xslfo="http://exist-db.org/xquery/xslfo";
import module namespace transform="http://exist-db.org/xquery/transform";
declare namespace fo="http://www.w3.org/1999/XSL/Format";
let $table :=
<table heading="Department Phone Extensions">
<Person>
<Name>John Doe</Name>
<Extension>1234</Extension>
</Person>
<Person>
<Name>Doe John</Name>
<Extension>4321</Extension>
</Person>
<Person>
<Name><span style="color: #f00;">Sue Smith</span></Name>
<Extension>5678</Extension>
</Person>
</table>
let $table-fo := transform:transform($table,doc("/db/Wiki/eXist/xsl-fo/table2fo.xsl"),())
let $fo :=
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="my-page">
<fo:region-body margin="1in"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="my-page">
<fo:flow flow-name="xsl-region-body">
<fo:block>
{$table-fo}
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
let $pdf := xslfo:render($fo, "application/pdf", ())
return
response:stream-binary($pdf, "application/pdf", "output.pdf")
作为另一个示例,以下 XQuery 选择所有员工并将它们呈现为 PDF 表格
xquery version "1.0";
import module namespace xslfo="http://exist-db.org/xquery/xslfo";
import module namespace transform="http://exist-db.org/xquery/transform";
declare namespace fo="http://www.w3.org/1999/XSL/Format";
let $table :=
<table heading="Employees">
{//Emp}
</table>
let $table-fo := transform:transform($table,doc("/db/Wiki/eXist/xsl-fo/table2fo.xsl"),())
let $fo :=
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="my-page">
<fo:region-body margin="1in"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="my-page">
<fo:flow flow-name="xsl-region-body">
<fo:block>
{$table-fo}
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
let $pdf := xslfo:render($fo, "application/pdf", ())
return
response:stream-binary($pdf, "application/pdf", "output.pdf")