58 lines
2.8 KiB
Python
58 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
"""生成"接受所有修订后"的干净 docx,用于 OnlyOffice 渲染做字体/排版的决定性视觉验证。
|
|
|
|
为什么需要:OnlyOffice 渲染修订态文字(w:ins,紫色+下划线)时视觉上常显示为类无衬线、
|
|
看起来字体/粗细与正文不同——这是 track-changes 的渲染特性,不是真实字体差异。vision 工具
|
|
会据此误报"字体不一致",导致无谓返工。把所有修订接受、批注去掉后再渲染,才能在无修订
|
|
颜色干扰下看到插入文字与正文的真实字体一致性。
|
|
|
|
用法: python accept-revisions-preview.py <in.docx> <out.docx>
|
|
处理: 解包所有 w:ins(保留内容)+ 删除所有 w:del(连内容)+ 移除批注锚点标记。
|
|
注意: 产物仅供"渲染核对",不是正式交付物(交付的是带修订痕迹的版本)。
|
|
"""
|
|
import sys, zipfile, io
|
|
from lxml import etree
|
|
|
|
W = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'
|
|
Wq = '{' + W + '}'
|
|
|
|
|
|
def accept_revisions(in_path, out_path):
|
|
with open(in_path, 'rb') as f:
|
|
data = f.read()
|
|
bin_, bout = io.BytesIO(data), io.BytesIO()
|
|
with zipfile.ZipFile(bin_) as zin, zipfile.ZipFile(bout, 'w', zipfile.ZIP_DEFLATED) as zout:
|
|
for item in zin.infolist():
|
|
raw = zin.read(item.filename)
|
|
if item.filename == 'word/document.xml':
|
|
root = etree.fromstring(raw)
|
|
# 删除所有 w:del(含内容)
|
|
for d in [e for e in root.iter(Wq + 'del')]:
|
|
d.getparent().remove(d)
|
|
# 解包所有 w:ins:把子元素提到 ins 的位置后删除 ins 壳
|
|
for ins in [e for e in root.iter(Wq + 'ins')]:
|
|
parent = ins.getparent()
|
|
idx = list(parent).index(ins)
|
|
for child in reversed(list(ins)):
|
|
parent.insert(idx, child)
|
|
parent.remove(ins)
|
|
# 移除批注锚点标记
|
|
for tag in ('commentRangeStart', 'commentRangeEnd'):
|
|
for e in [x for x in root.iter(Wq + tag)]:
|
|
e.getparent().remove(e)
|
|
for r in [x for x in root.iter(Wq + 'r')]:
|
|
if r.find(Wq + 'commentReference') is not None:
|
|
r.getparent().remove(r)
|
|
raw = etree.tostring(root, xml_declaration=True, encoding='UTF-8', standalone=True)
|
|
zout.writestr(item, raw)
|
|
with open(out_path, 'wb') as f:
|
|
f.write(bout.getvalue())
|
|
print(f'接受修订版已生成: {out_path}')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
if len(sys.argv) != 3:
|
|
print('用法: python accept-revisions-preview.py <in.docx> <out.docx>')
|
|
sys.exit(1)
|
|
accept_revisions(sys.argv[1], sys.argv[2])
|