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

1

5

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?

Gambetta answered 31/5, 2017 at 11:0 Comment(2)
Nitpick: #A_T1 is not found in the XML document. There is only A_T1Celadon
sry thanks for the editGambetta
O
7

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)].

Onfroi answered 31/5, 2017 at 11:39 Comment(3)
If the expected result for "output3" is #A_CN1, then the code for that should be print tree.find('{0}Terminal/{0}Terminal.ConnectivityNode'.format(cim)).attrib['{0}resource'.format(rdf)].Celadon
@Celadon You're right - I didn't even catch the mismatch between selected element and desired attribute. Thanks. Updated!Onfroi
thanks a lot obskyr! it hepled me to move to next level!!Gambetta

© 2022 - 2024 — McMap. All rights reserved.