XSL-FO 教程

XSL-FO 教程

XSL-FO(XSL Formatting Objects,XSL 格式化对象)是 W3C 制定的 XML 文档格式化标准,用于将 XML 内容转换为 PDF、打印文档等物理格式。它是 XSL 家族的第二个语言(第一个是 XSLT 转换语言)。

XSL 家族

语言作用
XSLT将 XML 转换为其他格式(XML/HTML/文本)
XPath在 XML 中导航与查询节点
XSL-FO将 XML 格式化为 PDF/打印文档

工作原理

XML 文档
   ↓ XSLT 转换
XSL-FO 文档
   ↓ FO 处理器(如 Apache FOP)
PDF / 打印输出

XSL-FO 能做什么

  • 生成分页的 PDF 文档
  • 精确控制页面布局(页眉页脚、页码)
  • 格式化表格、列表、图文混排
  • 支持字体、颜色、边框等排版属性

第一个 XSL-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="page">
      <fo:region-body/>
    </fo:simple-page-master>
  </fo:layout-master-set>
  <fo:page-sequence master-reference="page">
    <fo:flow flow-name="xsl-region-body">
      <fo:block>Hello XSL-FO!</fo:block>
    </fo:flow>
  </fo:page-sequence>
</fo:root>

XSLFO 简介

XSLFO 简介

1. 什么是 XSL-FO

XSL-FO 是一种基于 XML 的标记语言,描述文档应该如何打印和显示。它定义了格式化对象的集合,每个对象对应文档的一个元素(页面、块、表格等)。

2. 历史背景

  • 1998 年 W3C 开始制定 XSL 规范
  • 2001 年发布 XSL 1.0 推荐标准(含 XSLT 与 XSL-FO)
  • 2012 年发布 XSL-FO 2.0 草案
  • Apache FOP、Antenna House、RenderX 是主要实现

3. 核心概念

  • 格式化对象(FO):描述输出的 XML 元素,前缀 fo:
  • 页面主控:定义页面尺寸、边距、页眉页脚区域
  • 页序列:一组连续页面,应用相同主控
  • 内容流:实际内容被分配到页面区域

4. 典型流程

# 数据(XML)
<book><title>XSL-FO 入门</title></book>

# 样式(XSLT 生成 FO)
<fo:block><xsl:value-of select="title"/></fo:block>

# 处理(FOP)
fop -xml book.xml -xsl style.xsl -pdf book.pdf

5. 与其他技术对比

技术用途
CSS + HTMLWeb 屏幕显示
XSL-FOPDF 与打印(分页排版)
LaTeX学术论文排版
PDF 直接生成程序化控制(如 iText)

XSLFO 文档

XSLFO 文档

1. 文档结构

<?xml version="1.0" encoding="UTF-8"?>

<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">

  <!-- 1. 页面布局定义 -->
  <fo:layout-master-set>
    <fo:simple-page-master master-name="A4">
      <fo:region-body margin="2cm"/>
    </fo:simple-page-master>
  </fo:layout-master-set>

  <!-- 2. 页面序列(内容) -->
  <fo:page-sequence master-reference="A4">
    <fo:flow flow-name="xsl-region-body">
      <fo:block>内容</fo:block>
    </fo:flow>
  </fo:page-sequence>

</fo:root>

2. 文档组成元素

  • fo:root:文档根元素
  • fo:layout-master-set:包含所有页面主控定义
  • fo:page-sequence:一个文档由多个页序列组成
  • fo:flow:页序列内的内容流
  • fo:block:块级元素(段落、标题等)
  • fo:inline:行内元素

3. 命名空间

<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<!-- 所有格式化对象必须使用 fo: 前缀 -->

4. 简单完整示例

<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
  <fo:layout-master-set>
    <fo:simple-page-master master-name="main"
        page-width="21cm" page-height="29.7cm">
      <fo:region-body margin="2.5cm"/>
    </fo:simple-page-master>
  </fo:layout-master-set>

  <fo:page-sequence master-reference="main">
    <fo:flow flow-name="xsl-region-body">
      <fo:block font-size="24pt" text-align="center">
        报告标题
      </fo:block>
      <fo:block space-before="12pt">
        第一段正文内容...
      </fo:block>
    </fo:flow>
  </fo:page-sequence>
