Reputation: 27
I'm currently using Python to convert a XML file to CSV format by using ElementTree
library and XPath. My code works will if all of the child tag exists (First name, Last name, and address) for the first parent person tag, but I receive an error message of
Child Index out of range
when the first person is missing a child tag (only first and last name exist).
What code can I write to bypass this error message? This is my first time using XPath, how can an if statement be added to this? Or should I use something else?
Here's what my XML file looks like:
<?xml version="1.0" encoding="utf-8"?>
<Members>
<Person>
<FirstName>JANE</FirstName>
<LastName>DOE</LastName>
</Person>
<Person>
<FirstName>JOHN</FirstName>
<LastName>DOE</LastName>
<Address>
<Address1>123 Straw Street</Address1>
<Address2></Address2>
<City>Apple</City>
<State>Test</State>
<ZipCode>123456 </ZipCode>
</Address>
</Person>
</Members>
Current Python Code:
import csv
import xml.etree.ElementTree as ET
tree = ET.parse("TestStack.xml")
root = tree.getroot()
xml_data_to_csv =open('OutputStack.csv','w')
Csv_writer=csv.writer(xml_data_to_csv)
list_head=[]
count=0
for element in root.findall('Person'):
person = []
#Get head by tag
if count == 0:
FirstName = element.find('FirstName').tag
list_head.append(FirstName)
LastName = element.find('LastName').tag
list_head.append(LastName)
Address = element[2].tag
list_head.append(Address)
Csv_writer.writerow(list_head)
count = count +1
#get child node
FirstName = element.find('FirstName').text
person.append(FirstName)
LastName = element.find('LastName').text
person.append(LastName)
person.append([e.text for e in element.findall('Address//')])
#Write List_nodes to csv
Csv_writer.writerow(person)
xml_data_to_csv.close()
Upvotes: 1
Views: 448
Reputation: 18950
I think the header should be predefined. I doubt that your CSV import backend accepts any format.
import csv
import xml.etree.ElementTree as ET
tree = ET.parse("in.xml")
root = tree.getroot()
xml_data_to_csv =open('out.csv','w')
Csv_writer=csv.writer(xml_data_to_csv)
list_head=['FirstName', 'LastName', 'Address']
Csv_writer.writerow(list_head)
for element in root.findall('Person'):
person = []
#get child node
FirstName = element.find('FirstName').text
person.append(FirstName)
LastName = element.find('LastName').text
person.append(LastName)
person.append([e.text for e in element.findall('Address//')])
#Write List_nodes to csv
Csv_writer.writerow(person)
xml_data_to_csv.close()
Otherwise, you could either handle the exception or check how many elements exist like this
if len(element) > 2:
head_list.append(element[2])
continue
Preinitialize the head_list = [None] * 3 #len(element)
, and collect the headers (as the show-up) and persons during the for-loop, then write everything at the end. I would not recommend that route.
Upvotes: 1