Python Forum

Full Version: How to display XML tree structure with Python?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
@mreshko, This is 3 year old request and I doubt OP will take requests to develop functionality for you. I would suggest that you try to modify the code provided here and amend it to suit your needs. If you face a problem you cannot solve - start a new thread, post your code in python tags, any traceback - in error tags and ask specific questions.
Be aware that the user hasn't visited forum in two years, so unlikely that you will get a response.
But, you never know.
For those who might be interested, I've added a few things to the code, so now it displays the siblings number, e.g. 1 in "3.1", the text value from the element, and the number of identical siblings.

xml_root = etree.fromstring(xml_file_content)
raw_tree = etree.ElementTree(xml_root)
nice_tree = collections.OrderedDict()
 
for tag in xml_root.iter():
    path = re.sub('\[[0-9]+\]', '', raw_tree.getpath(tag))
    
    if path not in nice_tree:
        nice_tree[path] = {'attribs':[], 'values': '', 'count': 1}
    else:
        nice_tree[path]['count'] += 1
        
    if len(tag.keys()) > 0:
        nice_tree[path]['attribs'].extend(attrib for attrib in tag.keys() if attrib not in nice_tree[path])  
        
    if tag.text:
        nice_tree[path]['values'] = ' '.join(tag.text.split())
        

last_level = -1
sibling = 0
for path, d in nice_tree.items():
    
    this_level = int(path.count('/') - 1)
    if this_level == last_level:
        sibling += 1
    else:
        sibling = 0
    last_level = this_level
    
    print('{0}{1}.{2}: {3} [{4}] [{5}] [{6}]'.format('    ' * this_level,
                                                     this_level,
                                                     sibling,
                                                     path.split('/')[-1],
                                                     ', '.join(d['attribs']) if len(d['attribs']) > 0 else '',
                                                     d['values'],
                                                     d['count']))                      

The code in my last post was incorrectly calculating siblings id. This is an update which should fix it.

xml_root = etree.fromstring(file_content)
raw_tree = etree.ElementTree(xml_root)
nice_tree = collections.OrderedDict()
 
for tag in xml_root.iter():
    path = re.sub('\[[0-9]+\]', '', raw_tree.getpath(tag))
    
    if path not in nice_tree:
        nice_tree[path] = {'attribs':[], 'values':'', 'count':1}
    else:
        nice_tree[path]['count'] += 1
        
    if len(tag.keys()) > 0:
        nice_tree[path]['attribs'].extend(attrib for attrib in tag.keys() if attrib not in nice_tree[path])  
        
    if tag.text:
        nice_tree[path]['values'] = ' '.join(tag.text.split())
        

last_level = -1
siblings = []
for path, d in nice_tree.items():
    
    this_level = int(path.count('/') - 1)
    
    if len(siblings)-1 < this_level:
        siblings.append(0)
    elif this_level == last_level:
        siblings[this_level] += 1
    elif this_level < last_level:
        siblings[last_level] = 0
        siblings[this_level] += 1
    else:
        siblings[this_level] = 0
        
    last_level = this_level
    
    print('{0}{1}.{2}: {3} [{4}] [{5}] [{6}]'.format('    ' * this_level,
                                                     this_level,
                                                     siblings[this_level],
                                                     path.split('/')[-1],
                                                     ', '.join(d['attribs']) if len(d['attribs']) > 0 else '',
                                                     d['values'],
                                                     d['count']))
...not quite. Need to replace

siblings[last_level] = 0
with

siblings[this_level+1:] = [0] * (len(siblings) - this_level - 1)
That should now be it. Hopefully. Rolleyes
Pages: 1 2