</fo:root>

XSLFO 区域

XSLFO 区域

1. 页面区域模型

XSL-FO 的每个页面被划分为几个区域:

┌─────────────────────────────┐
│  region-before(页眉)        │
├─────────────────────────────┤
│ region-start │ region-body  │ region-end
│   (左页边)   │  (主体内容)  │   (右页边)
├─────────────────────────────┤
│  region-after(页脚)         │
└─────────────────────────────┘

2. 定义区域

<fo:simple-page-master master-name="report"
    page-width="21cm" page-height="29.7cm">

  <!-- 主体区域(正文) -->
  <fo:region-body margin="2cm 1.5cm 2cm 1.5cm"/>

  <!-- 页眉区域(上方) -->
  <fo:region-before extent="1.5cm">
    <fo:block text-align="end">公司内部资料</fo:block>
  </fo:region-before>

  <!-- 页脚区域(下方) -->
  <fo:region-after extent="1cm">
    <fo:block text-align="center">第 X 页</fo:block>
  </fo:region-after>
</fo:simple-page-master>

3. flow-name 对应关系

区域flow-name
主体xsl-region-body
页眉xsl-region-before
页脚xsl-region-after
左侧xsl-region-start
右侧xsl-region-end

4. 向区域填充内容

<fo:page-sequence master-reference="report">

  <!-- 页脚内容 -->
  <fo:static-content flow-name="xsl-region-after">
    <fo:block>
      第 <fo:page-number/> 页,共 <fo:page-number-citation ref-id="last"/> 页
    </fo:block>
  </fo:static-content>

  <!-- 主体内容 -->
  <fo:flow flow-name="xsl-region-body">
    <fo:block>正文...</fo:block>
  </fo:flow>
</fo:page-sequence>

5. 区域样式属性

<fo:region-body
    margin="2cm"                    <!-- 边距 -->
    background-color="#f5f5f5"      <!-- 背景色 -->
    overflow="auto"/>               <!-- 溢出处理 -->

XSLFO 输出

XSLFO 输出

1. 输出格式

XSL-FO 本身是 XML,必须通过格式化处理器(FO Processor)转换为最终格式:

处理器输出说明
Apache FOPPDF、PS、PNG、TXT开源免费,最常用
RenderX XEPPDF、PS、SVG商业,支持完整规范
Antenna HousePDF、SVG、XPS商业,东亚文字支持好
ibexPDF轻量商业处理器

2. Apache FOP 使用

# 下载 fop 后命令行转换
fop -fo report.fo -pdf report.pdf

# 从 XML+XSLT 直接生成
fop -xml data.xml -xsl style.xsl -pdf report.pdf

# 输出 PNG
fop -fo report.fo -png report.png

3. Java 程序调用

import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.Fop;
import java.io.FileOutputStream;

FopFactory fopFactory = FopFactory.newInstance();
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out);
Transformer transformer = TransformerFactory.newInstance().newTransformer(new StreamSource(styleXsl));
Source src = new StreamSource(dataXml);
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);

4. 检查输出质量

  • 字体嵌入:确认 PDF 字体可移植
  • 分页正确:表格跨页、标题跟随
  • 中文显示:配置中文字体(fop 默认不含中文字体)

5. 中文配置示例

<!-- fop.xconf 配置字体 -->
<fonts>
  <font kerning="yes">
    <font-triplet name="STSong" style="normal" weight="normal"/>
    <font-triplet name="STSong" style="normal" weight="bold"/>
  </font>
</fonts>

<!-- FO 中引用 -->
<fo:block font-family="STSong">中文内容</fo:block>

XSLFO 流

XSLFO 流

1. 什么是流(Flow)

流(fo:flow)是页序列中的内容容器,内容按顺序从流中流向页面区域,像水流一样自动分页填充。

