enumerate column headers in CSV that belong to the same tag (key) in python
Question: I am using the following sets of generators to parse XML in to CSV:

    
    
    import xml.etree.cElementTree as ElementTree 
    from xml.etree.ElementTree import XMLParser
    import csv
    
    def flatten_list(aList, prefix=''):
        for i, element in enumerate(aList, 1):
            eprefix = "{}{}".format(prefix, i)
            if element:
                # treat like dict 
                if len(element) == 1 or element[0].tag != element[1].tag: 
                    yield from flatten_dict(element, eprefix)
                # treat like list 
                elif element[0].tag == element[1].tag: 
                    yield from flatten_list(element, eprefix)
            elif element.text: 
                text = element.text.strip() 
                if text: 
                    yield eprefix[:].rstrip('.'), element.text
    
    def flatten_dict(parent_element, prefix=''):
        prefix = prefix + parent_element.tag 
        if parent_element.items():
            for k, v in parent_element.items():
                yield prefix + k, v
        for element in parent_element:
            eprefix = element.tag  
            if element:
                # treat like dict - we assume that if the first two tags 
                # in a series are different, then they are all different. 
                if len(element) == 1 or element[0].tag != element[1].tag: 
                    yield from flatten_dict(element, prefix=prefix)
                # treat like list - we assume that if the first two tags 
                # in a series are the same, then the rest are the same. 
                else: 
                    # here, we put the list in dictionary; the key is the 
                    # tag name the list elements all share in common, and 
                    # the value is the list itself
                    yield from flatten_list(element, prefix=eprefix)
                # if the tag has attributes, add those to the dict
                if element.items():
                    for k, v in element.items():
                        yield eprefix+k
            # this assumes that if you've got an attribute in a tag, 
            # you won't be having any text. This may or may not be a 
            # good idea -- time will tell. It works for the way we are 
            # currently doing XML configuration files... 
            elif element.items(): 
                for k, v in element.items():
                    yield eprefix+k
            # finally, if there are no child tags and no attributes, extract 
            # the text 
            else:
                yield eprefix, element.text                
    
    def makerows(pairs):
    
        headers = []
        columns = {}
        for k, v in pairs:
            if k in columns:
                columns[k].extend((v,))
            else:
                headers.append(k)
                columns[k] = [k, v]
        m = max(len(c) for c in columns.values())
        for c in columns.values():
            c.extend(' ' for i in range(len(c), m))
        L = [columns[k] for k in headers]
        rows = list(zip(*L))
        return rows      
    
    def main():
    
        with open('2-Response_duplicate.xml', 'r', encoding='utf-8') as f: 
            xml_string = f.read() 
        xml_string= xml_string.replace('&#x0;', '') #optional to remove ampersands. 
        root = ElementTree.XML(xml_string) 
    #     for key, value in flatten_dict(root):
    #         key = key.rstrip('.').rsplit('.', 1)[-1]
    #         print(key,value)
        writer = csv.writer(open("try5.csv", 'wt'))
        writer.writerows(makerows(flatten_dict(root)))
    
    if __name__ == "__main__":
        main()
    

One column of the CSV, when opened in Excel, looks like this:

ObjectGuid

2adeb916-cc43-4d73-8c90-579dd4aa050a

2e77c588-56e5-4f3f-b990-548b89c09acb

c8743bdd-04a6-4635-aedd-684a153f02f0

1cdc3d86-f9f4-4a22-81e1-2ecc20f5e558

2c19d69b-26d3-4df0-8df4-8e293201656f

6d235c85-6a3e-4cb3-9a28-9c37355c02db

c34e05de-0b0c-44ee-8572-c8efaea4a5ee

9b0fe8f5-8ec4-4f13-b797-961036f92f19

1d43d35f-61ef-4df2-bbd9-30bf014f7e10

9cb132e8-bc69-4e4f-8f29-c1f503b50018

24fd77da-030c-4cb7-94f7-040b165191ce

0a949d4f-4f4c-467e-b0a0-40c16fc95a79

801d3091-c28e-44d2-b9bd-3bad99b32547

7f355633-426d-464b-bab9-6a294e95c5d5

This is due to the fact that there are 14 tags with name ObjectGuid. For
example, one of these tags looks like this:

    
    
    <ObjectGuid>2adeb916-cc43-4d73-8c90-579dd4aa050a</ObjectGuid>
    

My question: is there an efficient method to enumerate the headers (the keys)
such that each key is enumerated like so with it's corresponding value (text
in the XML data structure):

It would be displayed in Excel as follows:

ObjectGuid_1 ObjectGuid_2 ObejectGuid3 etc.....

Please let me know if there is any other information that you need from me
(such as sample XML). Thank you for your help.


Answer: It is a mistake to add an element, attribute, or annotative descriptor to the
data set itself for the purpose of identity… Normalizing the data should only
be done if you own that data and know with 100% guarantee that doing so will
not have any negative effect on additional consumers (ones relying on
attribute order to manipulate the DOM). However what is the point of using a
dict or nested dicts (which I don’t quite get either t) if the efficiency of
the hashed table lookup is taken right back by making 0(n) checks for this
attribute new attribute? The point of this hashing is random look up..

If it’s simply the structured in (key, value) pair, which makes sense here..
Why not just use some other contiguous data structure, but treat it like a
dictionary.. Say a named tuple…

A second solution is if you want to add additional state is to throw your
generator in a class.

class order:

    
    
        def__init__(self, lines, order): 
            self.lines = lines 
            self.order - python(max) 
    
        def __iter__(self): 
            for l, line in enumerate(self.lines, 1); 
            self.order.append(  l, line))  
            yield line 
    
    when open (some file.csv) as f: 
        lines = oder( f); 
    

Messing with the data a Harmless conversion? For example if were to create a
conversion dictionary (see below)

Well that’s fine, that is until one of the values is blank…

types = [ (‘x ’, float’), (‘y’, float’)

    
    
    with open(‘some.csv’) as f: 
         for row in cvs.DictReader(f): 
              row.update((key, conversion (row [ key])) 
            for key, conversion in field_types) 
    
    
    [x: ,y: 2.  2]  — > that is until there is an empty data point.. Kaboom. 
    

So My suggestion would not be to change or add to the data, but change the
algorithm in which deal with such.. If the problem is order why not simply
treat say a tuple as a named tuple similar to a dictionary, the caveat being
mutability however makes sense with data uniformity...

*I don’t understand the nested dictionary…That is for the y header values yes? 

values and order key —> key — > ( key: value ) ? or you could just skip the

    
    
    first row :p..
        So just skip the first row.. 
    
        for  line in {header: list, header: list }  
            line.next()  # problem solved.. or print(line , end = ‘’) 
    
        *** Notables 
    -To iterator over multiple sequences in parallel 
    
    
     h = [a,b,c]
        x = [1,2,3]
    
        for i in zip(a,b): 
            print(i) 
    
        (a, 1) 
        (b, 2)
    
        -Chaining 
    
        a = [1,2 ,  3]
        b= [a, b ,  c ]enter code here
        for x in chain(a, b): 
            //remove white space 
    

