我在使用lxml库生成XML方面获得了一些帮助,这非常有用,而且我能够对其进行扩展以解决大多数问题。我正在努力解决一个用例。我尝试了一个建议,但仍在努力
下面我的数据集的简单表示形式
ID,Currency,Notional,Maturity,Type
ID1,,,,2018-06-01,
ID1-L1,EUR,100,,,Bond
ID1-L2,JPY,110,,A
ID1-L2,CNY,115,,B
ID2,,,,2018-06-01,
ID2-L1,EUR,100,,,Stock
ID2-L2,JPY,110,,C
ID2-L2,JPY,110,,D
基本上,我这里有两条记录ID-1和ID2。 ID-L1,ID-L2等是ID1的子元素,并且会有ID-L2的多个实例。我的问题是我需要识别所有ID-L2等事件,并为每个事件创建一个新元素,然后移至下一个记录ID2并重复。因此,实际上我的结果将如下所示。
<tradeRequests>
<ids>
<mainid>ID1</mainid>
<element>
<maturityDate>2018-06-01</maturityDate>
</element>
<cffixed>
<element>
<id>ID-L1</id>
<currency>EUR</currency>
</element>
</cffixed>
<cffloat>
<element>
<id>ID1-L2</id>
<currency>JPY</currency>
</element>
<element>
<id>ID1-L2</id>
<currency>CNY</currency>
</element>
</cffloat>
</ids>
</tradeRequests>
因此,这是我使用过的一小段代码,但在本例中,我对值进行了硬编码,而不是引用文件中的内容。
import csv
import lxml.etree
from lxml.builder import E
with open('tc.csv', 'r') as fb:
results = E.tradeRequests(*(
E.ids(
E.mainid('id'),
E.element(
E.MaturityDate('maturity'),
E.cffixed(
E.element(
E.id('id'),
E.currency('currency'),
),
),
E.cffloat(
E.element(
E.id('id'),
E.currency('id'),
) #for r in ids2_rows,
),
),
)for row in csv.DictReader(fb))
)
print(lxml.etree.tostring(results, pretty_print=True))
我的问题是,我可以独立地找到一种标识ID-L2的行的方法,但是不确定如何获取for循环来使用它。这确实是缺少的拼图,因此一如既往地乐于助人。
答案 0 :(得分:1)
此方法在生成元素之前使用itertools.groupby
按ID对数据进行分组。这样,可以为每个元素添加一个mainid
。
import itertools
import csv
import lxml.etree
from lxml.builder import E
with open('tc.csv', 'r') as fb:
cf = csv.DictReader(fb)
def groupkey(row):
return row['ID'].split('-')[0] # group by first part of ID
result_ids = E.ids()
result = E.tradeRequests(result_ids)
for main_id, rows in itertools.groupby(cf, key=groupkey):
rows = list(rows)
result_ids.extend([
E.mainid(main_id),
E.element(E.maturityDate(rows[0]['Type'])),
E.cffixed(E.element(E.id(rows[1]['ID']), E.currency(rows[1]['Currency']))),
E.cffloat(*(E.element(E.id(r['ID']), E.currency(r['Currency']))
for r in rows[2:])),
])
print(lxml.etree.tostring(result, pretty_print=True))
与您在问题中提供的csv一起运行时的结果:
<tradeRequests>
<ids>
<mainid>ID1</mainid>
<element>
<maturityDate>2018-06-01</maturityDate>
</element>
<cffixed>
<element>
<id>ID1-L1</id>
<currency>EUR</currency>
</element>
</cffixed>
<cffloat>
<element>
<id>ID1-L2</id>
<currency>JPY</currency>
</element>
<element>
<id>ID1-L2</id>
<currency>CNY</currency>
</element>
</cffloat>
<mainid>ID2</mainid>
<element>
<maturityDate>2018-06-01</maturityDate>
</element>
<cffixed>
<element>
<id>ID2-L1</id>
<currency>EUR</currency>
</element>
</cffixed>
<cffloat>
<element>
<id>ID2-L2</id>
<currency>JPY</currency>
</element>
<element>
<id>ID2-L2</id>
<currency>JPY</currency>
</element>
</cffloat>
</ids>
</tradeRequests>