2. 基本结构

<fo:page-sequence master-reference="main">

  <!-- 静态内容(页眉页脚,不流动) -->
  <fo:static-content flow-name="xsl-region-before">
    <fo:block>页眉文字</fo:block>
  </fo:static-content>

  <!-- 流内容(自动分页) -->
  <fo:flow flow-name="xsl-region-body">
    <fo:block>第一页内容...</fo:block>
    <fo:block>自动流动到下一页</fo:block>
  </fo:flow>
</fo:page-sequence>

3. 流动与分页

<fo:flow flow-name="xsl-region-body">
  <!-- 内容超过页面高度时自动分页 -->
  <fo:block>内容1</fo:block>
  <fo:block break-before="page">强制新页</fo:block>
  <fo:block keep-with-next.within-page="always">与下一块保持同页</fo:block>
</fo:flow>

4. 分页控制属性

break-before="page"       <!-- 块前分页 -->
break-after="page"        <!-- 块后分页 -->
keep-with-next="always"   <!-- 与下一个保持同页 -->
keep-together="always"    <!-- 块内不分页 -->
orphans="2"               <!-- 页首最少行数 -->
widows="2"                <!-- 页尾最少行数 -->

5. 流内容综合示例

<fo:flow flow-name="xsl-region-body">
  <fo:block font-size="18pt" font-weight="bold"
      space-after="10pt" keep-with-next.within-page="always">
    第一章 概述
  </fo:block>

  <fo:block text-indent="2em" text-align="justify">
    这是正文段落。内容足够长时会自动分页,
    段落不会在中间被截断(widows/orphans 控制)。
  </fo:block>

  <fo:block break-before="page">
    这是新的一页开始的内容。
  </fo:block>
</fo:flow>

XSLFO 页面

XSLFO 页面

1. 页面主控(layout-master-set)

<fo:layout-master-set>

  <!-- 单页主控 -->
  <fo:simple-page-master master-name="A4-page"
      page-width="210mm" page-height="297mm"
      margin-top="25mm" margin-bottom="25mm"
      margin-left="20mm" margin-right="20mm">
    <fo:region-body margin-top="15mm"/>
  </fo:simple-page-master>

  <!-- 双面主控(左页/右页不同) -->
  <fo:page-sequence-master master-name="book">
    <fo:single-page-master-binding master-reference="right"/>
    <fo:repeatable-page-master-alternatives>
      <fo:conditional-page-master-reference
          odd-or-even="odd" master-reference="right"/>
      <fo:conditional-page-master-reference
          odd-or-even="even" master-reference="left"/>
    </fo:repeatable-page-master-alternatives>
  </fo:page-sequence-master>
</fo:layout-master-set>

2. 页面尺寸

# 常见尺寸
A4:   210mm × 297mm
A5:   148mm × 210mm
Letter: 8.5in × 11in
Legal: 8.5in × 14in

# 自定义
page-width="10cm" page-height="15cm"

3. 使用页面主控

<!-- 用 master-reference 引用 -->
<fo:page-sequence master-reference="A4-page">
  ...
</fo:page-sequence>

4. 页号与引用

<!-- 当前页码 -->
<fo:page-number/>

<!-- 引用某元素的页码 -->
<fo:block id="last-page">最后一页内容</fo:block>
...
第 <fo:page-number-citation ref-id="last-page"/> 页

<!-- 总页数(常见技巧:标记末元素) -->
共 <fo:page-number-citation ref-id="last"></fo:page-number-citation> 页

5. 页面属性速查

page-width / page-height   页面尺寸
margin-top/bottom/left/right  页面边距
master-name                主控名称
flow-name                  内容流名称
reference-orientation      旋转(90/180/270)
page-position              页面位置(first/last/rest)

XSLFO 块

XSLFO 块

1. 块元素(fo:block)

fo:block 是 XSL-FO 中最基本的布局元素,类似 HTML 的 div/p,生成一个独立的矩形区域。

2. 基础示例

