Traversing from one node in xml to another using Python
Question: 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!


Answer: I would use the [`preceding`](https://developer.mozilla.org/en-
US/docs/Web/XPath/Axes/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'}
    }
    

