news 2026/9/14 9:38:27

Eigent PPTX 技能编辑指南:基于 XML 解包工作流精准修改 PowerPoint 模板

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Eigent PPTX 技能编辑指南:基于 XML 解包工作流精准修改 PowerPoint 模板

Eigent PPTX 技能编辑指南:基于 XML 解包工作流精准修改 PowerPoint 模板

【免费下载链接】eigentEigent: The Open Source Cowork Desktop - Local and Free Alternative to Claude Cowork and Codex项目地址: https://gitcode.com/GitHub_Trending/ei/eigent

在 Eigent 桌面应用中,PPTX 技能(Skill)负责处理一切与.pptx文件相关的任务:读取、解析、编辑、套用模板。当 Agent 需要基于一个已有演示文稿生成新文件时,editing.md 定义的"解包—改 XML—清理—打包"工作流就是其核心方法论。本文完整继承该文档的模板化编辑流程、五个配套脚本、幻灯片操作规则、内容编辑格式规范与常见陷阱,并结合resources/example-skills/pptx/scripts/下的真实源码,讲清每一步命令背后实际做了什么,帮助你理解 Agent 是如何在不破坏 OOXML 结构的前提下可靠地修改演示文稿的。

一、工作流总览:为什么走"解包-改 XML-打包"路线

PPTX 文件本质是一个 ZIP 压缩包,内部是遵循 OOXML 标准的一组 XML 文件(幻灯片、母版、布局、主题、媒体、关系文件等)。直接操作二进制 zip 或用黑盒 API 很难精确控制模板布局,而 Eigent 的 PPTX 技能选择了一条透明路线:把 pptx 解压成可读的 XML 目录,用精确编辑工具逐文件修改,再用带校验的打包器重新封装

SKILL.md 中的快速参考表给出了整个技能的任务路由:

任务指南
读取/分析内容python -m markitdown presentation.pptx
编辑或从模板创建阅读 editing.md
从零创建阅读 pptxgenjs.md

也就是说,editing.md 专门服务于"已有模板,我要基于它改"这一场景,与从零创建的 pptxgenjs 路线互补。

模板化工作流(Template-Based Workflow)

文档给出的七步流程如下,每一步都可直接复制执行:

1. 分析现有幻灯片

python scripts/thumbnail.py template.pptx python -m markitdown template.pptx

查看生成的thumbnails.jpg了解各页版式,查看 markitdown 输出了解占位文本。

2. 规划幻灯片映射(Plan slide mapping):为每个内容板块选择一个模板页。

文档特别强调使用多样化版式——单调的演示文稿是常见失败模式,不要默认只用"标题+要点"式版式。应主动寻找:

  • 多栏版式(两栏、三栏)
  • 图文组合
  • 全出血图片 + 文字叠加
  • 引言/强调页(Quote / callout)
  • 章节分隔页(Section dividers)
  • 数据/数字强调页(Stat callouts)
  • 图标网格或图标+文字行

避免:每一页都重复同一种文字密集的版式。应让内容类型匹配版式风格(如:要点→bullet 页,团队信息→多栏,用户评价→引言页)。

3. 解包

python scripts/office/unpack.py template.pptx unpacked/

