转换M8的XML通讯录为通用的VCard(VCF)格式

自从2011年某月某日,在广州大学城的公交上丢了手机之后,就一直用者同学的旧手机。过年后,钱够了,就打算买手机!于是,把以前M8的通讯录转换为Android可以导入的VCF文件。

Android2.3使用的VCard版本为3.0,我导出了一个样例用于分析:

BEGIN:VCARD
VERSION:3.0
N:黄;小虾;;;
FN:黄小虾
TEL;TYPE=CELL:13800138000
TEL;TYPE=WORK:02010086
EMAIL;TYPE=WORK:xiaoxia@xiaoxia.org
ADR;TYPE=WORK;CHARSET=UTF-8:;;c12-151;广州;广东;510006;
URL:xiaoxia.org
PHOTO;ENCODING=B;TYPE=PNG:iVBOR(… 此处省略编码后的图片数据)CYII=
X-QQ:10000
END:VCARD

从上面样例可以猜出VCard的大致格式。使用(\r\n)换行表示多个键,冒号(:)把键名和键值分开。分号(;)用来加入参数。

Name[;Attribute=AttributeValue]:Value[;MoreValue]

对上述样例中用到的键名的解释:

BEGIN:VCARD    用于开始一个VCard记录。
VERSION:3.0    VCard的版本。
N:姓氏;名字;中间名;尊称(先生、女士、小姐);不知道
FN             格式化的显示全名
TEL            电话号码
EMAIL          电子邮件
URL            网站
ADR            地址
PHOTO          个人照片
X-QQ           QQ号码
X-TWITTER      Twitter用户名
END:VCARD      一个VCard记录的结束。

再来研究一下M8里备份的通讯录的格式,下面是我抽取的一个示例。

文件名 mycontact.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<ContactTable>
    <Contact>
        <FileAs>楚中天</FileAs>
        <FirstName>中天</FirstName>
        <LastName>楚</LastName>
        <Phone>
            <PhoneElement IsPrimary="1" Value="10086" Type="0" />
            <PhoneElement IsPrimary="0" Value="13800138000" Type="0" />
        </Phone>
    </Contact>
    <Contact>
        <FileAs>林蛋大</FileAs>
        <FirstName>蛋大</FirstName>
        <LastName>林</LastName>
        <Phone>
            <PhoneElement IsPrimary="1" Value="10010" Type="0" />
        </Phone>
    </Contact>
</ContactTable>

看起来,好像XML的更加易读,但是体积也会比VCF的体积要大。

下面写一小段Python代码来做这个格式转换的工作(又是Python哦,要是有别的语言写起来更简洁,我会考虑学习一下)。

#!/usr/bin/env python
# coding: utf-8

from xml.etree import ElementTree as ET

# 输出到的VCF文件
out = file("mycontact.vcf", "wb")

# 从M8的XML通讯录读取每条记录。
root = ET.parse(file("mycontact.xml", "r")).getroot()
for e in root.findall('Contact'):
    out.write('BEGIN:VCARD\r\nVERSION:3.0\r\n')
    out.write('N:%s;%s;;;\r\n' % 
        (e.findtext('LastName', '').encode('utf8'), e.findtext('FirstName', '').encode('utf8')))
    out.write('FN:%s\r\n' % (e.findtext('FileAs', '').encode('utf8')))
    # 枚举号码条目
    for ee in e.find('Phone').findall('PhoneElement'):
        primary = int(ee.get('IsPrimary'))
        out.write('TEL;TYPE=CELL%s:%s\r\n' % 
            ( (';TYPE=PREF' if primary else ''), ee.get('Value')))
    out.write('END:VCARD\r\n')

out.close()

一开始运行遇到异常,原因是e.findtext(‘LastName’, ”)得到的值本应是utf8的,结果被Python转换成了unicode,所以最后还是要自己再encode为utf8。因为VCard文件编码必须为utf8。

执行转换后,结果如下:

文件名 mycontact.vcf

BEGIN:VCARD
VERSION:3.0
N:楚;中天;;;
FN:楚中天
TEL;TYPE=CELL;TYPE=PREF:10086
TEL;TYPE=CELL:13800138000
END:VCARD
BEGIN:VCARD
VERSION:3.0
N:林;蛋大;;;
FN:林蛋大
TEL;TYPE=CELL;TYPE=PREF:10010
END:VCARD

怎么样?体积小巧了,但是没有XML的那么有层次,那么容易看懂。

如果有时间的话,我打算用HTML5做一个在线给VCF通讯录的记录添加自定义照片的。觉得有需要的,请支持我 :)

参考文献:

http://en.wikipedia.org/wiki/VCard

RFC2426

RFC6350

转换M8的XML通讯录为通用的VCard(VCF)格式》上有20条评论

    1. Xiaoxia 文章作者

      我本来也打算买Defy+的,不过后来考虑了很久,觉得大屏幕比较适合我。经常用来看资料和查资料,所以买了me865.

      回复
    1. Xiaoxia 文章作者

      哈!应该是缓存问题吧。那个域名对应的缓存页面没有更新。
      我没有给缓存的静态页面设置超时,所以它会一直是那个页面 :-)

      回复
    1. 叫我小T

      Ca神……原来用M8的人还是不少的啊……我的M8也是去年丢的,当时好久没备份通讯录了,就剩下魅族网站上同步的一些,于是直接导入到gmail里了。
      另外,印象里听说M8似乎用的是EDB?

      回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>