1

I am very new to XML with Python and I have the following XML string that I get as a response from a network device:

'<Response MajorVersion="1" MinorVersion="0"><Get><Configuration><OSPF MajorVersion="19" MinorVersion="2"><ProcessTable><Process><Naming><ProcessName>1</ProcessName></Naming><DefaultVRF><AreaTable><Area><Naming><AreaID>0</AreaID></Naming><Running>true</Running><NameScopeTable><NameScope><Naming><InterfaceName>Loopback0</InterfaceName></Naming><Running>true</Running><Cost>1000</Cost></NameScope><NameScope><Naming><InterfaceName>Loopback1</InterfaceName></Naming><Running>true</Running><Cost>1</Cost></NameScope><NameScope><Naming><InterfaceName>GigabitEthernet0/0/0/0</InterfaceName></Naming><Running>true</Running><Cost>1</Cost></NameScope></NameScopeTable></Area></AreaTable></DefaultVRF><Start>true</Start></Process></ProcessTable></OSPF></Configuration></Get><ResultSummary ErrorCount="0" /></Response>'

I have the following code to retrieve the interface information along with the interface cost associated with it. However I would also like to get the 'AreaID' tag associated with each interface as part of my dictionary. Unable to navigate the tree correctly to retrieve the AreaID tag value:

for node in x.iter('NameScope'):
int_name = str(node.find('Naming/InterfaceName').text)
d[int_name] = {}
d[int_name]['cost'] = str(node.find('Cost').text)

This code gives the following output when 'd' is printed:

{'GigabitEthernet0/0/0/0': {'cost': '1'},
 'Loopback0': {'cost': '1000'},
 'Loopback1': {'cost': '1'}}

I want something like this in the output:

{'GigabitEthernet0/0/0/0': {'cost': '1', 'area': 0},
 'Loopback0': {'cost': '1000', 'area': 0},
 'Loopback1': {'cost': '1', 'area': 0}}

Any suggestions or modifications to my code will be really appreciated!

1 Answer 1

1

I would use the preceding notation:

node.xpath(".//preceding::AreaID")[0].text

Complete code I am executing:

from lxml import etree as ET

x = ET.parse("input.xml")
d = {}
for node in x.iter('NameScope'):
    int_name = str(node.find('Naming/InterfaceName').text)
    d[int_name] = {
        'cost': str(node.find('Cost').text),
        'area': node.xpath(".//preceding::AreaID")[0].text 
    }

print(d)

Prints:

{
    'Loopback0': {'cost': '1000', 'area': '0'}, 
    'Loopback1': {'cost': '1', 'area': '0'}, 
    'GigabitEthernet0/0/0/0': {'cost': '1', 'area': '0'}
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your reply. However, 'x' is an xml.etree.ElementTree.Element object. Hence, node doesnt have the xpath attribute. I am on Python 2.7. Also, I tried what you suggested by doing this: "area = str(node.find(".//preceding::AreaID")[0].text)" and I got this error "SyntaxError: prefix 'preceding' not found in prefix map "
Also, my input is not an xml file, but an xml.etree.ElementTree.Element object.
@pypep278 well, it works for me even if I define a data string variable and define x as x = ET.fromstring(data). What happens if you use xpath() method?
Thank you so much! I was using the following import as opposed to yours and hence it failed for me: import xml.etree.ElementTree as ET

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.