<fo:flow flow-name="xsl-region-body">

  <!-- 标题 -->
  <fo:block font-size="20pt" font-weight="bold"
      space-before="12pt" space-after="6pt">
    大标题
  </fo:block>

  <!-- 普通段落 -->
  <fo:block font-size="10.5pt" line-height="1.5"
      text-align="justify" text-indent="2em">
    段落文本...
  </fo:block>

  <!-- 带边框背景 -->
  <fo:block border="1pt solid #ccc"
      padding="6pt" background-color="#f9f9f9">
    提示框内容
  </fo:block>

  <!-- 居中 -->
  <fo:block text-align="center">居中内容</fo:block>
</fo:flow>

3. 常用属性

font-family      字体
font-size        字号
font-weight      bold/normal
font-style       italic/normal
color            文字颜色
background-color 背景色
text-align       start/center/end/justify
text-indent      首行缩进
line-height      行高
space-before     上间距
space-after      下间距
margin-*         外边距
padding-*        内边距
border-*         边框
keep-with-next   与下块同页
keep-together    块内不分页
break-before     前分页

4. 行内元素(fo:inline)

<fo:block>
  普通文字,<fo:inline font-weight="bold" color="red">加粗红字</fo:inline>,
  继续普通文字,<fo:inline font-style="italic">斜体</fo:inline>。
</fo:block>

5. 列表块

<fo:list-block space-after="12pt">
  <fo:list-item>
    <fo:list-item-label>
      <fo:block>•</fo:block>
    </fo:list-item-label>
    <fo:list-item-body>
      <fo:block>列表项一</fo:block>
    </fo:list-item-body>
  </fo:list-item>
</fo:list-block>

XSLFO 列表

XSLFO 列表

1. 列表结构

<fo:list-block>
  <fo:list-item>
    <fo:list-item-label end-indent="label-end()">
      <fo:block>1.</fo:block>
    </fo:list-item-label>
    <fo:list-item-body start-indent="body-start()">
      <fo:block>第一项内容</fo:block>
    </fo:list-item-body>
  </fo:list-item>

  <fo:list-item>
    <fo:list-item-label end-indent="label-end()">
      <fo:block>2.</fo:block>
    </fo:list-item-label>
    <fo:list-item-body start-indent="body-start()">
      <fo:block>第二项内容</fo:block>
    </fo:list-item-body>
  </fo:list-item>
</fo:list-block>

2. 列表属性

<fo:list-block
    start-indent="10pt"      <!-- 整体缩进 -->
    provisional-label-separation="6pt"  <!-- 标签与内容间距 -->
    provisional-distance-between-starts="1.5em">  <!-- 标签宽度 -->
  ...
</fo:list-block>

3. 与 XSLT 配合生成列表

<xsl:for-each select="item">
  <fo:list-item>
    <fo:list-item-label end-indent="label-end()">
      <fo:block><xsl:value-of select="position()"/>.</fo:block>
    </fo:list-item-label>
    <fo:list-item-body start-indent="body-start()">
      <fo:block><xsl:value-of select="."/></fo:block>
    </fo:list-item-body>
  </fo:list-item>
</xsl:for-each>

4. 列表样式变体

<!-- 圆点列表 -->
<fo:list-item-label>
  <fo:block>•</fo:block>
</fo:list-item-label>

<!-- 数字列表 -->
<fo:list-item-label>
  <fo:block>1.</fo:block>
</fo:list-item-label>

<!-- 字母列表 -->
<fo:list-item-label>
  <fo:block>a.</fo:block>
</fo:list-item-label>

<!-- 术语定义列表 -->
<fo:list-item-label>
  <fo:block font-weight="bold">术语</fo:block>
</fo:list-item-label>
<fo:list-item-body>
  <fo:block>术语定义...</fo:block>
</fo:list-item-body>

5. 列表跨页处理

<fo:list-item keep-together.within-page="always">
  <!-- 单个列表项不跨页 -->
</fo:list-item>

XSLFO 表格

XSLFO 表格

1. 表格结构

