如何使用 python 中的 ElementTree 访问包含命名空间的 xml 中的属性值
How to access attribute value in xml containing namespace using ElementTree in python
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 None
如何将 output2 作为 A_T1 & Output3 作为 #A_CN1?
上面代码中的{0}是什么意思,我发现一定要通过net使用没看懂?
首先,您想知道的 {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
而不是 ConductingEquipment
。你可以用 tree.find('{0}Terminal/{0}Terminal.ConnectivityNode'.format(cim)).attrib['{0}resource'.format(rdf)]
.
得到 A_CN1
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 None
如何将 output2 作为 A_T1 & Output3 作为 #A_CN1?
上面代码中的{0}是什么意思,我发现一定要通过net使用没看懂?
首先,您想知道的 {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
而不是 ConductingEquipment
。你可以用 tree.find('{0}Terminal/{0}Terminal.ConnectivityNode'.format(cim)).attrib['{0}resource'.format(rdf)]
.
A_CN1