2017-09-12 2 views
0

J'essaye de prendre des données d'appel d'API qui retourne l'objet XML et d'analyser quelques points de données dans un fichier csv avec chaque objet dans sa propre colonne.Comment écrire des données à partir de plusieurs balises xml dans plusieurs colonnes dans csv?

Le XML ressemble à ceci:

<?xml version="1.0" encoding="utf-8" ?> 

<YourMembership_Response> 
<Items> 
<Item> 
<ItemID></ItemID> 
<ID>92304823A-2932</ID> 
<WebsiteID>0987</WebsiteID> 
<NamePrefix></NamePrefix> 
<FirstName>John</FirstName> 
<MiddleName></MiddleName> 
<LastName>Smith</LastName> 
<Suffix></Suffix> 
<Nickname></Nickname> 
<EmployerName>abc company</EmployerName> 
<WorkTitle>manager</WorkTitle> 
<Date>3/14/2013 2:12:39 PM</Date> 
<Description>Removed from group by Administration.</Description> 
</Item> 
<Item> 
<ItemID></ItemID> 
<ID>92304823A-2932</ID> 
<WebsiteID>0987</WebsiteID> 
<NamePrefix></NamePrefix> 
<FirstName>John</FirstName> 
<MiddleName></MiddleName> 
<LastName>Smith</LastName> 
<Suffix></Suffix> 
<Nickname></Nickname> 
<EmployerName>abc company</EmployerName> 
<WorkTitle>manager</WorkTitle> 
<Date>3/14/2013 2:12:39 PM</Date> 
<Description>Removed from group by Administration.</Description> 
</Item> 

J'ai écrit ce code à écrire juste ID au format CSV, qui fonctionne très bien.

with open("output1.csv", "wb") as f: 
    writer = csv.writer(f) 
    for node in tree.findall('.//ID'): 
     writer.writerow([node.text]) 

Maintenant, quand je tente d'écrire plusieurs points de données en csv, la machine est simplement les points Annexer des données dans une colonne. Ce code ici je tente avec:

with open("test1.csv", "wb") as f: 
    writer = csv.writer(f) 
    for node in tree.findall('.//ID'): 
     writer.writerow([node.text]) 
    for node in tree.findall('.//FirstName'): 
     writer.writerow([node.text]) 
    for node in tree.findall('.//LastName'): 
     writer.writerow([node.text]) 

J'ai besoin des données pour ressembler à ceci dans le csv avec d'autres points de données de choisir plus tard, qu'est-ce que je fais mal ?:

ID     FirstName  LastName 
92304823A-2932   John   Smith 

Merci d'avance.

+0

Quelle est la taille xml d'entrée? –

+0

Je n'ai pas de réponse pour la taille d'entrée, mais il y a environ 15000 membres pour lesquels je dois faire ça. – RustyShackleford

Répondre

1

Il s'agit essentiellement de la façon de collecter les données.

>>> from xml.etree import ElementTree 
>>> tree = ElementTree.parse('api.xml') 
>>> tree.findall('.//Item') 
[<Element 'Item' at 0x0000000006679EA8>, <Element 'Item' at 0x0000000006681318>] 
>>> for item in tree.findall('.//Item'): 
...  item.find('ID').text, item.find('FirstName').text, item.find('LastName').text 
... 
('92304823A-2932', 'John', 'Smith') 
('92304823A-2932', 'John', 'Smith') 

En revanche, lorsque vous utilisez une construction comme tree.findall('.//ID') vous demandez au moteur de XPath pour commencer tree (c'est le « » partie) et regarder vers le bas à travers les branches pour toutes les occurences de « ID » à une fois. Cela signifie que, dans votre exemple de code XML, vous obtiendrez un de deux ID qui ne seront pas nécessairement dans l'ordre original. Ce que vous devez faire est, d'abord trouver toutes les entrées Item, puis trouver les trois éléments de données correspondants d'intérêt pour ce Item.

Addendum:

>>> import csv 
>>> with open('api.csv', 'w', newline='') as csvfile: 
...  fieldnames = ['ID', 'FirstName', 'LastName'] 
...  writer = csv.DictWriter(csvfile, fieldnames=fieldnames) 
...  writer.writeheader() 
...  for item in tree.findall('.//Item'): 
...   writer.writerow({ 
...    'ID': item.find('ID').text, 
...    'FirstName': item.find('FirstName').text, 
...    'LastName': item.find('LastName').text}) 

résultant fichier de sortie:

ID,FirstName,LastName 
92304823A-2932,John,Smith 
92304823A-2932,John,Smith