docx 文件脚注的编号
(发布于 2015 年 8 月 3 日)
最近,使用 pandoc 生成 docx 文件遇到一个问题。默认情况下,一个文档中的所有脚注是按顺序标号的。这其实没什么问题,因为“语义”上讲,这就是正确的编号方法。但是,我想实现的是“按章”编号。
我之前已经从样式上区别了各章(方法参见《docx 文件定制指南》),即在一级标题之前换页。这只是“表面功夫”,Word 看到的仍是一个没有结构划分的文档。为了实现脚注按章编号,首先要想办法让 Word 知道每一章在哪里开始,在哪里结束,也就是从“语义”上实现分章。
其实 Word 提供了这种功能——分节。不过在代码层级,实现起来有点复杂。根据 WordProcessingML 的定义,文档最后一节的相关属性在 w:body
元素中最后一个 w:sectPr
元素中定义,而之前每一节的相关属性都在各节最后一个段落(w:p
)的属性中定义,如下述代码所示:
<w:body>
<!--第一节-->
<w:p>...</w:p>
<w:p>...</w:p>
<w:p>
<w:pPr>
<w:sectPr>...</w:sectPr>
</w:pPr>
...
</w:p>
<!--第二节-->
<w:p>...</w:p>
<w:p>...</w:p>
<w:p>
<w:pPr>
<w:sectPr>...</w:sectPr>
</w:pPr>
...
</w:p>
<!--最后一节-->
<w:p>...</w:p>
<w:p>...</w:p>
<w:p>...</w:p>
<w:sectPr>
...
</w:sectPr>
</w:body>
pandoc 所用的模板没有为最后一节指定任何属性,即只有 <w:sectPr/>
。所以,要想办法设置最后一节的属性,还要在每个一级标题之前的段落属性里插入 <w:sectPr>
元素。这个好办,使用相关的 XML 处理库就行。如果使用 Ruby,可以用 nokogiri。XML 的具体处理方法本文不再赘述。
不过,要如何设置每一节的属性才能让脚注按章编号呢?按照 WordProcessingML 的定义,脚注的属性放在 w:footnotePr
元素中,控制编号方式的是 w:numRestart
元素。这个元素的值可以设为下述三个值中的一个:
continuous
(默认值)eachSect
eachPage
从上可以看出,我们需要把这个元素的值设为 eachSect
,即开始新的一节时重新从头开始为脚注编号。最终设置的 w:sectPr
如下:
<w:sectPr>
<w:footnotePr>
<w:numRestart w:val="eachSect"/>
</w:footnotePr>
</w:sectPr>
如果想每页单独编号,可以把 w:numRestart
的值设为 eachPage
。