enumerate column headers in CSV that belong to the same tag (key) in python

时间:2015-06-25 18:31:42

标签: python csv

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('�', '') #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.

1 个答案:

答案 0 :(得分:1)

为了身份的目的,将元素,属性或注释描述符添加到数据集本身是错误的...只有拥有该数据并且100%保证这样做才能正常化数据。不 对其他消费者有任何负面影响(依赖于属性顺序来操纵DOM)。但是,如果通过对此属性新属性进行0(n)检查来获取散列表查找的效率,那么使用dict或嵌套dicts(我不太理解)的重点是什么?这个散列的重点是随机查找..

如果它只是结构化的(键,值)对,这在这里是有意义的。为什么不只是使用一些其他连续的数据结构,但把它当作字典对待..说一个命名的元组......

第二个解决方案是,如果你想添加额外的状态就是把你的生成器抛给一个类。

班级订单:

    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); 

将数据与无害转换相混淆?例如,如果要创建转换字典(见下文)

那很好,直到其中一个值为空......

types = [('x',float'),           ('y',漂浮')

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. 

所以我的建议不是改变或添加数据,而是更改处理此类数据的算法。如果问题是顺序,为什么不简单地将元组称为类似于字典的命名元组,但需要注意的是数据的一致性......

*我不明白嵌套字典...那对于y标头值是吗?

值和订单键 - &gt;键 - &gt; ( 核心价值 ) ?或者你可以跳过

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