如何使用python中的ElementTree访问包含命名空间的xml中的属性值

时间:2017-05-31 11:00:42

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

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

output1::符合预期

{'{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))

output3

如何将 output2 作为A_T1&amp; 输出3 为#A_CN1?

在上面的代码中{0}的意义是什么,我发现它必须通过net才能得到它的意义吗?

1 个答案:

答案 0 :(得分:3)

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

这里的问题是ElementTree对名称空间有点愚蠢。您必须以XPath格式提供,而不是简单地提供名称空间前缀(如cim:rdf:)。这意味着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而不是{ {1}},A_EF2而不是ConnectivityNode。您可以使用ConductingEquipment获取A_CN1