【问题标题】:How to access attribute value in xml containing namespace using ElementTree in python如何在python中使用ElementTree访问包含命名空间的xml中的属性值
【发布时间】:2017-05-31 11:00:41
【问题描述】:

XML 文件:

<?xml version="1.0" encoding="iso-8859-1"?>
<rdf:RDF xmlns:cim="http://iec.ch/TC57/2008/CIM-schema-cim13#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<cim:Terminal rdf:ID="A_T1">
<cim:Terminal.ConductingEquipment rdf:resource="#A_EF2"/>
<cim:Terminal.ConnectivityNode rdf:resource="#A_CN1"/>
</cim:Terminal>
</rdf:RDF>

我想获取 Terminal.ConnnectivityNode 元素的属性值和 Terminal 元素的属性值也作为上述 xml 的输出。我已经尝试过以下方式!

Python 代码:

from elementtree import ElementTree as etree
tree= etree.parse(r'N:\myinternwork\files xml of bus systems\cimxmleg.xml')
cim= "{http://iec.ch/TC57/2008/CIM-schema-cim13#}" 
rdf= "{http://www.w3.org/1999/02/22-rdf-syntax-ns#}"

将下面一行添加到代码中

print tree.find('{0}Terminal'.format(cim)).attrib

输出1::符合预期

{'{http://www.w3.org/1999/02/22-rdf-syntax-ns#}ID': 'A_T1'}

如果我们将下面这一行附加到上面的代码中

print tree.find('{0}Terminal'.format(cim)).attrib['rdf:ID'] 

output2:rdf:ID 中的键错误

如果我们将下面这一行附加到上面的代码中

print tree.find('{0}Terminal/{0}Terminal.ConductivityEquipment'.format(cim))

输出3

如何获得 output2 作为 A_T1 和 Output3 作为 #A_CN1?

上面代码中的{0}是什么意思,我发现必须通过net来使用没明白它的意义?

【问题讨论】:

  • Nitpick: #A_T1 在 XML 文档中找不到。只有A_T1
  • 非常感谢您的编辑

标签: python xml python-2.7 xml-namespaces elementtree


【解决方案1】:

首先,您想知道的{0} 是Python 内置字符串格式化工具语法的一部分。 The Python documentation has a fairly comprehensive guide to the syntax. 在您的情况下,它只是被 cim 替换,这导致字符串 {http://iec.ch/TC57/2008/CIM-schema-cim13#}Terminal

这里的问题是ElementTree 对命名空间有点傻。您不能简单地提供命名空间前缀(如cim:rdf:),您必须以XPath 形式提供它。这意味着rdf:id 变成了{http://www.w3.org/1999/02/22-rdf-syntax-ns#}ID,这很笨拙。

ElementTree 确实支持a way to use the namespace prefix for finding tags,但不支持属性。这意味着您必须自己将rdf: 扩展为{http://www.w3.org/1999/02/22-rdf-syntax-ns#}

在您的情况下,它可能如下所示(另请注意,ID 区分大小写):

tree.find('{0}Terminal'.format(cim)).attrib['{0}ID'.format(rdf)]

这些替换扩展为:

tree.find('{http://iec.ch/TC57/2008/CIM-schema-cim13#}Terminal').attrib['{http://www.w3.org/1999/02/22-rdf-syntax-ns#}ID']

跳过这些箍后,它就可以工作了(请注意,ID 是A_T1 而不是#A_T1)。当然,这一切真的很烦人,所以你也可以切换到lxml,大部分时间都会为你处理。

您的第三种情况不起作用,因为 1) 它被命名为 Terminal.ConductingEquipment 而不是 Terminal.ConductivityEquipment,并且 2) 如果你真的想要 A_CN1 而不是 A_EF2,那就是 ConnectivityNode 而不是 @ 987654345@。您可以通过tree.find('{0}Terminal/{0}Terminal.ConnectivityNode'.format(cim)).attrib['{0}resource'.format(rdf)] 获取A_CN1

【讨论】:

  • 如果“output3”的预期结果是#A_CN1,那么它的代码应该是print tree.find('{0}Terminal/{0}Terminal.ConnectivityNode'.format(cim)).attrib['{0}resource'.format(rdf)]
  • @mzjn 你是对的 - 我什至没有发现所选元素和所需属性之间的不匹配。谢谢。更新了!
  • 非常感谢 obskyr!它帮助我更上一层楼!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-06
  • 2013-01-28
相关资源
最近更新 更多