ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Ekko Studio docx Skill 源码级解析:Word 修订(Tracked Changes)与批注(Comments)的 WordprocessingML 处理

Ekko Studio docx Skill 源码级解析:Word 修订(Tracked Changes)与批注(Comments)的 WordprocessingML 处理 AI 应用人工智能AI Agent本地部署前端后端工作流自动化【免费下载链接】ekko-studioEkko Studio is a local-first AI workspace for multi-agent chat, coding, and visual workflows, available on desktop and the web.项目地址https://gitcode.com/gh_mirrors/he/ekko-studio点击查看免费下载本篇技术指南聚焦 Ekko Studio 仓库中packages/ekko-agent/skills/docx这一文档处理 Skill 的核心难点——Word 修订追踪w:ins/w:del与批注Comments的底层 WordprocessingML 处理。文章以 revisions-and-comments.md 为骨架结合 docx_revisions.py 与 docx_comments.py 的源码实现帮助读者理解修订接受/拒绝的决议语义、批注的三件套XML 结构以及如何在日常自动化流程中安全地使用这些命令。读完本文你将能读懂任意 .docx 中的修订与批注 XML并能用命令行完成列出、接受、拒绝、增删批注等全部操作。一、docx Skill 中修订与批注的定位Ekko Studio 的 docx Skill 是一套围绕 python-docx 与 lxml 构建的 Word 文档处理工具集其入口与总览见 SKILL.md。其中与本文主题直接相关的两个脚本是docx_revisions.py检查并决议修订追踪w:ins/w:deldocx_comments.py列出、添加、删除批注。这两个脚本被定位为深层参考deep reference日常使用只需按 SKILL.md 的操作流程走只有需要推理原始 WordprocessingML、扩展脚本或调试异常文档时才需要进入 revisions-and-comments.md 这一层。SKILL.md 还给出了明确的安全约定除非用户明确要求绝不丢弃批注或修订accept-all/reject-all与批量删除批注均属于破坏性变换操作前必须确认范围。脚本运行环境仅需两个 Python 依赖见 SKILL.md 的 Core dependency 段python3 -m pip install python-docx lxml所有脚本均以python3 脚本路径 ...方式调用例如python3 packages/ekko-agent/skills/docx/scripts/docx_read.py input.docx --json python3 packages/ekko-agent/skills/docx/scripts/docx_validate.py output.docx二、修订追踪的 XML 结构w:ins/w:delWord 将运行级run-level修订记录为段落w:p内部的包装元素wrapper element命名空间为http://schemas.openxmlformats.org/wordprocessingml/2006/mainrevisions-and-comments.md 给出的典型结构如下w:p w:rw:tBase /w:t/w:r w:ins w:id1 w:authorEditor w:date2026-01-02T03:04:05Z w:rw:tinserted text/w:t/w:r /w:ins w:del w:id2 w:authorEditor w:date2026-01-02T03:04:05Z w:rw:delTextdeleted text/w:delText/w:r /w:del /w:p两个关键事实决定了脚本的全部行为被删除的文本存放在w:delText而非w:t中。正因为如此普通的纯文本提取如 python-docx 的paragraph.text天然呈现接受修订后的视图——插入可见、删除隐藏。这可以从 docx_read.py 的 docstring 中得到印证Body text is the accepted/as-is text (python-docx ignores deleted-in-revision text and shows inserted text)。决议resolve语义是确定性的见下表修订类型动作处理方式w:ins接受accept解包unwrap把子 runs 上移到父级移除包装元素w:ins拒绝reject移除包装元素及其全部内容w:del接受accept移除包装元素及其全部内容w:del拒绝reject把每个w:delText重命名为w:t然后解包上述解包逻辑在 docx_revisions.py 中有直接实现_unwrap找到父元素中当前元素的位置把其子节点逐个插入到原位置并移除包装器_apply则按上表分支执行——拒绝删除时对delText改名再解包从而实现恢复被删文本。三、docx_revisions.py五个子命令与调用链docx_revisions.py 提供五个子命令对应argparsesubparsers子命令说明额外参数list以 JSON 列出全部修订id、author、date、type、text无accept-all接受全部插入与删除-o/--outputreject-all拒绝全部插入与删除-o/--outputaccept按w:id接受单个修订--id必填reject按w:id拒绝单个修订--id必填所有命令的通用参数是输入path-o/--output省略时原地覆盖输入文件源码中out args.output or args.path因此生产环境建议总是显式传-o。典型用法摘自脚本 docstringpython3 docx_revisions.py list report.docx python3 docx_revisions.py accept-all report.docx -o accepted.docx python3 docx_revisions.py reject report.docx --id 3 -o out.docx输出为结构化 JSON例如list返回{ok: true, revisions: [...]}accept/reject返回{ok: true, output: ..., resolved: n, action: accept|reject}。当按--id决议但找不到该 id 时返回{ok: false, error: no revision with id ...}并以退出码 1 结束见 docx_revisions.py。覆盖范围正文、表格、页眉页脚脚本遍历的是body 根 每个页眉/页脚部件根核心是root.iter(Wins, Wdel)它按文档顺序递归查找任意深度的元素。提供这套遍历的是公共模块 docx_common.py 中的iter_part_roots它依次产出 body 根以及每个 section 的 header / footer / first_page_header / first_page_footer / even_page_header / even_page_footer 的 XML 根用id(part._element)去重避免同源部件重复处理。因此正文段落、表格单元格含嵌套表格、页眉、页脚、文本框中的修订都能被发现和决议修订可以出现在任何允许块级内容block content的位置。关于w:id的注意事项w:id的值在每个修订元素上是唯一的但一次逻辑上的编辑会话可能产生多个元素。因此accept/reject --id精确作用于携带该 id 的一个或多个元素——源码resolve()中rev_id is None or el.get(q(id)) rev_id正是这种按 id 精确匹配的语义。四、脚本不处理的修订类型与检测手段revisions-and-comments.md 明确列出了脚本不做决议、仅检测的修订类型段落标记修订paragraph-mark revisions即w:pPr上的w:rPr/w:ins表格行插入/删除w:trPr/w:ins格式变更记录w:rPrChange、w:pPrChange移动修订w:moveFrom/w:moveTo。其中移动修订在常见编辑器中较为罕见文档建议如果文档中存在移动修订直接用 Word 本身处理不要猜测。这些类型的检测由 docx_read.py 的--revisions参数完成其detect_revisions()实现方式非常轻量直接以 zipfile 打开 .docx扫描word/下所有 XML 部件的原始字节匹配w:ins、w:del、w:rPrChange以及word/comments部件是否存在见 docx_read.py返回has_tracked_changes、comments等布尔标记。建议任何编辑操作前先运行它做是否有修订/批注的摸底。五、批注的三件套XML 结构批注由三个相互协作的部分组成见 revisions-and-comments.md 的 Comments 一节word/comments.xml部件——每个批注一个w:comment元素携带w:id、w:author、w:initials、w:date及正文段落。它通过关系类型.../comments与 document.xml 关联内容类型为application/vnd...wordprocessingml.commentsxml同时需要在[Content_Types].xml中登记 override——python-docx 的 part 机制在部件注册时会自动补上。故事story中的范围标记——锚定文本之前放置w:commentRangeStart w:idN之后放置w:commentRangeEnd w:idN。引用 run——一个包含w:commentReference w:idN的w:r紧跟范围结束标记之后它把批注气泡与位置绑定。三者的位置关系可示意为w:p w:rw:tQ3 /w:t/w:r w:commentRangeStart w:id0/ w:rw:trevenue/w:t/w:r w:commentRangeEnd w:id0/ w:rw:commentReference w:id0//w:r /w:p六、docx_comments.pylist / add / delete 的实现细节docx_comments.py 提供三个子命令子命令说明关键参数list按批注输出 JSONid、author、initials、date、text、anchored_textpathadd在--target文本首次出现处锚定新批注--target、--text必填--author默认Hermes、--initials、--xmldelete按--id删除批注及其全部范围标记--id必填listXML 层的锚定文本重建list/delete始终工作在 XML 层因此能处理任何生产者生成的文档。anchored_text的重建算法见 docx_comments.py是遍历每个部件根同样复用iter_part_roots保证按文档顺序维护一个活跃 id 集合——遇到commentRangeStart加入 id遇到commentRangeEnd移除 id期间遇到的所有w:t文本都追加到该 id 的文本缓冲中。这保证跨 run、甚至跨段落锚定的文本都能被正确拼接。add先切分 run 再锚定add的第一步是把目标文本隔离成完整的 run。find_anchor_runs在全文正文表格页眉页脚经 docx_common.py 的iter_all_paragraphs中查找--target的首次出现若匹配起点或终点落在某个 run 中间_split_run会在边界处把 run 一分为二——切分时会深拷贝w:rPrright deepcopy(run_el)因此格式粗体、斜体、颜色等得以保留并且新w:t会设置xml:spacepreserve防止前后空格丢失。随后按环境二选一python-docx 1.2使用原生document.add_comment(runs, ...)API由 python-docx 自己创建 comments 部件、范围标记和引用 run见add_comment_native旧版本或显式--xml脚本自行构建word/comments.xml——通过 OPC 层创建Partpack URI 为/word/comments.xml内容类型为 commentsxml用part.relate_to(part, RT.COMMENTS)注册关系再手工插入范围标记与引用 run见add_comment_xml。为让编辑结果能写回保存代码还给 part 动态换上了自定义 blob 属性每次保存时重新序列化 live 的 XML 树。新批注的 id 由_next_id计算取 comments 部件中现存全部数字 id 的max 1避免冲突。delete同时清理四类痕迹删除批注会移除w:comment元素以及该 id 的全部三种标记commentRangeStart、commentRangeEnd、commentReference其中引用 run 标记还会连带删除其外层w:r见 docx_comments.py。被锚定的文档正文文本不受影响——这一点在测试中也被明确断言删除后docx_read.py --text仍能读到完整句子。commentsExtended.xml 的边界现代 Word 还会写出commentsExtended.xml用于记录回复threading与已解决resolved状态。脚本既不读取也不产出该部件回复和 resolved 标记在此不可见由本 Skill 添加的批注都是顶层top-level批注。这是使用前必须知晓的能力边界。七、实战组合完整操作流程结合 SKILL.md 的工作流一个典型的修订批注自动化场景如下# 1. 摸底是否有修订/批注 python3 docx_read.py report.docx --revisions # 2. 查看全部修订 python3 docx_revisions.py list report.docx # 3. 拒绝某条错误的插入按 id python3 docx_revisions.py reject report.docx --id 3 -o step1.docx # 4. 接受其余全部修订 python3 docx_revisions.py accept-all step1.docx -o step2.docx # 5. 在关键段落添加批注 python3 docx_comments.py add step2.docx --target Q3 revenue \ --text Needs a source --author Reviewer --initials R -o step3.docx # 6. 查看批注含锚定文本 python3 docx_comments.py list step3.docx # 7. 结构校验后交付 python3 docx_validate.py step3.docx其中第 7 步 docx_validate.py 做的是健康检查而非完整 XSD 校验验证 zip 可读、必需部件存在、所有关系可解析悬空引用报错、r:id/r:embed引用有效、嵌入图片非空且魔数正确、文档引用的样式 id 在 styles.xml 中存在并尝试用 python-docx 打开。任何 error 级问题都会使退出码为 1。八、测试套件如何背书这些语义这些行为并非仅靠文档描述端到端测试 test_docx_skill.py 直接以子进程方式运行脚本并断言结果TestRevisions构造同时含正文与表格单元格修订的文档_add_ins/_add_del直接向w:p注入w:ins/w:del验证list输出 4 条记录、accept-all后正文变为Base ADDED且表格变为Cell CELLADD、reject-all后为Base REMOVED/Cell CELLGONE、按--id单条决议只影响目标 id、未知 id 返回退出码 1。TestComments验证add→list→delete全链路——anchored_text精确等于目标文本、文档正文不受影响、--xml强制走回退路径后文件仍可被 python-docx 正常打开、目标文本不存在时报错退出。测试还固定了LC_ALLC与PYTHONIOENCODINGutf-8证明脚本在无本地化环境下的非 ASCII 文本处理是稳定的。这些测试文件位于 packages/ekko-agent/skills/docx/tests是阅读本文后继续深挖底层行为的最佳入口。九、总结与安全边界修订决议是纯 XML 层的确定性操作接受插入解包拒绝插入移除接受删除移除拒绝删除delText改名w:t后解包。批注由 comments 部件、范围标记、引用 run 三件套构成list/delete通用兼容任何生产者add会先切分 run 保留格式再选择原生 API 或 XML 回退路径。边界段落标记修订、表格行修订、格式变更、移动修订只检测不决议commentsExtended.xml的回复与 resolved 状态不可见。安全删除批注或批量决议修订属于破坏性操作应遵循 SKILL.md 的约定——先docx_read.py --revisions摸底、保留可恢复的原始副本、默认输出到新文件、操作后运行docx_validate.py校验并在布局敏感的文档上用 LibreOffice 渲染核对。对于需要对接 Word 协作工作流的 Agent 与自动化管线理解本文的 WordprocessingML 细节是避免修订丢失批注错位文件损坏等问题的前提。赞分享AI 应用人工智能AI Agent本地部署前端后端工作流自动化【免费下载链接】ekko-studioEkko Studio is a local-first AI workspace for multi-agent chat, coding, and visual workflows, available on desktop and the web.项目地址https://gitcode.com/gh_mirrors/he/ekko-studio点击查看免费下载相关推荐pandoc 批注处理实战深入解析 Word 修订与评论的 --track-changes 机制pandoc 批注处理实战深入解析 Word 修订与评论的 track changes 机制 导读 本文以 pandoc 仓库中的命令测试用例 test/co文档开发工具CLIpandoc 转换带 Word 修订标记的 docx 时如何设置 --track-changespandoc 转换带 Word 修订标记的 docx 时如何设置 track changes 如果你用 pandoc 转换由 Word 生成的 .docx 文文档开发工具CLIdocx 修订追踪Track Changes完整指南用 InsertedTextRun、DeletedTextRun 与 revision 属性生成带修订标记的 Word 文档docx 修订追踪Track Changes完整指南用 InsertedTextRun、DeletedTextRun 与 revision 属性生成带修订文档创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表