Skip to content

Instantly share code, notes, and snippets.

@fredlahde
Last active January 17, 2019 14:56
Show Gist options
  • Save fredlahde/8b1075ba87f69d749d621f4624369f36 to your computer and use it in GitHub Desktop.
Save fredlahde/8b1075ba87f69d749d621f4624369f36 to your computer and use it in GitHub Desktop.
Convert from google exported contacts csv to Fritz!Box xml for importing
import csv
header = ['Name', 'Given Name', 'Additional Name', 'Family Name', 'Yomi Name', 'Given Name Yomi', 'Additional Name Yomi', 'Family Name Yomi', 'Name Prefix', 'Name Suffix', 'Initials', 'Nickname', 'Short Name', 'Maiden Name', 'Birthday', 'Gender', 'Location', 'Billing Information', 'Directory Server', 'Mileage', 'Occupation', 'Hobby', 'Sensitivity', 'Priority', 'Subject', 'Notes', 'Language', 'Photo', 'Group Membership', 'E-mail 1 - Type', 'E-mail 1 - Value', 'E-mail 2 - Type', 'E-mail 2 - Value', 'E-mail 3 - Type', 'E-mail 3 - Value', 'IM 1 - Type', 'IM 1 - Service', 'IM 1 - Value', 'Phone 1 - Type', 'Phone 1 - Value', 'Phone 2 - Type', 'Phone 2 - Value', 'Phone 3 - Type', 'Phone 3 - Value', 'Address 1 - Type', 'Address 1 - Formatted', 'Address 1 - Street', 'Address 1 - City', 'Address 1 - PO Box', 'Address 1 - Region', 'Address 1 - Postal Code', 'Address 1 - Country', 'Address 1 - Extended Address', 'Organization 1 - Type', 'Organization 1 - Name', 'Organization 1 - Yomi Name', 'Organization 1 - Title', 'Organization 1 - Department', 'Organization 1 - Symbol', 'Organization 1 - Location', 'Organization 1 - Job Description']
#for i,s in enumerate(header):
#print(i,s)
XML_TEMPLATE = """<?xml version="1.0" encoding="utf-8"?>
<phonebooks>
<phonebook>
%s
</phonebook>
</phonebooks>
"""
CONTACT_XML_TEMPLATE = """ <contact>
<category>0</category>
<person>
<realName>%s</realName>
</person>
<telephony nid="%d">
%s
</telephony>
<services/>
<setup/>
<features doorphone="0"/>
<mod_time>1547652319</mod_time>
<uniqueid>%d</uniqueid>
</contact> """
PHONE_XML_TEMPLATE = """ <number type="%s" prio="0" id="%s">%s</number> """
def to_lower_case(s):
if len(s) < 2:
return s
return s[0].lower() + s[1:]
class Contact:
def __init__(self):
self.name = None
self.last_name = None
self.phone_1_type = None
self.phone_1_value = None
self.phone_2_type = None
self.phone_2_value = None
self.phone_3_type = None
self.phone_3_value = None
def set_name(self, name, last_name):
self.name = name
self.last_name = last_name
def set_phone_1(self, p_type, number):
if not p_type:
p_type = "home"
self.phone_1_type = p_type
self.phone_1_value = number
def set_phone_2(self, p_type, number):
if not p_type:
p_type = "home"
self.phone_2_type = p_type
self.phone_2_value = number
def set_phone_3(self, p_type, number):
if not p_type:
p_type = "home"
self.phone_3_type = p_type
self.phone_3_value = number
def to_xml(self, uid):
real_name = "%s %s" % (self.name, self.last_name)
if self.phone_1_type is None:
return ""
phones = []
phone_1_xml = PHONE_XML_TEMPLATE % (to_lower_case(self.phone_1_type), 0, self.phone_1_value)
phones.append(phone_1_xml)
if self.phone_2_type is not None:
phone_2_xml = PHONE_XML_TEMPLATE % (to_lower_case(self.phone_2_type), 1, self.phone_2_value)
phones.append(phone_2_xml)
if self.phone_3_type is not None:
phone_3_xml = PHONE_XML_TEMPLATE % (to_lower_case(self.phone_3_type), 1, self.phone_3_value)
phones.append(phone_3_xml)
ps = '\n'.join(phones)
return CONTACT_XML_TEMPLATE % (real_name, len(phones), ps, uid)
# CSV column numbers, refer to header array
NAME = 1
LAST_NAME = 3
PHONE_1_TYPE = 38
PHONE_1_VALUE = 39
PHONE_2_TYPE = 40
PHONE_2_VALUE = 41
PHONE_3_TYPE = 42
PHONE_3_VALUE = 43
csv_file = csv.reader(open("contacts.csv"), delimiter=',')
contacts = []
def sanitize_number(number):
if ":::" in number:
number = number[number.index(":::")+4:]
return number.strip()
for i, row in enumerate(csv_file):
if i == 0:
continue
c = Contact()
if not row[NAME] or not row[LAST_NAME]:
continue
c.set_name(row[NAME], row[LAST_NAME])
if row[PHONE_1_VALUE]:
c.set_phone_1(row[PHONE_1_TYPE], sanitize_number(row[PHONE_1_VALUE]))
if row[PHONE_2_VALUE]:
c.set_phone_2(row[PHONE_2_TYPE], sanitize_number(row[PHONE_2_VALUE]))
if row[PHONE_3_VALUE]:
c.set_phone_3(row[PHONE_3_TYPE], sanitize_number(row[PHONE_3_VALUE]))
contacts.append(c)
xml_parts = []
for i,c in enumerate(contacts):
xml_parts.append(c.to_xml(i))
print(XML_TEMPLATE % ('\n'.join(xml_parts)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment