You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用XSL-FO结合Apache Fop生成带书签的PDF?求实现示例

嘿,这事儿我熟!给你一套完整的Apache FOP生成带书签PDF的示例,包括XSL-FO的书签定义和Java调用代码,直接就能用。

使用Apache FOP生成带书签的PDF示例

1. XSL-FO 样式表示例(包含书签定义)

在XSL-FO里,我们通过fo:bookmark-tree来定义整个书签结构,每个书签用fo:bookmark节点,通过internal-destination关联到文档里的锚点元素。下面是完整的示例:

<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <!-- 定义书签树,所有书签都放在这里 -->
    <fo:bookmark-tree>
        <!-- 一级书签:文档概述 -->
        <fo:bookmark internal-destination="overview-section">
            <fo:bookmark-title>文档概述</fo:bookmark-title>
        </fo:bookmark>
        <!-- 一级书签:详细内容(包含子书签) -->
        <fo:bookmark internal-destination="details-section">
            <fo:bookmark-title>详细内容</fo:bookmark-title>
            <!-- 子书签:第一小节 -->
            <fo:bookmark internal-destination="sub-section-1">
                <fo:bookmark-title>第一小节:核心概念</fo:bookmark-title>
            </fo:bookmark>
            <!-- 子书签:第二小节 -->
            <fo:bookmark internal-destination="sub-section-2">
                <fo:bookmark-title>第二小节:实践操作</fo:bookmark-title>
            </fo:bookmark>
        </fo:bookmark>
        <!-- 一级书签:总结 -->
        <fo:bookmark internal-destination="summary-section">
            <fo:bookmark-title>总结</fo:bookmark-title>
        </fo:bookmark>
    </fo:bookmark-tree>

    <!-- 页面布局设置 -->
    <fo:layout-master-set>
        <fo:simple-page-master master-name="A4" page-height="29.7cm" page-width="21cm" margin-top="2cm" margin-bottom="2cm" margin-left="2.5cm" margin-right="2.5cm">
            <fo:region-body/>
        </fo:simple-page-master>
    </fo:layout-master-set>

    <!-- 文档主体内容 -->
    <fo:page-sequence master-reference="A4">
        <fo:flow flow-name="xsl-region-body">
            <!-- 文档概述章节,设置锚点id -->
            <fo:block id="overview-section" font-size="24pt" font-weight="bold" space-after="1cm">
                文档概述
            </fo:block>
            <fo:block font-size="12pt" line-height="1.5" space-after="2cm">
                这里是文档的概述内容,简要介绍文档的主题和目的,帮读者快速了解核心方向。
            </fo:block>

            <!-- 详细内容章节,设置锚点id -->
            <fo:block id="details-section" font-size="24pt" font-weight="bold" space-after="1cm">
                详细内容
            </fo:block>
            <!-- 第一小节,设置锚点id -->
            <fo:block id="sub-section-1" font-size="18pt" font-weight="bold" space-after="0.5cm">
                第一小节:核心概念
            </fo:block>
            <fo:block font-size="12pt" line-height="1.5" space-after="1cm">
                这里讲解核心概念的详细内容,把抽象的原理拆解成易懂的知识点,帮助读者夯实基础。
            </fo:block>
            <!-- 第二小节,设置锚点id -->
            <fo:block id="sub-section-2" font-size="18pt" font-weight="bold" space-after="0.5cm">
                第二小节:实践操作
            </fo:block>
            <fo:block font-size="12pt" line-height="1.5" space-after="2cm">
                这里提供一步步的实践操作指南,配合示例代码,让读者能快速上手实现功能。
            </fo:block>

            <!-- 总结章节,设置锚点id -->
            <fo:block id="summary-section" font-size="24pt" font-weight="bold" space-after="1cm">
                总结
            </fo:block>
            <fo:block font-size="12pt" line-height="1.5">
                这里是文档的总结内容,回顾所有关键要点,强调核心收获,帮读者梳理整体知识体系。
            </fo:block>
        </fo:flow>
    </fo:page-sequence>
</fo:root>

关键说明

  • fo:bookmark-tree是所有书签的容器,必须放在fo:root下面,在fo:layout-master-set之前
  • 每个fo:bookmark的internal-destination属性值,必须和文档中对应块元素的id完全匹配(大小写敏感)
  • 嵌套fo:bookmark就能创建多级子书签,PDF阅读器会自动展示层级结构

2. Java 代码调用Apache FOP生成PDF

如果你用Java来调用FOP生成PDF,下面是直接可用的代码示例:

import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class FopBookmarkGenerator {
    public static void main(String[] args) throws Exception {
        // 初始化FOP工厂,指定当前目录为基础路径
        FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
        
        // 准备输出流,指定生成的PDF文件名
        OutputStream pdfOut = new FileOutputStream(new File("document-with-bookmarks.pdf"));
        
        try {
            // 创建FOP实例,指定输出格式为PDF
            Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, pdfOut);
            
            // 创建Identity转换器(因为我们直接用XSL-FO文件,不需要从XML转换)
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            
            // 指定输入的XSL-FO文件路径
            StreamSource foSource = new StreamSource(new File("input-document.fo"));
            
            // 关联转换器结果到FOP
            StreamResult result = new StreamResult(fop.getDefaultHandler());
            
            // 执行转换生成PDF
            transformer.transform(foSource, result);
            
            System.out.println("带书签的PDF已成功生成!");
        } finally {
            // 关闭输出流
            pdfOut.close();
        }
    }
}

使用提示

  • 确保你的项目已经引入Apache FOP的依赖,比如Maven可以添加如下依赖:
    <dependency>
        <groupId>org.apache.xmlgraphics</groupId>
        <artifactId>fop</artifactId>
        <version>2.9</version>
    </dependency>
    
  • 把之前的XSL-FO文件保存为input-document.fo,和Java类放在同一目录(或者调整代码里的文件路径)
  • 运行这个Java类,就能得到带书签的PDF文件了

3. 额外小贴士

  • 如果你的需求是从XML数据通过XSL转换生成XSL-FO,只需要在XSL模板中动态生成fo:bookmark-tree结构即可,比如遍历XML中的章节节点来创建对应的书签
  • 书签的标题可以动态设置,完全适配你的文档内容结构

内容的提问来源于stack exchange,提问作者Abhinav Agarwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:52:05