使用python';s zip和列表理解以将xml转换为csv
我一直在看关于zip和魔法的其他问题,这对我理解它的工作原理有很大帮助。例如:使用python';s zip和列表理解以将xml转换为csv,python,xml,csv,zip,list-comprehension,Python,Xml,Csv,Zip,List Comprehension,我一直在看关于zip和魔法的其他问题,这对我理解它的工作原理有很大帮助。例如: 尽管我还得想一想到底发生了什么,但我现在已经有了更好的理解。因此,我试图实现的是将xml文档转换为csv。上面的最后一个链接非常接近我想要做的事情,但是我的源xml没有最一致的结构,这就是我遇到麻烦的地方。下面是我的源xml的一个示例(为了这个示例而简化): 虽然这为我提供了一种可以用来编写csv的格式,但它有两个问题: 它跳过第二个子元素,因为它没有元素(我想)。如果我只通过设置tags=('Name'
元素(我想)。如果我只通过设置tags=('Name','姓氏')
搜索存在于两个子元素中的元素,那么我有两个列表(太棒了!)谢谢 关于第一个问题,您说“[i]f我只搜索两个子节点中存在的元素……我有两个列表返回”,这意味着第二个子节点缺少输出与两个
子节点之间的交互有关。事实并非如此。您似乎忽略了zip
行为的一个方面是zip
在用尽最短的参数后停止处理其参数
考虑以下代码简化的输出:
for child in data:
print [child.findall(x) for x in tags]
输出将为(忽略内存地址):
这将产生:
['John', 'Doe', '123456', '654321', '111111']
['Tom', 'Cat', '98765', '56789', '00000']
我把它拼凑起来了。阅读csv模块的文档,如果需要更具体的格式,请进行相应的更改
from csv import DictWriter
from StringIO import StringIO
import xml.etree
from xml.etree import ElementTree
xml_str = \
'''
<?xml version="1.0" encoding="utf-8"?>
<root>
<child>
<Name>John</Name>
<Surname>Doe</Surname>
<Phone>123456</Phone>
<Phone>654321</Phone>
<Fax>111111</Fax>
</child>
<child>
<Name>Tom</Name>
<Surname>Cat</Surname>
<Phone>98765</Phone>
<Phone>56789</Phone>
<Phone>00000</Phone>
</child>
</root>
'''
root = ElementTree.parse(StringIO(xml_str.strip()))
entry_list = []
for child_tag in root.iterfind("child"):
child_tags = child_tag.getchildren()
tag_count = {}
[tag_count.__setitem__(tag.tag, tag_count.get(tag.tag, 0) + 1) for tag in child_tags]
m_count = dict([(key, 0) for (key, val) in filter(lambda (x, y): y > 1, tag_count.items())])
enum = lambda x: ("%s%s" % (x.tag, (" %d" % m_count.setdefault(x.tag, m_count.pop(x.tag) + 1)) if(tag_count[x.tag] > 1) else ""), x.text)
tmp_dict = dict([enum(tag) for tag in child_tags])
entry_list.append(tmp_dict)
field_order = ["Name", "Surname", "Phone 1", "Phone 2", "Phone 3", "Fax"]
field_check = lambda q: field_order.index(q) if(field_order.count(q)) else sys.maxint
all_fields = list(reduce(lambda x, y: x | set(y.keys()), entry_list, set([])))
all_fields.sort(cmp=lambda x, y: field_check(x) - field_check(y))
with open("test.csv", "w") as file_h:
writer = DictWriter(file_h, all_fields, restval="", extrasaction="ignore", dialect="excel", lineterminator="\n")
writer.writerow(dict(zip(all_fields, all_fields)))
writer.writerows(entry_list)
从csv导入DictWriter
从StringIO导入StringIO
导入xml.etree
从xml.etree导入元素树
xml_str=\
'''
约翰
雌鹿
123456
654321
111111
汤姆
猫
98765
56789
00000
'''
root=ElementTree.parse(StringIO(xml_str.strip()))
条目列表=[]
对于root.iterfind(“child”)中的child_标记:
child\u tags=child\u tag.getchildren()
标记_计数={}
[tag\u count.\uuuuu setitem\uuuuuu(tag.tag,tag\u count.get(tag.tag,0)+1)用于子\u标记中的标记]
m_count=dict([(key,0)表示过滤器中的(key,val)(lambda(x,y):y>1,tag_count.items()))
enum=lambda x:(“%s%s%”(x.tag,(“%d”%m_count.setdefault(x.tag,m_count.pop(x.tag)+1))如果(tag_count[x.tag]>1)else“”,x.text)
tmp_dict=dict([子标签中标签的枚举(标签)])
条目列表追加(tmp目录)
字段顺序=[“姓名”、“姓氏”、“电话1”、“电话2”、“电话3”、“传真”]
field_check=lambda q:field_order.index(q)if(field_order.count(q))else sys.maxint
所有字段=列表(reduce(lambda x,y:x | set(y.keys()),entry_list,set([]))
所有字段。排序(cmp=lambda x,y:field\u check(x)-field\u check(y))
打开(“test.csv”、“w”)作为文件:
writer=DictWriter(文件,所有字段,restval=,extraction=“忽略”,dialogue=“excel”,lineterminator=“\n”)
writer.writerow(dict(zip(所有字段,所有字段)))
writer.writerows(条目列表)
你好,阿尔普,谢谢你的回复。然而,它遗漏了几点。我将编辑我的回复,添加预期的输出,使其更加清晰。我的目的是将结果转换为csv格式,以便您的输出在该上下文中不正常。这就是我最终想要的:John;乔;123456,654321;111111;代码>汤姆;猫;98765,56789;00000;;代码>因此,如果我有2个
元素,它们需要在一个csv“字段”中结束。此外,顺序很重要,作为csv,每个字段都必须与相应的标题明显匹配。。。这很好,但我得花好几个小时去理解你刚才在那里做的一切!谢谢
for child in data:
print [child.findall(x) for x in tags]
[[<Element 'Name'>], [<Element 'Surname'>], [<Element 'Phone'>, <Element 'Phone'>], [<Element 'Fax'>]]
[[<Element 'Name'>], [<Element 'Surname'>], [<Element 'Phone'>, <Element 'Phone'>, <Element 'Phone'>], []]
for child in data:
print [x.text for x in child]
['John', 'Doe', '123456', '654321', '111111']
['Tom', 'Cat', '98765', '56789', '00000']
from csv import DictWriter
from StringIO import StringIO
import xml.etree
from xml.etree import ElementTree
xml_str = \
'''
<?xml version="1.0" encoding="utf-8"?>
<root>
<child>
<Name>John</Name>
<Surname>Doe</Surname>
<Phone>123456</Phone>
<Phone>654321</Phone>
<Fax>111111</Fax>
</child>
<child>
<Name>Tom</Name>
<Surname>Cat</Surname>
<Phone>98765</Phone>
<Phone>56789</Phone>
<Phone>00000</Phone>
</child>
</root>
'''
root = ElementTree.parse(StringIO(xml_str.strip()))
entry_list = []
for child_tag in root.iterfind("child"):
child_tags = child_tag.getchildren()
tag_count = {}
[tag_count.__setitem__(tag.tag, tag_count.get(tag.tag, 0) + 1) for tag in child_tags]
m_count = dict([(key, 0) for (key, val) in filter(lambda (x, y): y > 1, tag_count.items())])
enum = lambda x: ("%s%s" % (x.tag, (" %d" % m_count.setdefault(x.tag, m_count.pop(x.tag) + 1)) if(tag_count[x.tag] > 1) else ""), x.text)
tmp_dict = dict([enum(tag) for tag in child_tags])
entry_list.append(tmp_dict)
field_order = ["Name", "Surname", "Phone 1", "Phone 2", "Phone 3", "Fax"]
field_check = lambda q: field_order.index(q) if(field_order.count(q)) else sys.maxint
all_fields = list(reduce(lambda x, y: x | set(y.keys()), entry_list, set([])))
all_fields.sort(cmp=lambda x, y: field_check(x) - field_check(y))
with open("test.csv", "w") as file_h:
writer = DictWriter(file_h, all_fields, restval="", extrasaction="ignore", dialect="excel", lineterminator="\n")
writer.writerow(dict(zip(all_fields, all_fields)))
writer.writerows(entry_list)