4. 构建演示文稿(结构调整)

  • 删除不需要的幻灯片(从<p:sldIdLst>中移除)
  • 复制要复用的幻灯片(add_slide.py
  • <p:sldIdLst>中重排顺序
  • 务必在第 5 步之前完成所有结构性变更

5. 编辑内容:更新每个slide{N}.xml中的文本——每页幻灯片是独立的 XML 文件。

6. 清理

python scripts/clean.py unpacked/

7. 打包

python scripts/office/pack.py unpacked/ output.pptx --original template.pptx

二、五个配套脚本:文档说明 + 源码印证

文档附带的脚本总表如下:

脚本用途
unpack.py解压并格式化 PPTX
add_slide.py复制幻灯片或从布局新建
clean.py移除孤立文件
pack.py带校验的重新打包
thumbnail.py生成幻灯片视觉缩略图网格

下面逐个结合源码深入说明。

unpack.py:解压、美化、转义

python scripts/office/unpack.py input.pptx unpacked/

文档说明:解压 PPTX、格式化 XML、转义智能引号。源码 unpack.py 印证了这一点,并补充了几个文档未展开的细节:

  • 它同时服务.docx.pptx.xlsx三种后缀(L61);
  • 对所有*.xml*.rels文件调用toprettyxml(缩进两空格)进行美化,解析失败时静默跳过(L96-L102),这解释了为什么解包后 XML 是缩进整齐的;
  • 智能引号转义由SMART_QUOTE_REPLACEMENTS表实现:U+201C/201D/2018/2019 四种字符分别替换为&#x201C;等 XML 实体(L40-L45)。这正是后文"智能引号"陷阱的源头——解包阶段主动把 Unicode 引号变成实体,保证后续文本编辑不引入编码问题;
  • --merge-runs--simplify-redlines两个开关仅对 DOCX 生效,PPTX 编辑流程不受影响(L76-L83)。

add_slide.py:唯一被允许的"新增幻灯片"方式

python scripts/add_slide.py unpacked/ slide2.xml # 复制幻灯片 python scripts/add_slide.py unpacked/ slideLayout2.xml # 从布局新建

两种来源(见 add_slide.py 的模块 docstring):

  • 传入slide{N}.xml:复制该幻灯片,自动生成slide{下一个序号}.xml
  • 传入slideLayout{N}.xml:基于版式创建一个空幻灯片骨架(内置最小<p:sld>模板,L62-L84)。

脚本执行后会打印一段<p:sldId>片段,由你手动插入presentation.xml<p:sldIdLst>期望位置(L101、L141)。

从源码可以看到,手动复制幻灯片文件会漏掉的三件事,脚本都会自动处理:

  1. Content_Types 登记:向[Content_Types].xml追加新幻灯片的 Override 条目(_add_to_content_types);
  2. 关系 ID:在ppt/_rels/presentation.xml.rels中分配下一个rId并添加 slide 类型的 Relationship(_add_to_presentation_rels);
  3. notes 引用剥离:复制幻灯片时会用正则把源.rels中的 notesSlide 关系删除,避免两页共享同一份演讲者备注(L126-L132)。

此外,新幻灯片的id取自现有<p:sldId>最大值 +1,无幻灯片时从 256 起(_get_next_slide_id)——这也是文档强调"绝不要手动复制幻灯片文件"的原因:以上任何一步漏掉都会导致 PowerPoint 打开时报损坏。

clean.py:引用图驱动的垃圾回收

python scripts/clean.py unpacked/

文档说明:移除不在<p:sldIdLst>中的幻灯片、未被引用的媒体、孤立的 rels。源码 clean.py 的 docstring 给出了完整清理清单,比文档表格更细:

  • 不在 sldIdLst 中的孤立幻灯片及其.rels(remove_orphaned_slides,并同步从presentation.xml.rels移除对应关系);
  • [trash]目录(L105-L117);
  • charts/diagrams/drawings 下的孤儿.rels(L142-L164);
  • mediaembeddingschartsdiagramstagsdrawingsink七个资源目录中未被任何.rels引用的文件,以及未引用的 theme、notesSlide(remove_orphaned_files);
  • 最后同步删除[Content_Types].xml中对应 Override(update_content_types)。

值得注意的实现细节:主循环 clean_unused_files 用while True反复执行"删孤儿 rels → 重新扫描引用图 → 删孤儿文件",直到一轮删不动为止——因为删除一个资源后可能连带使其 rels 文件也成为孤儿,需要级联回收。这也意味着文档中"删幻灯片后运行 clean.py"一步,实际是保证包内不残留任何不可达对象的安全网。

pack.py:先自动修复、再校验、后压缩

python scripts/office/pack.py unpacked/ output.pptx --original input.pptx

文档说明:校验、修复、压缩 XML、重新编码智能引号。源码 pack.py 的实际流程是:

  1. 当传入--original时,先运行校验器。PPTX 走PPTXSchemaValidator,会依次做:XML 良构性、命名空间、ID 唯一性、UUID 形态、文件引用存在性、slideMaster 中sldLayoutId引用合法性、Content-Types 一致性、XSD schema 校验、备注页引用唯一性、slideLayout 引用不重复等十余项检查(validate());
  2. 校验前先执行repair()自动修复,并打印Auto-repaired N issue(s)(pack.py#L110-L117);
  3. 复制一份到临时目录,对所有*.xml/*.rels执行_condense_xml:删除标签间纯空白文本节点和注释,把 unpack 阶段美化产生的缩进"压缩"回紧凑形态——且明确跳过*:t文本元素,保住正文中的空格;
  4. ZIP_DEFLATED压缩打包输出。--validate false可跳过第 1 步(L155-L161)。

从源码结构看,校验失败(Validation failed)会直接中止打包,这使pack.py成为整个工作流的质量闸门:能走通 pack 的目录,大概率能被 PowerPoint 正常打开。

thumbnail.py:只用于模板分析,不用于最终 QA

python scripts/thumbnail.py input.pptx [output_prefix] [--cols N]

生成thumbnails.jpg,每格标注对应幻灯片文件名。文档强调它只用于模板分析(选择版式);最终视觉 QA 应走 SKILL.md 中的soffice+pdftoppm高清单页渲染路线。源码 thumbnail.py 给出了文档未展开的默认值与上限:

  • 缩略图宽 300px、渲染 DPI 100、JPEG 质量 95(L43-L47);
  • --cols默认 3,最大 6,超出会降级并告警(L74-L76);
  • 每张网格最多cols × (cols+1)页(默认 3 列即每格 12 页,与文档"max 12 per grid"一致,create_grids),超出自动拆分为prefix-1.jpgprefix-2.jpg
  • 隐藏幻灯片(show="0")不渲染,用斜线占位图并标注(hidden)(create_hidden_placeholder)——在模板分析时这是个实用信号:带斜线的格子不可用作版式来源。

三、幻灯片操作(Slide Operations)

文档的核心断言:幻灯片顺序由ppt/presentation.xml中的<p:sldIdLst>决定。三个操作的具体规则:

  • 重排(Reorder):直接调整<p:sldId>元素顺序即可,无需动任何幻灯片文件;
  • 删除(Delete):移除<p:sldId>条目,然后运行clean.py回收幻灯片文件、rels、媒体与 Content-Types 条目(对应 clean.py 的 remove_orphaned_slides);
  • 新增(Add):必须使用add_slide.py绝不要手动复制幻灯片文件——脚本会处理 notes 引用、Content_Types.xml 与关系 ID 这些手动复制必然遗漏的环节(前文 add_slide.py 一节已逐一印证)。

四、编辑内容(Editing Content)

工具选择:用 Edit 工具而非 sed 或 Python

文档明确:编辑 XML 内容应使用精确的 Edit 工具,而不是 sed 或 Python 脚本。理由是 Edit 工具强制你指明"替换什么、在哪里替换",可靠性更高。这一规则对 Agent 执行尤其重要:批量正则替换很容易误伤<a:t>文本中出现的形似标签的内容。

格式规则(Formatting Rules)

  • 标题、小标题、行内标签全部加粗:在<a:rPr>上加b="1"。范围包括:
    • 幻灯片标题
    • 页内章节小标题
    • 行首的行内标签(如 "Status:"、"Description:")
  • 绝不使用 Unicode 项目符号(•):应使用<a:buChar><a:buAutoNum>实现真正的列表格式。配套的 pptxgenjs.md 中也有同样警告——直接写 "• First item" 会产生双重项目符号;
  • 项目符号继承优先:让 bullet 从版式(layout)继承。确需显式声明时只允许<a:buChar><a:buNone>,不要自造其他属性。

智能引号(Smart Quotes)

解包/打包阶段自动处理智能引号,但Edit 类工具会把智能引号转换成 ASCII。因此新增带引号的文本时,必须写 XML 实体:

<a:t>the &#x201C;Agreement&#x201D;</a:t>
字符名称UnicodeXML 实体
左双引号U+201C&#x201C;
右双引号U+201D&#x201D;
左单引号U+2018&#x2018;
右单引号U+2019&#x2019;

该表与 unpack.py 的 SMART_QUOTE_REPLACEMENTS 一一对应,保证解包侧的实体化与打包侧的反解码闭环。

其他注意点

  • 空白:首尾含空格的<a:t>必须加xml:space="preserve",否则空白会被 XML 解析器吞掉;
  • XML 解析库:需要程序化处理时用defusedxml.minidom,不要用xml.etree.ElementTree——后者会破坏命名空间。这一选择在整个脚本库中得到了贯彻:unpack.py、clean.py、thumbnail.py 全部 import 的是defusedxml.minidom

五、常见陷阱(Common Pitfalls)

5.1 模板适配(Template Adaptation)

源内容条目少于模板时

  • 多余元素要整体删除(图片、形状、文本框),而不是只清空文字;
  • 清空文本后检查是否残留孤立视觉元素;
  • 运行视觉 QA 核对数量是否匹配。

文档给出一条关键等式:模板槽位 ≠ 源数据条目。例如模板画了 4 位团队成员而源数据只有 3 人,应删除第 4 位成员的整个组合(图片 + 文本框),而不是留一个空框。

替换为不同长度文本时

  • 更短的替换通常安全;
  • 更长的替换可能溢出或意外换行;
  • 文本改动后必须做视觉 QA;
  • 必要时截断或拆分内容以适应模板的设计约束。

5.2 多条目内容:每个条目独立段落

当源内容包含多个条目(编号列表、多个小节)时,每个条目必须创建独立的<a:p>段落,绝不拼成一个字符串

错误示范——所有条目挤在一个段落里:

<a:p> <a:r><a:rPr .../><a:t>Step 1: Do the first thing. Step 2: Do the second thing.</a:t></a:r> </a:p>

正确示范——独立段落 + 加粗小标题:

<a:p> <a:pPr algn="l"><a:lnSpc><a:spcPts val="3919"/></a:lnSpc></a:pPr> <a:r><a:rPr lang="en-US" sz="2799" b="1" .../><a:t>Step 1</a:t></a:r> </a:p> <a:p> <a:pPr algn="l"><a:lnSpc><a:spcPts val="3919"/></a:lnSpc></a:pPr> <a:r><a:rPr lang="en-US" sz="2799" .../><a:t>Do the first thing.</a:t></a:r> </a:p> <a:p> <a:pPr algn="l"><a:lnSpc><a:spcPts val="3919"/></a:lnSpc></a:pPr> <a:r><a:rPr lang="en-US" sz="2799" b="1" .../><a:t>Step 2</a:t></a:r> </a:p> <!-- continue pattern -->

要点:从原段落复制<a:pPr>以保留行距(如上例中3919百分之一的spcPts行距设置),标题行使用b="1"加粗。若把多条目压进一个<a:t>,PowerPoint 会把它渲染成一行连续文字,版式完全失控。

六、端到端执行清单与 QA 衔接

把以上规则串起来,一次完整的模板化编辑按序执行:

# 1. 分析模板 python scripts/thumbnail.py template.pptx # → thumbnails.jpg(选版式) python -m markitdown template.pptx # → 占位文本清单 # 3. 解包 python scripts/office/unpack.py template.pptx unpacked/ # 4. 结构调整(在编辑文本之前完成!) python scripts/add_slide.py unpacked/ slide2.xml # 输出待插入的 <p:sldId> # 编辑 unpacked/ppt/presentation.xml 的 <p:sldIdLst>:增/删/排序 # 5. 编辑内容:精确编辑 unpacked/ppt/slides/slide{N}.xml # - 标题/小标题/行内标签加粗(b="1") # - 多条目用多个 <a:p>,引号用 &#x201C; 等实体 # - 模板槽位多于源数据时整组删除 # 6. 清理 python scripts/clean.py unpacked/ # 7. 打包(自动校验 + 修复) python scripts/office/pack.py unpacked/ output.pptx --original template.pptx

打包成功后,QA 阶段衔接 SKILL.md 的验证循环:先跑内容 QA(python -m markitdown output.pptx,并用grep -iE "xxxx|lorem|ipsum|this.*(page|slide).*layout"揪出残留占位符),再做视觉 QA(python scripts/office/soffice.py --headless --convert-to pdf output.pptxpdftoppm -jpeg -r 150逐页检查)。SKILL.md 要求"假设一定有问题",至少完成一轮"修复—复检"循环才可宣告成功——这一点对长文本替换可能溢出的场景尤其重要。

七、依赖与环境前提

执行上述命令需要以下依赖(来自 SKILL.md 的 Dependencies 一节):

  • pip install "markitdown[pptx]"— 文本抽取;
  • pip install Pillow— 缩略图网格(thumbnail.py 依赖);
  • LibreOffice(soffice)— PDF 转换,脚本通过 soffice.py 为沙箱环境自动配置;
  • Poppler(pdftoppm)— PDF 转图片。

需要注意的适用前提:thumbnail.py 在scripts/目录下运行from office.soffice import ...(thumbnail.py#L40),意味着命令需要以resources/example-skills/pptx/scripts/为工作目录执行,使office包可导入;pack 的自动修复与校验依赖lxml与 XSD schema(位于 scripts/office/schemas/ISO-IEC29500-4_2016/,含pml.xsddml-main.xsd等 PresentationML/DrawingML 模式文件)。

八、小结

editing.md 的价值在于把"改 PPT"这件黑盒操作拆解成一条可审计的流水线:thumbnail 分析 → unpack 解包 → 先结构后内容 → clean 级联回收 → pack 校验打包。源码印证了几个关键设计决策:add_slide.py自动维护 Content_Types、rels 与 slide id 三处登记并剥离共享备注引用;clean.py以引用图做级联垃圾回收;pack.py用 XSD 校验器加自动修复作为最后一道闸门;智能引号在 unpack 阶段实体化、pack 阶段还原,形成闭环。掌握了这套规则,无论是人工操作还是为 Agent 编写提示词,都能在不破坏 OOXML 结构的前提下可靠地基于任意模板产出结构合法、版式多样的演示文稿。

【免费下载链接】eigentEigent: The Open Source Cowork Desktop - Local and Free Alternative to Claude Cowork and Codex项目地址: https://gitcode.com/GitHub_Trending/ei/eigent

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 9:37:39

程序员35岁危机:技术迭代与职业破局之道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 9:34:06

基于JSP+SSM的大学生创业创新网站开发实践

1. 项目概述这个Java毕业设计项目选题"jspssm大学生创业创新网站"是一个典型的基于Java EE技术栈的Web应用开发实践。作为一名有多年Java开发经验的工程师&#xff0c;我认为这个选题非常适合计算机相关专业的毕业设计&#xff0c;因为它涵盖了从数据库设计到前端展示…

作者头像 李华
网站建设 2026/9/14 9:33:32

SpringBoot+Vue智能健康推荐系统开发实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 9:33:25

西门子PLC模拟量编程:揭秘27648的由来与工程值换算

1. 为什么每个西门子工程师都绕不开 27648做西门子 PLC 的同学应该都有过这种经历&#xff1a;第一次接触模拟量编程&#xff0c;翻开手册看到“单极性 0&#xff5e;27648”“双极性 -27648&#xff5e;27648”&#xff0c;第一反应基本都是——这数字也太奇葩了&#xff0c;为…

作者头像 李华