Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Convert a HandySafe exported XML file to a CSV file for Sky Wallet to import.
# HandySafeXmlToSkyWalletCsv.py
# Convert HandySafe XML to Sky Wallet CSV
# Save the HandySafe export as test1.xml (hard coded below)
# Then, run: python HandySafeXmlToSkyWalletCsv.py > output.txt
# Tested using Python 2.7.4
# Author: Kit Menke (@kitmenke) on 7/30/2013
import csv, xml.etree.ElementTree as ET
# CHANGE ME: change HANDY_SAFE_XML with the name of your exported HandySafe XML file
HANDY_SAFE_XML = 'test1.xml'
# CHANGE ME: change SKY_WALLET_CSV with the name of the Sky Wallet CSV file you want to generate
SKY_WALLET_CSV = 'test1.csv'
root = ET.parse(HANDY_SAFE_XML).getroot()
rows = []
customFields = dict()
customFieldIndex = 1
# for each "folder" xml node in the file
for folder in root:
folderName = folder.attrib['name'].encode('utf-8')
# for each "card" xml node in the folder
for card in folder:
# row dictionary maps each column a particular value
row = dict()
# colMapping dictionary maps HandySafe field name to Sky Wallet field name
# Sky Wallet uses two separate columns for each field, ex: "Field 1 Name" and "Field 1 Value"
colMapping = dict()
row['Name'] = card.attrib.get('name', '???').encode('utf-8')
print row['Name']
row['Description'] = '' # not setting description right now
row['Group'] = folderName
fieldIndex = 1 # Sky Wallet columns start at 1
for field in card:
# for some reason "Note" is the only node that doesn't follow convention
# so we force it to be just another field in Sky Wallet
if (field.tag == 'Note'):
fieldName = 'Note'
else:
fieldName = field.attrib.get('name', '???').encode('utf-8')
# HandySafe likes to print out empty <Field/> nodes... not sure why
if fieldName == "???":
print "WARN: Field with no name detected."
continue
# HandySafe also likes to print out duplicate <Field/> nodes.. so
# check if we already added this field to the current row
if (fieldName in colMapping):
print "WARN: %s already contains field %s" % (row['Name'], fieldName)
continue
# Map HandySafe field to Sky Wallet auto-incremented field
customFieldColName = "Field %d Name" % fieldIndex
customFieldColValue = "Field %d Value" % fieldIndex
print "\t%s mapped to %s" % (fieldName, customFieldColName)
colMapping[fieldName] = customFieldColName
row[customFieldColName] = fieldName
if field.text:
row[customFieldColValue] = field.text.encode('utf-8')
else:
row[customFieldColValue] = '' #default to empty string
fieldIndex += 1
# keep track of how many Sky Wallet columns we need to output
if fieldIndex > customFieldIndex:
customFieldIndex = fieldIndex
rows.append(row)
# Write the Sky Wallet CSV file using each row dictionary
with open(SKY_WALLET_CSV, 'wb') as fout:
writer = csv.writer(fout)
# default first three columns
header = ['Name', 'Description', 'Group']
# each of our custom fields
for cf in range(1,customFieldIndex+1):
header.append("Field %d Name" % cf)
header.append("Field %d Value" % cf)
writer.writerow(header)
for row in rows:
rowArray = []
for columnName in header:
if row.has_key(columnName):
rowArray.append(row[columnName])
else:
rowArray.append('')
writer.writerow(rowArray)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.