【问题标题】:Python XML parser renames namespace variablesPython XML 解析器重命名命名空间变量
【发布时间】:2018-05-24 14:43:57
【问题描述】:

我一直在使用 xml.etree.ElementTree 来解析 Word XML 文档。进行更改后,我使用tree.write('test.xml') 将树写入文件。保存 XML 后,Word 无法读取该文件。查看 XML,似乎新 XML 已重命名所有名称空间。

例如 w:t 变成 ns2:t

import xml.etree.ElementTree as ET
import re

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'):
    l[0] = l[1]
    l[1] = t.text
    if(l[0] <> '' and l[1] <> '' and re.search(r'[a-zA-Z]', l[0][len(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 = prev.text + words[0][0]
            t.text = t.text[len(words[0][0]):]
            count += 1
    prev = t

tree.write('FL0809spec2Improved.xml')

【问题讨论】:

  • a) 如果您的代码没有做任何更改,只是直接写回,命名空间名称是否会更改? b)只要命名空间定义相同,在 XML 术语中,我认为命名空间的实际名称是什么并不重要 - 问题可能是单词而不是 ElementTree
  • 正如您在代码中看到的,在 ElemenTree 中,对 t 命名空间的引用不是物理 XML 中的名称,而是命名空间 URI。
  • 有没有办法强制 ElementTree 使用与原来相同的命名空间引用?
  • 不知道 - 去看看源代码?
  • 看起来 lxml 可以更好地控制命名空间前缀(显然正确的术语是前缀)参见lxml.de/tutorial.html#namespaces 和 nsmap - 除此之外,我相信 lxml 具有与 ElementTree 类似的 API,因此可能不需要其他更改

标签: python xml-parsing


【解决方案1】:

看来:

a) Python 内置的 xml.etree.ElementTree 不是幂等的(透明的)——如果你读取一个 XML 文件然后立即写出 xml,输出与输入不同。例如,名称空间前缀已更改。初始的 ?xml 和 ?mso 标记也被删除。可能还有其他差异。删除两个初始标记似乎无关紧要,因此 Word 不喜欢 XML 的其余部分。

和 b) MS Word 期望命名空间使用与其生成的 xml 文件完全相同的前缀编写 - IMO 这是非常糟糕的(如果不是令人震惊的)风格,因为在纯 XML 术语中,它是命名空间 URI 定义命名空间,而不是用于引用它的前缀,但是嘿,这似乎是它的工作方式。

只要你不介意安装lxml,解决你的问题就很容易了。令人高兴的是,lxml.etree.ElementTree 似乎比 xml.etree.ElementTree 在写入它已读取的内容时不更改任何内容更加坚定,至少它保留了读入的前缀,并且前两个标签也被写入。

所以要使用lxml:

用 pip 安装 xlmx:

pip install lxml

将代码的第一行更改为:

import xml.etree.ElementTree as ET

到:

from lxml import etree as ET

然后(在我对您的代码的测试中,删除了读取和写入 xml 之间的变化位)输出文档可以在 MS Word 中打开而不会出现错误:-)

【讨论】:

  • 删除了?xml and ?mso“标签”(那些不是真正的标签)更多比命名空间前缀更改更可能是罪魁祸首。在 XML 解析之后,命名空间前缀实际上不再存在,并且 Word 在解析发生之前不会获取文档。无论如何,ElementTree 是一个不完整的 XML 实现,我同意您应该放弃它(并记住这一事实,以便将来使用 XML)。
  • 我尝试从 word 写的原始 xml 文档中删除它们,并且它在文档中读取得很好 - 所以不,删除 ?xml 和 ?mso 非标签对 Word 似乎无关紧要.在猜测/推测任何其他可能的原因之前自己尝试一下怎么样?我知道命名空间前缀在纯 XML 术语中并不重要——去告诉微软吧。或者你自己试试,证明我错了。
  • 我不是在猜测,我知道 XML 是如何工作的。但是,如果您坚持:我刚刚打开了一个 DOCX 文件,将 word\document.xml 中的所有命名空间前缀从“w:”更改为“y:”,将其保存回来,将其加载到 Word 中并得到一个干净的文档,不错误,没有抱怨,它只是工作。命名空间前缀无关紧要。
  • 我尝试了一个写成 .xml 的文档,而不是 docx - OP 没有提到 docx。我重复一遍,我并不是说重命名前缀是不好的 XML - 也许它是关于 xml.etree.ElementTree 读/写 xml 的其他东西。使用 xml.etree.ElementTree 和 lxml.etree.ElementTrre 自己尝试运行 OP 的 python(没有处理位)。尝试删除非标签。 lxml 处理的版本有效,非标签无关紧要,xml.etree.ElementTree 处理的版本不会加载到 Word 中。
  • 这解决了我的问题。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2010-11-08
  • 2021-10-24
  • 2018-07-15
  • 2016-07-08
  • 2019-11-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多