Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access attribute value in xml containing namespace using ElementTree in python

XML file:

<?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>

I want to get the Terminal.ConnnectivityNode element's attribute value and Terminal element's attribute value also as output from the above xml. I have tried in below way!

Python code:

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#}"

Appending the below line to the code

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

output1: : Is as expected

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

If we Append with this below line to above code

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

output2: key error in rdf:ID

If we append with this below line to above code

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

output3 None

How to get output2 as A_T1 & Output3 as #A_CN1?

What is the significance of {0} in the above code, I have found that it must be used through net didn't get the significance of it?

like image 793
Nikhil Valiveti Avatar asked Mar 08 '23 23:03

Nikhil Valiveti


1 Answers

First off, the {0} you're wondering about is part of the syntax for Python's built-in string formatting facility. The Python documentation has a fairly comprehensive guide to the syntax. In your case, it simply gets substituted by cim, which results in the string {http://iec.ch/TC57/2008/CIM-schema-cim13#}Terminal.

The problem here is that ElementTree is a bit silly about namespaces. Instead of being able to simply supply the namespace prefix (like cim: or rdf:), you have to supply it in XPath form. This means that rdf:id becomes {http://www.w3.org/1999/02/22-rdf-syntax-ns#}ID, which is very clunky.

ElementTree does support a way to use the namespace prefix for finding tags, but not for attributes. This means you'll have to expand rdf: to {http://www.w3.org/1999/02/22-rdf-syntax-ns#} yourself.

In your case, it could look as following (note also that ID is case-sensitive):

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

Those substitutions expand to:

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

With those hoops jumped through, it works (note that the ID is A_T1 and not #A_T1, however). Of course, this is all really annoying to have to deal with, so you could also switch to lxml and have it mostly handled for you.

Your third case doesn't work simply because 1) it's named Terminal.ConductingEquipment and not Terminal.ConductivityEquipment, and 2) if you really want A_CN1 and not A_EF2, that's the ConnectivityNode and not the ConductingEquipment. You can get A_CN1 with tree.find('{0}Terminal/{0}Terminal.ConnectivityNode'.format(cim)).attrib['{0}resource'.format(rdf)].

like image 153
obskyr Avatar answered Apr 26 '23 09:04

obskyr