<fo:table table-layout="fixed" width="100%">

  <!-- 列定义 -->
  <fo:table-column column-width="25%"/>
  <fo:table-column column-width="45%"/>
  <fo:table-column column-width="30%"/>

  <!-- 表头 -->
  <fo:table-header>
    <fo:table-row>
      <fo:table-cell><fo:block font-weight="bold">姓名</fo:block></fo:table-cell>
      <fo:table-cell><fo:block font-weight="bold">部门</fo:block></fo:table-cell>
      <fo:table-cell><fo:block font-weight="bold">工资</fo:block></fo:table-cell>
    </fo:table-row>
  </fo:table-header>

  <!-- 表体 -->
  <fo:table-body>
    <fo:table-row>
      <fo:table-cell><fo:block>张三</fo:block></fo:table-cell>
      <fo:table-cell><fo:block>技术部</fo:block></fo:table-cell>
      <fo:table-cell><fo:block>12000</fo:block></fo:table-cell>
    </fo:table-row>
  </fo:table-body>
</fo:table>

2. 表格属性

<fo:table
    width="100%"                       <!-- 宽度 -->
    table-layout="fixed|auto"          <!-- 布局 -->
    border-collapse="collapse"         <!-- 边框合并 -->
    border="0.5pt solid #000">         <!-- 边框 -->

<fo:table-column column-width="2cm"/>
<fo:table-column column-width="*"/>    <!-- 剩余宽度 -->

<fo:table-cell number-columns-spanned="2">   <!-- 跨列 -->
<fo:table-cell number-rows-spanned="2">      <!-- 跨行 -->
<fo:table-cell padding="4pt" background-color="#eee">  <!-- 样式 -->

3. 表头跨页重复

<fo:table-header>
  <!-- 表格跨页时,表头自动在每页重复 -->
  <fo:table-row>...</fo:table-row>
</fo:table-header>

<!-- 行不跨页 -->
<fo:table-row keep-together.within-page="always">...</fo:table-row>

4. 从 XML 生成表格(XSLT)

<xsl:for-each select="employees/employee">
  <fo:table-row>
    <fo:table-cell>
      <fo:block><xsl:value-of select="name"/></fo:block>
    </fo:table-cell>
    <fo:table-cell>
      <fo:block><xsl:value-of select="salary"/></fo:block>
    </fo:table-cell>
  </fo:table-row>
</xsl:for-each>

XSLFO & XSLT

XSLFO & XSLT

1. 二者关系

XSLT 负责转换:把 XML 转换为 XSL-FO;XSL-FO 负责格式化:把转换结果排版为 PDF/打印文档。二者配合完成"数据到文档"的完整流程。

2. 转换流程

XML(数据) + XSLT(样式表)
        ↓ XSLT 处理器
FO 文档(格式化对象)
        ↓ FO 处理器(FOP)
PDF / 打印

3. 完整示例:XML → XSLT → FO

<!-- 数据:report.xml -->
<report>
  <title>季度报告</title>
  <section>
    <heading>销售概况</heading>
    <para>本季度销售额增长 15%。</para>
  </section>
</report>
<!-- 样式:report.xsl -->
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:fo="http://www.w3.org/1999/XSL/Format">

  <xsl:template match="/">
    <fo:root>
      <fo:layout-master-set>
        <fo:simple-page-master master-name="A4">
          <fo:region-body margin="2cm"/>
        </fo:simple-page-master>
      </fo:layout-master-set>
      <fo:page-sequence master-reference="A4">
        <fo:flow flow-name="xsl-region-body">
          <fo:block font-size="22pt" font-weight="bold">
            <xsl:value-of select="report/title"/>
          </fo:block>
          <xsl:apply-templates select="report/section"/>
        </fo:flow>
      </fo:page-sequence>
    </fo:root>
  </xsl:template>

  <xsl:template match="section">
    <fo:block font-size="14pt" font-weight="bold" space-before="12pt">
      <xsl:value-of select="heading"/>
    </fo:block>
    <fo:block text-indent="2em">
      <xsl:value-of select="para"/>
    </fo:block>
  </xsl:template>
