4.1 KiB
4.1 KiB
占位符提取功能修复总结
问题描述
在测试占位符提取功能时,发现使用 docxtemplater 库的 getFullText() 方法会因为 Word 文档中的格式化(粗体、斜体等)导致占位符标签被分割成多个 XML 元素,从而引发编译错误。
原始错误
Error: Duplicate open tag, expected one open tag
Error: Duplicate close tag, expected one close tag
这是因为 Word 文档中的 {{占位符}} 可能被格式化标签分割,例如:
{{地市名称}}可能在 XML 中被分割为{{地市和名称}}- 这导致 docxtemplater 在编译时检测到重复的开/闭标签
解决方案
核心思路
不使用 docxtemplater 进行编译,而是直接读取 word/document.xml 文件,移除 XML 标签后提取占位符。
实现步骤
-
使用 PizZip 解压 docx 文件
const zip = new PizZip(content); -
直接读取 document.xml
const documentXml = zip.file('word/document.xml'); const xmlContent = documentXml.asText(); -
移除所有 XML 标签,只保留纯文本
const fullText = xmlContent.replace(/<[^>]+>/g, ''); -
使用正则表达式提取占位符
const placeholderRegex = /\{\{([^}]+)\}\}/g; const matches = fullText.matchAll(placeholderRegex);
优势
✅ 避免格式化问题 - 不受 Word 文档格式化的影响 ✅ 更简单 - 不需要创建 docxtemplater 实例 ✅ 更快 - 跳过编译步骤,直接提取 ✅ 更可靠 - 适用于任何格式化的 docx 文件
修改的文件
1. app/api/contracts/docx-parser.server.ts
修改前:使用 docxtemplater.getFullText()
const doc = new Docxtemplater(zip, {
paragraphLoop: true,
linebreaks: true,
});
const fullText = doc.getFullText();
修改后:直接读取 XML
const documentXml = zip.file('word/document.xml');
const xmlContent = documentXml.asText();
const fullText = xmlContent.replace(/<[^>]+>/g, '');
2. scripts/test-docx-parser.cjs
- 重命名:
test-docx-parser.js→test-docx-parser.cjs(适配 ES 模块项目) - 移除了
docxtemplater依赖 - 使用相同的 XML 读取方法
3. docs/docxtemplater-placeholder-extraction.md
更新文档以反映新的实现方式:
- 技术栈:移除 docxtemplater,强调使用 pizzip + 正则表达式
- 工作流程:更新为直接读取 XML 的流程
- 代码示例:更新为新的实现
测试结果
运行 node scripts/test-docx-parser.cjs 成功提取了 18 个占位符:
✅ 文件读取成功, 大小: 18.95 KB
✅ PizZip 解压成功
✅ document.xml 读取成功
✅ XML 内容长度: 33378
✅ 提取纯文本成功
文本长度: 5047
找到 18 个占位符:
1. {{地市名称}}
2. {{合同名称}}
3. {{合同编号}}
4. {{项目编号}}
5. {{市名}}
6. {{区名}}
7. {{年}}
8. {{月}}
9. {{日}}
10. {{有效期限}}
11. {{甲方名称}}
12. {{甲方注册地址}}
13. {{甲方法定代表人}}
14. {{甲方联系电话}}
15. {{乙方名称}}
16. {{乙方注册地址}}
17. {{乙方法定代表人}}
18. {{乙方联系电话}}
智能分类
系统自动推测了字段类型和分组:
- 基本信息:地市名称、合同名称、合同编号等
- 甲方信息:甲方名称、甲方注册地址(textarea)、甲方法定代表人、甲方联系电话
- 乙方信息:乙方名称、乙方注册地址(textarea)、乙方法定代表人、乙方联系电话
类型检查
运行 npm run typecheck 确认没有引入新的类型错误。所有显示的错误都是代码库中的既有问题,与本次修改无关。
总结
✅ 问题已解决 - 占位符提取功能正常工作 ✅ 测试通过 - 成功从测试文档中提取 18 个占位符 ✅ 类型安全 - 没有引入新的 TypeScript 错误 ✅ 文档更新 - 文档已更新以反映新的实现方式
功能已经可以集成到实际应用中使用。下一步可以:
- 启动开发服务器测试完整流程
- 验证占位符表单渲染
- 测试一键替换功能