如何用XSL为DocBook目录不同层级设置差异化格式?修改autotoc.xsl遇阻
嘿,我之前折腾过DocBook目录的样式定制,刚好能给你支招!你说改autotoc.xsl没生效,大概率是没摸对模板优先级、没匹配对toc模式,或者直接修改原生文件后处理器没加载到改动后的版本——直接改原生文件也不是最佳实践,不如自己写个自定义样式表来覆盖,既安全又好维护。
下面分两种常见输出场景给你具体实现方案:
一、生成PDF(使用XSL-FO)
创建一个名为custom-toc.xsl的自定义样式表,导入DocBook的基础FO样式表,然后重写不同章节级别的toc模板:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> <!-- 导入DocBook官方FO样式表,路径根据你的本地安装位置调整 --> <xsl:import href="docbook-xsl-ns/fo/docbook.xsl"/> <!-- 重写顶级章节(sect1)的目录条目:加粗+指定字体字号 --> <xsl:template match="sect1" mode="toc"> <fo:list-item> <fo:list-item-label end-indent="label-end()"> <fo:block> <xsl:number level="multiple" count="chapter|sect1" format="1. "/> </fo:block> </fo:list-item-label> <fo:list-item-body start-indent="body-start()"> <fo:block font-family="Arial" font-size="12pt" font-weight="bold"> <xsl:apply-templates select="." mode="toc-link"/> </fo:block> <!-- 递归处理子章节sect2 --> <xsl:apply-templates select="sect2" mode="toc"/> </fo:list-item-body> </fo:list-item> </xsl:template> <!-- 重写sect2的目录条目:不加粗+不同字体字号 --> <xsl:template match="sect2" mode="toc"> <fo:list-item margin-left="15pt"> <fo:list-item-label end-indent="label-end()"> <fo:block> <xsl:number level="multiple" count="chapter|sect1|sect2" format="1.1 "/> </fo:block> </fo:list-item-label> <fo:list-item-body start-indent="body-start()"> <fo:block font-family="Verdana" font-size="10pt" font-weight="normal"> <xsl:apply-templates select="." mode="toc-link"/> </fo:block> <!-- 递归处理子章节sect3 --> <xsl:apply-templates select="sect3" mode="toc"/> </fo:list-item-body> </fo:list-item> </xsl:template> <!-- 重写sect3的目录条目:不加粗+另一组字体字号 --> <xsl:template match="sect3" mode="toc"> <fo:list-item margin-left="30pt"> <fo:list-item-label end-indent="label-end()"> <fo:block> <xsl:number level="multiple" count="chapter|sect1|sect2|sect3" format="1.1.1 "/> </fo:block> </fo:list-item-label> <fo:list-item-body start-indent="body-start()"> <fo:block font-family="Georgia" font-size="9pt" font-weight="normal"> <xsl:apply-templates select="." mode="toc-link"/> </fo:block> </fo:list-item-body> </fo:list-item> </xsl:template> </xsl:stylesheet>
二、生成HTML
如果是输出HTML,同样用自定义样式表覆盖模板,直接给链接加内联样式(或者后续用CSS统一管理):
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 导入DocBook官方HTML样式表,路径按需调整 --> <xsl:import href="docbook-xsl-ns/html/docbook.xsl"/> <!-- 顶级章节sect1的HTML目录条目 --> <xsl:template match="sect1" mode="toc"> <li> <a href="{@id}.html" style="font-family: Arial; font-size: 12pt; font-weight: bold;"> <xsl:number level="multiple" count="chapter|sect1" format="1. "/> <xsl:apply-templates select="title"/> </a> <xsl:if test="sect2"> <ul> <xsl:apply-templates select="sect2" mode="toc"/> </ul> </xsl:if> </li> </xsl:template> <!-- sect2的HTML目录条目 --> <xsl:template match="sect2" mode="toc"> <li> <a href="{@id}.html" style="font-family: Verdana; font-size: 10pt; font-weight: normal;"> <xsl:number level="multiple" count="chapter|sect1|sect2" format="1.1 "/> <xsl:apply-templates select="title"/> </a> <xsl:if test="sect3"> <ul> <xsl:apply-templates select="sect3" mode="toc"/> </ul> </xsl:if> </li> </xsl:template> <!-- sect3的HTML目录条目 --> <xsl:template match="sect3" mode="toc"> <li> <a href="{@id}.html" style="font-family: Georgia; font-size: 9pt; font-weight: normal;"> <xsl:number level="multiple" count="chapter|sect1|sect2|sect3" format="1.1.1 "/> <xsl:apply-templates select="title"/> </a> </li> </xsl:template> </xsl:stylesheet>
关键注意事项
- 模板优先级:用
<xsl:import>导入官方样式表,自定义模板会优先被调用,因为导入的模板优先级低于当前样式表的模板,这也是你之前改autotoc.xsl没生效的核心原因之一——原生模板优先级可能更高,或者你没匹配对mode="toc"。 - 字体可用性:如果是PDF输出,要确保你指定的字体(比如Arial、Verdana)已经安装在系统中,或者在样式表中通过
fo:font-face指定字体文件路径,否则处理器会 fallback 到默认字体。 - 使用方式:用XSLT处理器(比如
xsltproc)调用自定义样式表,而不是官方的:
# PDF输出示例(还需要后续用FOP等工具转PDF) xsltproc custom-toc.xsl your-docbook.xml > output.fo # HTML输出示例 xsltproc custom-toc.xsl your-docbook.xml > index.html
内容的提问来源于stack exchange,提问作者R Zol
相关产品推荐
相关产品推荐