</xsl:stylesheet>

4. 常用转换模式

# 直接输出 FO 元素
<xsl:element name="fo:block">...

# 条件生成
<xsl:if test="@important='true'">
  <fo:block font-weight="bold">重要内容</fo:block>
</xsl:if>

# 循环生成表格行
<xsl:for-each select="rows/row">...</xsl:for-each>

XSLFO 软件

XSLFO 软件

1. 编辑器与工具

  • XMLSpy:Altova 出品,支持 XSLT/XSL-FO 编辑调试,集成 FO 预览
  • Oxygen XML Editor:跨平台 XML 工具,内置 FOP 转换
  • VS Code:XML 插件 + 命令行 FOP
  • Stylus Studio:XML 开发套件

2. FO 处理器

软件类型特点
Apache FOP开源跨平台,Java,支持 PDF/PNG/PS/TIF
RenderX XEP商业规范覆盖率高,性能好
Antenna House商业东亚字体、SVG 支持强
Altsoft Xml2PDF商业纯 .NET 实现

3. Apache FOP 详解

# 下载
https://xmlgraphics.apache.org/fop/

# 目录结构
fop/
├── fop                    # 启动脚本
├── fop.xconf              # 配置文件
├── conf/
├── lib/                   # 依赖 jar
└── examples/

4. FOP 命令行常用

# FO 转 PDF
fop -fo input.fo -pdf output.pdf

# XML+XSL 转 PDF
fop -xml input.xml -xsl style.xsl -pdf output.pdf

# 其他格式
fop -fo input.fo -png output.png
fop -fo input.fo -txt output.txt
fop -fo input.fo -ps output.ps

# 使用配置文件
fop -c fop.xconf -fo input.fo -pdf output.pdf

# 详细日志
fop -fo input.fo -pdf output.pdf -d

5. 常见问题

  • 中文字体乱码:fop.xconf 中注册中文字体(STSong/微软雅黑)
  • 图片不显示:使用 fo:external-graphic 并给绝对/相对路径
  • 性能:大数据量分页转换,建议流式处理

XSL-FO 对象

XSL-FO 对象

1. 对象分类

XSL-FO 对象按用途分为几大类:

类别对象
文档结构fo:root
页面布局fo:layout-master-set、fo:simple-page-master、fo:page-sequence-master
页面内容fo:page-sequence、fo:flow、fo:static-content
块级fo:block、fo:block-container、fo:list-block、fo:table
行内fo:inline、fo:inline-container、fo:character
图形fo:external-graphic、fo:instream-foreign-object
文本相关fo:page-number、fo:leader、fo:basic-link
表格fo:table、fo:table-column、fo:table-header/body/footer、fo:table-row、fo:table-cell

2. 常用对象速查

fo:root                 文档根
fo:layout-master-set    页面主控集合
fo:simple-page-master   简单页面主控
fo:page-sequence        页序列
fo:flow                 内容流
fo:static-content       静态内容(页眉页脚)
fo:block                块(段落/标题)
fo:inline               行内元素
fo:external-graphic     外部图片
fo:page-number          页码
fo:basic-link           超链接
fo:leader               引导线(目录点线)
fo:table-*              表格系列

3. 图片对象

<fo:external-graphic src="url('images/logo.png')"
    content-width="5cm" content-height="2cm"/>

4. 链接对象

<fo:basic-link external-destination="url('https://example.com')">
  <fo:block color="blue" text-decoration="underline">访问官网</fo:block>
</fo:basic-link>

5. 目录引导线

<fo:block>
  第一章 概述
  <fo:leader leader-pattern="dots" leader-length.optimum="100%"/>
  第 1 页
</fo:block>

XSL-FO 简介

XSL-FO 简介

1. 定义

XSL-FO(Extensible Stylesheet Language Formatting Objects)是 W3C 推荐的用于 XML 文档格式化的标准,将结构化数据排版为适合打印和分页的格式。

