使用Python将Word文档转换为XML的实践要点总结
作者:缺点内向
Word 文档在内容编排上足够灵活,但当需要把文档内容送入下游系统做结构化处理时,XML 往往是更合适的中转格式。无论是构建文档内容索引、做数据抽取,还是与旧版系统对接,将 .docx 转换为 XML 都是一项基础操作。Python 生态中能处理 Word 的库不少,但专门为格式转换设计的选项相对有限。本文围绕 Spire.Doc for Python,梳理 Word 转 XML 的代码实现、批量处理中的资源管理,以及转换时需要注意的几个实际问题。
环境准备
Spire.Doc for Python 是一个独立的 Word 文档处理库,转换过程不依赖 Microsoft Word 或 Office 组件。安装通过 pip 完成:
pip install Spire.Doc
导入时需要注意,Document 类与 FileFormat 枚举分别位于不同的模块:
from spire.doc import * from spire.doc.common import *
FileFormat 是指定输出格式的关键,它决定了 SaveToFile 方法最终生成的文件类型。
基础转换:单文件输出
单文件转换的代码量很小,核心只有三步:加载、保存、释放。
from spire.doc import *
from spire.doc.common import *
document = Document()
document.LoadFromFile("sample.docx")
document.SaveToFile("output.xml", FileFormat.Xml)
document.Close()
这段代码的行为很直接:LoadFromFile 读取磁盘上的 Word 文件,SaveToFile 将其序列化为 XML 格式。生成的 .xml 文件可以用任何文本编辑器查看,适合作为数据管道中的中间产物。对于只需要提取文字内容与基本段落结构的场景,这种方式足够简洁。
输出格式的选择
实际使用中容易混淆的是与 XML 相关的几个格式枚举。它们都产出 XML 结构,但语义层次不同:
| 格式枚举 | 输出扩展名 | 典型用途 |
|---|---|---|
FileFormat.Xml | .xml | 通用结构化数据 |
FileFormat.WordXml | .wordxml | 保留 Word 排版语义 |
FileFormat.WordML | .wordml | Word 2003 格式兼容 |
FileFormat.Xml 输出的是较为扁平的通用 XML,适合下游只做通用解析的场景。FileFormat.WordXml 对应 Word 2007 及之后版本使用的 WordprocessingML,内部结构遵循 Office Open XML 规范,保留了段落样式、字体信息、表格结构等 Word 特有语义,适合需要回写 Word 或做精细排版分析的情况。FileFormat.WordML 则是 Word 2003 使用的旧版 XML 格式,主要用于与遗留系统对接。
选择哪一种,取决于下游系统需要什么。如果对方只是一个通用的 XML 解析器,FileFormat.Xml 的输出最直接;如果下游需要理解“这是标题”“这是表格”这类 Word 语义,则应该选择 WordXml。这一项属于转换前需要先确认的实践要点。
批量处理与资源管理
单文件转换的代码量很小,但实际工作中往往需要处理成批的文档。在循环中反复创建 Document 对象时,资源释放需要留意。Document 对象持有文件句柄和内部资源,如果只依赖 Python 的垃圾回收,在处理大量文件时可能出现内存持续增长的情况。
一个稳妥的做法是在每次转换后显式调用 Close(),并在循环中适当触发回收:
import os
import gc
from spire.doc import *
from spire.doc.common import *
input_dir = "./docs"
output_dir = "./xml_output"
os.makedirs(output_dir, exist_ok=True)
for filename in os.listdir(input_dir):
if filename.endswith((".doc", ".docx")):
doc = Document()
try:
doc.LoadFromFile(os.path.join(input_dir, filename))
out_name = os.path.splitext(filename)[0] + ".xml"
doc.SaveToFile(os.path.join(output_dir, out_name), FileFormat.Xml)
finally:
doc.Close()
del doc
gc.collect()
这段代码的要点在于 try...finally 结构:无论加载或保存是否成功,Close() 都会被调用。del doc 配合 gc.collect() 进一步帮助释放底层资源。对于几十个文件的批量任务,这样做与不做之间的内存差异可能并不明显;但当文件数量上升到数百甚至上千时,显式管理资源就是必要的了。
转换中的其他注意事项
格式保真度的边界。 将 Word 转为 XML 时,并非所有 Word 特性都能无损映射。复杂排版如文本框嵌套、艺术字、某些域代码,在 XML 输出中可能以简化或变形的方式呈现。如果转换结果要用于严格的文档重建,建议先用包含代表性元素的文档做测试,确认关键排版信息是否保留。
免费版本的功能限制。 根据官方说明,免费版本在读取或写入 Word 文件时存在段落数(500 段)和表格数(25 个)的限制。这一限制作用于文档的加载与保存环节,因此 Word 转 XML 的输出完整性同样会受到影响。如果处理的文档段落或表格数量接近或超过上述阈值,输出结果可能不完整。建议在实际使用前用具有代表性的文档验证输出范围。
编码与命名空间。 生成的 XML 文件默认采用 UTF-8 编码,但 WordXml 格式的输出会包含 Office 命名空间声明。如果下游解析器对命名空间敏感,需要在解析时做相应处理。对于普通 XML 输出(FileFormat.Xml),结构相对扁平,命名空间负担较小。
方法补充
方案一:直接解压 .docx,拿到原生 OOXML(最忠实)
.docx 是 Office Open XML 格式,内部就是一组 XML 文件打包成 ZIP。核心文件是 word/document.xml(正文),此外还有 styles.xml、numbering.xml、settings.xml、_rels/.rels 等。
import zipfile
import os
def docx_to_ooxml(docx_path, output_dir):
"""解压 docx,提取全部 XML 部件,保留原始目录结构"""
os.makedirs(output_dir, exist_ok=True)
with zipfile.ZipFile(docx_path) as z:
for name in z.namelist():
if name.endswith(('.xml', '.rels')):
z.extract(name, output_dir)
print(f"已提取到 {output_dir},正文文件: {output_dir}/word/document.xml")
docx_to_ooxml("input.docx", "ooxml_out")适用场景:需要完整保留 Word 的段落、表格、样式、编号、页眉页脚、批注、图片引用关系。这是唯一不丢失任何信息的“转换”方式,因为严格说它不是转换,而是提取——docx 本来就是 XML。
局限:输出是 Word 的复杂 OOXML 结构,命名空间多、层级深,直接阅读或做二次处理不友好。如果目的是“给人看”或“喂给别的系统”,通常需要方案二。
方案二:python-docx 提取内容,生成自定义 XML(最可控)
如果目标是一个结构清晰、字段明确的 XML,而不是 Word 的原始 OOXML,用 python-docx 读取段落、表格、样式,再用 ElementTree 生成自定义结构。
from docx import Document
import xml.etree.ElementTree as ET
def docx_to_custom_xml(docx_path, xml_path):
doc = Document(docx_path)
root = ET.Element("document")
body = ET.SubElement(root, "body")
for para in doc.paragraphs:
p = ET.SubElement(body, "paragraph")
p.set("style", para.style.name if para.style else "")
p.text = para.text
for table in doc.tables:
t = ET.SubElement(body, "table")
for row in table.rows:
r = ET.SubElement(t, "row")
for cell in row.cells:
c = ET.SubElement(r, "cell")
c.text = cell.text
tree = ET.ElementTree(root)
ET.indent(tree, space=" ")
tree.write(xml_path, encoding="utf-8", xml_declaration=True)
print(f"已生成 {xml_path}")
docx_to_custom_xml("input.docx", "output.xml")生成的 XML 大致是:
<document>
<body>
<paragraph style="Heading 1">标题</paragraph>
<paragraph style="Normal">正文段落</paragraph>
<table>
<row><cell>单元格A</cell><cell>单元格B</cell></row>
</table>
</body>
</document>适用场景:需要把 Word 内容接入自己的系统、做结构化分析、或生成便于人工阅读的 XML。
几个必须注意的点:
cell.text对合并单元格会重复返回同一内容。如果表格有水平合并,同一单元格对象会在多个网格位置出现,需要按table._cells处理或去重。- 段落内的 run 级样式(加粗、斜体、颜色)默认丢失。上面的代码只取
para.text。如果需要保留 run 级信息,要遍历para.runs,读取run.bold、run.italic、run.font.name等属性。 - 图片、公式、超链接不会出现在
paragraphs的纯文本里。图片需要解析document.part.related_parts,超链接需要读paragraph._p的 XML 节点。 style.name是样式显示名,中文文档里可能是“标题 1”“正文”,不是英文的 “Heading 1”。做下游处理时不要硬编码英文样式名。
方案三:pypandoc 转换为通用文档 XML
如果目标是 DocBook、Pandoc AST XML 这类跨格式标准,而不是 Word 原生结构,用 Pandoc:
import pypandoc
# 输出 DocBook XML
pypandoc.convert_file("input.docx", "docbook", outputfile="output.dbk.xml")
# 输出 Pandoc AST 的 XML 表示
pypandoc.convert_file("input.docx", "xml", outputfile="output.ast.xml")适用场景:需要把 Word 转成一种通用中间格式,再转去 HTML、LaTeX、EPUB 等。Pandoc 的解析能力强,对标题、列表、表格、脚注的语义识别比 python-docx 更完整。
局限:输出的不是 Word 的 OOXML,而是 Pandoc 自己的文档模型。如果需要“Word 原生 XML”,这条路走不通。
小结
Word 转 XML 在代码层面并不复杂,LoadFromFile 与 SaveToFile 两次调用即可完成基本转换。但能够完成转换与输出结果可直接使用之间仍存在差距,输出格式决定了 XML 的语义层次,资源释放影响批量任务的稳定性,而保真度、版本限制与编码细节则关系到转换结果能否顺利进入下游流程。这些问题单独来看并不复杂,却往往在转换任务从示例代码转向实际应用时才会显现。建议先以规模适中、具有代表性的文档进行验证,再扩展至正式流程,通常比事后排查输出异常更为高效。
到此这篇关于使用Python将Word文档转换为XML的实践要点总结的文章就介绍到这了,更多相关Python Word转XML内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
