6.7 KiB
法律文书:脚注、同源模板成稿、Doro 编辑后字体修复
contract-editor 库(zipfile+lxml)在新成稿文书(非修订态)上的复用。2026-06-23-24 邹家《情况反映》制作中验证。配套 litigation-doc-tracked-changes.md(那篇讲修订态;本篇讲脚注+新建文书+字体规范化,都不是 tracked-changes)。
1. 法条原文脚注——从同案"姊妹文书"克隆脚注样式(铁律:脚注样式不要凭空造)
需求场景:Doro 把正文里的法条引用("《民事诉讼法》第七十一条之规定")要求改成脚注呈现法条全文,且"脚注格式和申请书一样"。
正确做法是从同案已有带脚注的文书(如同目录的《民事诉讼监督申请书》v9)克隆脚注体例,而不是自己拼 footnotes.xml:
脚注的两个组成(先从姊妹文书读出样式模板):
- 正文里的引用标:一个
<w:r>,rPr 带<w:rStyle w:val="affb"/>+ Times New Roman + 与正文同字号(sz24),内含<w:footnoteReference w:id="N"/>。affb是 Word 默认的 FootnoteReference 字符样式 id(不同文档可能不同,从姊妹文书正文的 footnoteReference 承载 run 实测,别硬编码)。 - footnotes.xml 里的脚注正文:separator/continuationSeparator 两个特殊脚注(id=-1/0,原样复制)+ 内容脚注(id≥1)。内容脚注段落 spacing line=240,run 字号是脚注体例 sz18(9pt,小于正文),法名加粗(
<w:b/>)、条号与原文不加粗。
# 从姊妹文书 sqs_v9.docx 取模板
fn_sqs = etree.fromstring(z_sqs.read('word/footnotes.xml'))
special = {ft: deepcopy(f) for f in fn_sqs.iter(qn('footnote'))
for ft in [f.get(qn('type'))] if ft in ('separator','continuationSeparator')}
content_tmpl_p = deepcopy([f.find(qn('p')) for f in fn_sqs.iter(qn('footnote'))
if f.get(qn('id'))=='1'][0])
# 从模板段落抽三种 rPr:mark(带rStyle affb)、bold(法名)、plain(原文)
# 正文引用标 rPr 则从姊妹文书 document.xml 里 footnoteReference 承载 run 抓
目标 docx 必须已支持脚注:word/_rels/document.xml.rels 有 footnotes 关系、[Content_Types].xml 有 footnotes+xml、styles.xml 有 affb 样式。若目标是从同源文书演化来的(本例情况反映以申请书为母版),这三样天然齐全;若从零新建则要补。
2. 脚注标定位的坑:锚点跨 run 时 footnoteReference 会插错位置(本会话实犯)
把脚注标插在"第五十一条第二款"之后时,第一版用"找锚点子串→定位锚点所在 run→run 后插标",结果 ³ 插到了下游的"承办部门"后面——因为锚点文字跨多个 run,按 run 粒度定位会落到错误的 run。
正解:字符流定位 + 必要时拆 run。把全段所有 w:t 拼成字符流,建立 每个字符→(t元素, 字符在t内的索引) 映射,找到锚点结束字符的精确位置;若结束字符在某 run 中间,split 该 run(head 留原 run,tail 进新 run),脚注引用 run 插在 head 和 tail 之间。这样标精确落在"…第二款【标】所定…"。
验证只能靠 OnlyOffice x2t 渲染后看页脚——vision 一眼就抓出"³ 标在承办部门后",肉眼读 XML 容易漏。体例统一:四个脚注一律"法条号正后方"挂注(不要有的挂句末有的挂条号后)。
3. 用同案文书做"母版"新建文书——保证两份同源同体例
新建《情况反映》时,以同案《民事诉讼监督申请书》v9 为母版克隆,确保字体/字号/页边距/样式完全一致(Doro/Maggie 两份并排看不会有体例差):
- 从母版抽各类段落模板:title(居中bold sz30)、body(首行缩进480 sz24)、recip(顶格bold 机关名)、sign(右对齐)、date、attachment-title、attachment-item。
mk(tmpl_key, text, bold=, no_indent=)克隆模板段→清空 run/numPr/ins/del→重设仿宋+Times→填文字。 - 用母版的整个 docx 做容器(保留 sectPr 页面设置、styles、numbering),只重写 body 的段落序列 + 清掉
<w:trackRevisions/>。 - 清掉母版页眉:母版页眉可能是另一种文书的抬头(本例申请书页眉"申请监督案号/受理法院"套在情况反映上不对)。清页眉要两步:①删页眉段所有 run 文字;②删页眉段 pPr 的
<w:pBdr>(页眉那条横线来自段落下边框,只删文字会留一条孤线)。OnlyOffice 渲染确认顶部纯白到标题。
4. ⚠️Doro 用编辑器改过的 docx 会丢显式 eastAsia 字体属性——每轮都要补(本会话两轮各犯一次)
现象:Doro 在他本机编辑器改过 docx 后回传,正文中文 run 的 rFonts 没有显式 eastAsia 字体名(本会话两轮分别 1283、1243 个中文字符 eastAsia=None,docDefaults 也空)。OnlyOffice 靠底层回退仍渲染成仿宋、肉眼看正常,但显式字体属性缺失不符合交付标准(我们要求中文显式仿宋)。
判别:交付前扫一遍——
for r in root.iter(qn('r')):
rf = r.find(qn('rPr/rFonts'))
ea = rf.get(qn('eastAsia')) if rf is not None else None
# 统计含中文 run 里 ea is None 的数量;>0 就要补
修复(格式规范化,不改字形/文字/Doro 内容):每个含文字的 run,rFonts 显式设 eastAsia=仿宋,缺 ascii/hAnsi 的补 Times New Roman;再给 docDefaults/rPrDefault/rPr/rFonts 补 eastAsia=仿宋 兜底。改完目标:CJK 全仿宋、英数全 Times。这是和合同字体规范化同类的操作,但要点在"每次 Doro 回传都要重做一遍"——他的编辑器每改一次就再剥一次,不是一次性问题。改完必须 OnlyOffice 重渲染确认无字形回退(字体属性动过就要重验)。
5. 附件/正文 Doro 自己加的内容:修错别字但不擅改实质
Doro 自己在附件加了"检查监督申请书"——①错别字"检查"→"检察"院的监督,规范名应是与正式文件名一致的《民事诉讼监督申请书》(改);②但若附件项之间有实质区分缺失(如两份《质证通知书》一份标了"3日期限版"另一份没标"15日期限版"),那是 Doro 定的内容,只提示不擅改。附件清单常是自动编号(numId),Doro 删手敲序号是对的,自动会续 1-6。
一句话
脚注从同案姊妹文书克隆样式(rStyle affb + sz18 脚注体、法名加粗)、标位置用字符流+拆run精确落在条号后;新建文书拿同案文书做母版保同源(清页眉含删 pBdr);Doro 编辑器回传的 docx 每轮都丢显式 eastAsia,每次交付前都要全局补仿宋再渲染。