在 Python 中使用 ElementTree 解析带有命名空间的 XML

mid*_*ori 1 python xml elementtree xml-parsing python-2.7

我有一个 xml,它的一小部分看起来像这样:

<?xml version="1.0" ?>
<i:insert xmlns:i="urn:com:xml:insert" xmlns="urn:com:xml:data">
  <data>
    <image imageId="1"></image>
    <content>Content</content>
  </data>
</i:insert>
Run Code Online (Sandbox Code Playgroud)

当我使用解析它ElementTree并将其保存到文件时,我看到以下内容:

<ns0:insert xmlns:ns0="urn:com:xml:insert" xmlns:ns1="urn:com:xml:data">
  <ns1:data>
    <ns1:image imageId="1"></ns1:image>
    <ns1:content>Content</ns1:content>
  </ns1:data>
</ns0:insert>
Run Code Online (Sandbox Code Playgroud)

为什么它会改变前缀并将它们放在任何地方?使用minidom我没有这样的问题。配置了吗?的文档ElementTree很差。问题是,我无法找到任何节点,解析后,例如image-不能带或不带命名空间找到它,如果我使用它像{namespace}image或只image。为什么?任何建议都非常感谢。

我已经尝试过的:

import xml.etree.ElementTree as ET
tree = ET.parse('test.xml')
root = tree.getroot()
for a in root.findall('ns1:image'):
    print a.attrib
Run Code Online (Sandbox Code Playgroud)

这将返回一个错误,而另一个不返回任何内容:

for a in root.findall('{urn:com:xml:data}image'):
    print a.attrib
Run Code Online (Sandbox Code Playgroud)

我也尝试制作这样的命名空间并使用它:

namespaces = {'ns1': 'urn:com:xml:data'}
for a in root.findall('ns1:image', namespaces):
    print a.attrib
Run Code Online (Sandbox Code Playgroud)

它什么都不返回。我究竟做错了什么?

mzj*_*zjn 6

你问题中的这个片段,

for a in root.findall('{urn:com:xml:data}image'):
    print a.attrib
Run Code Online (Sandbox Code Playgroud)

不输出任何内容,因为它只查找{urn:com:xml:data}image树根的直接子节点。

这个稍微修改的代码,

for a in root.findall('.//{urn:com:xml:data}image'):
    print a.attrib
Run Code Online (Sandbox Code Playgroud)

将打印,{'imageId': '1'}因为它使用.//,它选择所有级别上的匹配子元素。

参考:https : //docs.python.org/2/library/xml.etree.elementtree.html#supported-xpath-syntax


令人有点恼火的是,ElementTree 不仅默认保留原始名称空间前缀,而且请记住,无论如何前缀并不重要。该register_namespace()函数可用于在序列化XML时设置所需的前缀。该函数对解析或搜索没有任何影响。