2. 关键特性

  • 完全基于 XML,声明式描述排版
  • 面向打印:支持分页、页眉页脚、页码
  • 精确控制:字体、间距、边框、对齐、颜色
  • 与 XSLT 天然配合,自动化文档生成

3. 适用场景

  • 企业报表、发票、合同批量生成 PDF
  • 书籍、手册排版出版
  • 电子发票、单据打印
  • 任何"XML 数据 → PDF"的自动化需求

4. 学习门槛

相比 CSS, XSL-FO 概念更多(主控、区域、流),但模式固定、属性体系完整,掌握核心对象后即可产出专业文档。

5. 快速回顾核心流程

1. 准备 XML 数据
2. 编写 XSLT 样式表生成 FO
3. 用 FOP 等处理器输出 PDF
4. 检查分页、字体、表格排版

现在开始学习XSL-FO!

现在开始学习 XSL-FO!

1. 准备工作

  1. 下载 Apache FOP:xmlgraphics.apache.org/fop
  2. 准备一个文本编辑器(推荐 VS Code)
  3. 准备示例 XML 数据

2. 第一步:创建最小 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="page"
        page-width="21cm" page-height="29.7cm">
      <fo:region-body margin="2cm"/>
    </fo:simple-page-master>
  </fo:layout-master-set>
  <fo:page-sequence master-reference="page">
    <fo:flow flow-name="xsl-region-body">
      <fo:block font-size="16pt" font-weight="bold">
        我的第一份 XSL-FO 文档
      </fo:block>
    </fo:flow>
  </fo:page-sequence>
</fo:root>

3. 第二步:转换

fop -fo hello.fo -pdf hello.pdf
# 打开 hello.pdf 查看效果

4. 第三步:用 XSLT 驱动数据

# 准备 data.xml
<items>
  <item>苹果</item>
  <item>香蕉</item>
</items>

# 在 XSLT 中循环生成 FO
<xsl:for-each select="items/item">
  <fo:block>• <xsl:value-of select="."/></fo:block>
</xsl:for-each>

5. 练习建议

  • 生成一份带页眉页脚和页码的报表
  • 生成一个跨页的表格并验证表头重复
  • 生成一份目录(引导线 + 页码引用)
  • 加入图片与超链接

动手实践是掌握 XSL-FO 最快的方式,开始吧!

XSL-FO 对象参考手册

XSL-FO 对象参考手册

1. 文档与页面对象

对象说明
fo:root文档根元素
fo:layout-master-set页面主控集合
fo:simple-page-master单页主控,定义尺寸边距区域
fo:page-sequence-master复合页面主控(奇偶页等)
fo:region-body/before/after/start/end页面区域
fo:page-sequence页序列
fo:flow内容流
fo:static-content静态内容(页眉页脚)

2. 块与行内对象

对象说明
fo:block块级元素(段落、标题、表格单元格内容)
fo:block-container块容器(可定位/旋转)
fo:inline行内元素
fo:inline-container行内容器
fo:character单个字符
fo:leader引导线
fo:page-number当前页码
fo:page-number-citation引用页码

3. 表格对象

对象说明
fo:table表格
fo:table-column列定义
fo:table-header表头(跨页重复)
fo:table-body表体
fo:table-footer表尾
fo:table-row行
fo:table-cell单元格

4. 列表与链接对象

对象说明
fo:list-block列表
fo:list-item列表项
fo:list-item-label列表标签
fo:list-item-body列表内容
fo:basic-link超链接
fo:external-graphic外部图片
fo:instream-foreign-object内嵌对象(SVG 等)

5. 常用属性速查

# 字体
font-family / font-size / font-weight / font-style / color

# 间距
margin-* / padding-* / space-before / space-after

# 边框
border / border-color / border-style / border-width

# 对齐
text-align / text-indent / line-height / vertical-align

# 分页
break-before / break-after / keep-with-next / keep-together

# 定位
position / top / left / width / height / z-index

完整属性定义参见 W3C XSL 规范。

第 1 / 16 节