XSL-FO的list-block如何定义列表样式?

来源:安卓APP网作者:夏天宇头衔:网络博主
导读:本期聚焦于小伙伴创作的《XSL-FO的list-block如何定义列表样式?》,敬请观看详情。把一份XML文档排成印刷级PDF时,不少人卡在条目化内容的呈现上。XSL-FO用list-block搭配list-item来构造列表,而非CSS那种ul li加disc圆点。list-block本身只管纵向堆叠,真正的标记符号由list-item-label里的block承载,内容则放在list-item-body。通过调整label和body的provisional-distance-between-starts、relative-align等属性,可控制缩进与对齐。常见误区是直接给list-block设type属性期待自动编号,实际上必须用list-item-label手动输出序号或图形。下面以书籍目录与法律条款为例,说明从基础两栏布局到嵌套编号的完整写法。

在XSL-FO排版体系里,列表并不是像HTML那样有现成的无序或有序标签自动渲染符号,而是完全依靠list-block以及内部的list-itemlist-item-labellist-item-body组合来手工搭建。理解这套结构,是控制印刷文档中条目样式的前提。很多从CSS转来做XSL-FO的人,会习惯性寻找list-style-type之类的属性,结果在规范里找不到对应内容,就是因为两者的抽象层级不同。

XSL-FO的list-block如何定义列表样式?

list-block的基础结构与标签职责

list-block在XSL-FO中是一个块级格式化对象,它的作用类似于一个纵向容器,负责把多个list-item按顺序排下去。它本身并不绘制任何项目符号或编号,仅仅提供列表整体的外边距、缩进和间距控制。真正决定每一行长什么样的是list-item内部的拆分:左边是list-item-label,右边是list-item-body。这种左右分栏模型,让标签和内容可以独立设置字体、对齐方式。

一个最简单的list-item必须同时包含list-item-labellist-item-body,缺少任何一个都会导致格式化器报错。在list-item-label里通常会放一个block,里面写星号、横线或者数字;而list-item-body里的block则是具体的条目文本。两者通过provisional-distance-between-starts属性约定标签起点与正文起点的水平距离,这个距离直接决定了缩进量。

下面的示例展示了最基础的实心方块列表写法。可以看到,符号是自己写在label里的,而不是由处理器生成。这种做法虽然繁琐,但带来了极高的可控性,比如同一个列表里可以混用不同符号。

<fo:list-block provisional-distance-between-starts="10mm"
               provisional-label-separation="2mm">
  <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-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>

通过属性控制缩进、对齐与编号样式

要让列表看起来专业,仅靠基础结构还不够,必须精细调节list-blocklist-item上的几个核心属性。provisional-distance-between-starts设定的是从列表左边到正文内容开始位置的距离,而provisional-label-separation则是标签块和正文块之间的最小间隙。如果前者设置过小,长一点的标签(比如三位数编号)就会和正文重叠。

另一个关键属性是relative-align,它出现在list-item上,取值可以是beforebaseline。当设为before时,label的顶部和body的顶部对齐,适合方块或图片类符号;设为baseline时,则按文字基线对齐,适合数字编号场景,能让序号和正文首行文字视觉上平稳。对于多行正文条目,基线对齐能避免符号孤零零悬在上方。

如果希望实现自动递增编号,XSL-FO本身没有计数器机制,但可以在XSLT转换阶段利用xsl:number生成序号文本,再塞进list-item-label。这样既能保持FO层简洁,又免于手工维护数字。下面代码演示了XSLT如何为每一个条目算出序号并输出带点的编号:

<xsl:template match="item">
  <fo:list-item>
    <fo:list-item-label>
      <fo:block>
        <xsl:number format="1."/>
      </fo:block>
    </fo:list-item-label>
    <fo:list-item-body>
      <fo:block><xsl:value-of select="text"/></fo:block>
    </fo:list-item-body>
  </fo:list-item>
</xsl:template>

对于无序列表的符号变换,常见做法是在list-item-labelblock中使用不同Unicode字符,例如来表现层级。配合font-familycolor,可以轻松模拟出CSS里disc、circle、square的效果,而不依赖任何内置样式关键字。

嵌套列表与复杂排版场景实践

实际业务中经常遇到多级条款,例如法律文本或标准文档。XSL-FO允许在list-item-body内部再嵌入一个list-block,从而形成嵌套。每一层都可以独立设置缩进距离,外层用数字编号,内层用字母或符号,层次感通过缩进自然体现。需要注意的是,嵌套越深,provisional-distance-between-starts应当逐层递增,否则内层会和外层左边界挤在一起。

在制作技术手册目录时,我们常把一级章节作为数字编号,二级作为小数点编号。此时如果纯靠XSLT算号,可以用xsl:numberlevel属性输出多级编号,再格式化为1.1.这样的字符串。然后将结果写入对应层级的list-item-label。这种方案比在FO里做条件判断更清晰,也方便后期修改编号规则。

下面给出一个两级嵌套的示例,外层为章节,内层为小节,各自使用不同的标签符号与缩进,演示了如何在同一个list-block体系下保持视觉条理:

<fo:list-block provisional-distance-between-starts="8mm">
  <fo:list-item>
    <fo:list-item-label><fo:block>1.</fo:block></fo:list-item-label>
    <fo:list-item-body>
      <fo:block>安装与部署
        <fo:list-block provisional-distance-between-starts="6mm">
          <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-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>
      </fo:block>
    </fo:list-item-body>
  </fo:list-item>
</fo:list-block>

除了嵌套,还有一种场景是横排术语表:用list-block做定义列表,label放术语,body放解释,通过relative-align="baseline"让术语和解释首行对齐。这种用法已经超出了传统列表范畴,但正好说明list-block的本质是一个双栏对齐工具,只要掌握label与body的分离思想,就能衍生出丰富的版式。

XSL-FOlist-block列表样式修改时间:2026-08-16 09:18:33

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。