Python xml.etree.ElementTree处理Word XML后命名空间被重命名,Word无法读取
解决ElementTree保存Word XML后命名空间被重命名的问题
问题根源
xml.etree.ElementTree默认会给未手动注册的命名空间自动生成ns1、ns2这类随机别名,但Word的OOXML格式依赖固定的前缀(比如w:对应WordprocessingML核心命名空间),别名替换后Word无法识别文档的结构逻辑,自然就打不开文件了。
具体解决方案
你需要手动绑定命名空间前缀,并调整保存参数,同时修复代码里的小问题,具体步骤如下:
1. 提前注册命名空间前缀
在代码开头添加命名空间注册代码,让ElementTree使用Word认可的前缀,而不是自动生成别名:
ET.register_namespace('w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main')
2. 保存时指定必要参数
调用tree.write()时,必须指定xml_declaration=True和encoding='UTF-8',这是Word XML文档要求的标准格式。
3. 修复代码中的语法与容错问题
- Python中判断不等要用
!=,而不是<>(这是旧版本Python的语法,现在已经废弃) - 处理文本节点时要考虑
t.text为None的情况,避免索引报错
修改后的完整代码
import xml.etree.ElementTree as ET import re # 注册Word核心命名空间的前缀,避免自动生成别名 ET.register_namespace('w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main') tree = ET.parse('FL0809spec2.xml') root = tree.getroot() l = ['', ''] prev = None count = 0 for t in root.iter('{http://schemas.openxmlformats.org/wordprocessingml/2006/main}t'): # 处理文本为None的情况,转为空字符串避免报错 current_text = t.text or '' l[0] = l[1] l[1] = current_text if l[0] != '' and l[1] != '' and re.search(r'[a-zA-Z]', l[0][-1]) and re.search(r'[a-z]', l[1][0]): words = re.findall(r'(\b\w+\b)(\W+)', l[1]) if len(words) > 0: # 容错处理prev.text为None的情况 prev.text = (prev.text or '') + words[0][0] t.text = current_text[len(words[0][0]):] count += 1 prev = t # 按Word要求的格式保存XML tree.write('FL0809spec2Improved.xml', xml_declaration=True, encoding='UTF-8')
额外提示
如果你的文档里还用到了其他命名空间(比如r:对应关系、a:对应绘图等),只需要用同样的ET.register_namespace方法注册对应的前缀和URL即可,比如:
ET.register_namespace('r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships')
内容的提问来源于stack exchange,提问作者Bman425




