如何将Word文档(DOCX)中的XML内容进行映射?

DOCX文件本质是ZIP压缩包,含document.xml、styles.xml等XML文件,需解压后按命名空间解析,样式与编号须跨文件关联,盲目映射易出错。

DOCX 文件本质是 ZIP 压缩包,内部包含多个 XML 文件(如 document.xmlstyles.xmlnumbering.xml),直接“映射 XML 内容”没有通用标准——你得先明确想映射什么:是提取文字结构?还原样式逻辑?还是把 DOCX 的 XML 节点转成自定义 JSON 模型?否则任何“映射”都是盲操作。

用 Python 解压并定位关键 XML 文件

DOCX 不是纯 XML,而是 ZIP 封装。不能直接用 xml.etree.ElementTree 读取 .docx 文件本身,必须先解压或用 zipfile 随机访问。

  • document.xmlword/document.xml,存正文段落、运行(run)、文本(t)等核心内容
  • styles.xmlword/styles.xml,定义段落样式(w:pStyle)和字符样式(w:rStyle
  • numbering.xmlword/numbering.xml,控制编号列表逻辑,与 document.xml 中的 w:numId 关联
  • 所有路径区分大小写,Windows 上可能不敏感,Linux/macOS 会报 KeyError

解析 document.xml 时注意命名空间(namespace)

Office Open XML 使用默认命名空间 https://www./link/0f18e4824fc601cd270a4d31b084bb5d,几乎所有元素(如 w:pw:t)都属于它。忽略命名空间会导致 find()iter() 返回空。

import xml.etree.ElementTree as ET
from zipfile import ZipFile

with ZipFile("example.docx") as docx: with docx.open("word/document.xml") as f: tree = ET.parse(f) root = tree.getroot()

必须声明命名空间,否则找不到节点

NS = {"w": "https://www./link/0f18e4824fc601cd270a4d31b084bb5d"} paragraphs = root.findall(".//w:p", NS) # 正确

paragraphs = root.findall(".//p") # 错误:返回 []

for p in paragraphs: texts = [t.text for t in p.iterfind(".//w:t", NS) if t.text] print("".join(texts))

样式与编号需跨文件关联,不能只看 document.xml

DOCX 的样式不是内联属性,而是通过 ID 引用:一个段落有 w:pPr/w:pStyle[@w:val="Heading1"],但“Heading1”具体长什么样,得去 styles.xml 查;同理,编号 ID(w:numId)指向 numbering.xml 里的定义。硬编码匹配 ID 字符串极易出错。

  • lxml(支持 XPath 和更稳的命名空间处理)比原生 xml.etree 更可靠
  • 不要手动拼接 numIdabstractNumId,它们是两级映射,numbering.xml 里有 w:abstractNumw:num 两个层级
  • 若需还原“标题 1 → HTML

    ”,建议建映射表:{"Heading1": "h1", "Normal": "p"},而非解析 styles.xml 的全部格式细节

真正难的不是读 XML,而是理解 DOCX 的隐式依赖链:一个带编号的标题段落,可能

同时牵扯 document.xml(内容+ID)、styles.xml(标题样式)、numbering.xml(编号格式)、甚至 fonts.xml(字体 fallback)。没理清这个链条就写映射逻辑,十有八九漏掉缩进、多级列表或条件样式。