XSL-FO的marker是一种用于在页面静态区域(如页眉、页脚)中显示文档流动态内容的格式化对象。它允许你在正文的不同位置放置标记,然后在页面区域中把这些标记对应的值取出来显示,从而实现随页面内容变化的页眉页脚信息。

marker的基本用途
在排版书籍、报告或票据时,我们通常希望页眉显示当前页所属的章节,页脚显示当前页的小节。如果不用marker,只能在生成XSL-FO之前人为计算每一页的内容并写死,非常麻烦。marker的出现就是为了解决这个问题:
- 在文档流中使用<fo:marker>定义具名标记和内容
- 在页眉页脚等静态区域使用<fo:retrieve-marker>按规则取出最近或最远的标记
- 处理器在分页时自动把对应页的标记内容填入页面区域
一个简单的示例
下面演示如何用marker让页眉显示当前章节标题。我们在每个章节块里放一个marker,然后在page-header里取出来。
<?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="210mm" page-height="297mm">
<fo:region-body margin="2cm"/>
<fo:region-before extent="1cm"/>
<fo:simple-page-master>
<fo:layout-master-set>
<fo:page-sequence master-reference="page">
<fo:static-content flow-name="xsl-region-before">
<fo:block>
当前章节:<fo:retrieve-marker retrieve-class-name="chapter" retrieve-position="first-including-carryover"/>
<fo:block>
<fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block break-before="page">
<fo:marker marker-class-name="chapter">第一章 概述</fo:marker>
这是第一章的内容。
<fo:block>
<fo:block break-before="page">
<fo:marker marker-class-name="chapter">第二章 细节</fo:marker>
这是第二章的内容。
<fo:block>
<fo:flow>
<fo:page-sequence>
<fo:root>
retrieve-position的取值含义
使用<fo:retrieve-marker>时,retrieve-position属性决定取哪一处的marker。常见取值如下:
| 取值 | 含义 |
|---|---|
| first-including-carryover | 取本页第一个marker,若本页没有则沿用上一页最后的marker |
| first-starting-within-page | 只取本页新开始的marker,不沿用上一页 |
| last-starting-within-page | 取本页最后一个新开始的marker |
实际使用建议
当你需要页眉页脚跟随内容变化时,优先考虑用marker而不是在外部程序里硬算。注意marker的内容应是纯文本或简单 inline 级格式化对象,不要放复杂块级布局。另外,marker名字(marker-class-name)要在文档中保持唯一语义,方便 retrieve-marker 准确匹配。
总结:XSL-FO的marker用途就是在分页渲染时,把文档流里的动态信息桥接到页面静态区域,是制作专业排版输出的重要工具。