I'm trying to parse an XML from a string in Python with no success. The string I'm trying to parse is:
<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:573a453c-72c0-4185-8c54-9010593dd102">
<data>
<config xmlns="http://www.calix.com/ns/exa/base">
<profile>
<policy-map>
<name>ELINE_PM_1</name>
<class-map-ethernet>
<name>Eth-match-any-1</name>
<ingress>
<meter-type>meter-mef</meter-type>
<eir>1000000</eir>
</ingress>
</class-map-ethernet>
</policy-map>
<policy-map>
<name>ELINE_PM_2</name>
<class-map-ethernet>
<name>Eth-match-any-2</name>
<ingress>
<meter-type>meter-mef</meter-type>
<eir>10000000</eir>
</ingress>
</class-map-ethernet>
</policy-map>
</profile>
</config>
</data>
</rpc-reply>
I'm trying to use xml.etree.ElementTree library to parse the xml and I also tried to remove the first line related to xml version and encoding with no results. The code snippet to reproduce the issue I'm facing is:
import xml.etree.ElementTree as ET
reply_xml='''
<data>
<config>
<profile>
<policy-map>
<name>ELINE_PM_1</name>
<class-map-ethernet>
<name>Eth-match-any-1</name>
<ingress>
<meter-type>meter-mef</meter-type>
<eir>1000000</eir>
</ingress>
</class-map-ethernet>
</policy-map>
<policy-map>
<name>ELINE_PM_2</name>
<class-map-ethernet>
<name>Eth-match-any-2</name>
<ingress>
<meter-type>meter-mef</meter-type>
<eir>10000000</eir>
</ingress>
</class-map-ethernet>
</policy-map>
</profile>
</config>
</data>
'''
root = ET.fromstring(reply_xml)
for child in root:
print(child.tag, child.attrib)
reply_xml
is a string containing the above mentioned xml so it should work but if I inspect the root variable using the debugger I see that it is not being populated correctly.
It seems that the first xml tag (<?xml version="1.0" encoding="UTF-8"?>
) creates some problems but even if I manually remove it I am not able to parse the xml correctly.
Any clue to parse that xml?
Your original XML has namespaces. You need to honor them in your XPath queries.
import xml.etree.ElementTree as ET
reply_xml '''<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:573a453c-72c0-4185-8c54-9010593dd102">
<data>
<config xmlns="http://www.calix.com/ns/exa/base">
<!-- ... the rest of it ... -->
</config>
</data>
</rpc-reply>'''
ns = {
'calix': 'http://www.calix.com/ns/exa/base'
}
root = ET.fromstring(reply_xml)
for eir in root.findall('.//calix:eir', ns):
print(eir.text)
prints
1000000 10000000
Your code works fine. It shows all children of the root element, which is only <config> .. </config>
and it has no attributes.
To get to the <eir>
tag, you should use XPath, or go through the tree recursively.
Quick solution for XPath:
root.findall('.//eir')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With