|
from __future__ import print_function |
|
|
|
import glob |
|
import lxml.etree as ET |
|
import os |
|
import sys |
|
import isodate |
|
import datetime |
|
|
|
TOMBOY_CAT_PREFIX = 'system:notebook:' |
|
|
|
EV_EXPORT_XML = u"""<?xml version="1.0" encoding="UTF-8"?> |
|
<!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export3.dtd"> |
|
""" |
|
|
|
EV_NOTE_XML = u"""<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"> |
|
""" |
|
|
|
EV_DATE_FORMAT = '%Y%m%dT%H%M%SZ' |
|
|
|
def el(name): |
|
return '{http://beatniksoftware.com/tomboy}' + name |
|
|
|
def innertext(tag): |
|
"""Convert Tomboy XML to Markdown""" |
|
|
|
text = (tag.text or '') |
|
|
|
if tag.tag == el('bold'): |
|
text = '**' + text.strip() + '**' |
|
elif tag.tag == el('list-item'): |
|
text = '- ' + text |
|
|
|
return text + ''.join(innertext(e) for e in tag) + (tag.tail or '') |
|
|
|
def append_content(path, content): |
|
with open(path, 'r') as f: |
|
existingContent = f.read().decode('utf8') |
|
|
|
if -1 == existingContent.find(content): |
|
with open(path, 'a') as f: |
|
content = u'\n* *\n *\n\n' + content |
|
f.write(content.encode('utf8')) |
|
|
|
def extract_data(path): |
|
root = ET.parse(path).getroot() |
|
|
|
tags = [] |
|
category = None |
|
|
|
tagsEl = root.find(el('tags')) |
|
if tagsEl is not None: |
|
for tagEl in tagsEl: |
|
tag = tagEl.text |
|
|
|
if tag.startswith(TOMBOY_CAT_PREFIX): |
|
category = tag.replace(TOMBOY_CAT_PREFIX, '') |
|
else: |
|
tags.append(tag) |
|
|
|
if 'system:template' in tags: |
|
return None |
|
|
|
note = {} |
|
|
|
title = root.find(el('title')).text |
|
contentTag = root.find(el('text')).find(el('note-content')) |
|
content = innertext(contentTag) |
|
|
|
note['title'] = title |
|
note['content'] = content.replace(title, '').lstrip() |
|
|
|
for tag, key in [('create-date', 'created'), ('last-change-date', 'updated')]: |
|
dateTag = root.find(el(tag)) |
|
note[key] = isodate.parse_datetime(dateTag.text) |
|
|
|
note['tags'] = tags |
|
note['category'] = category |
|
|
|
return note |
|
|
|
def prepare_content(text_content): |
|
tree = ET.Element('en-note') |
|
|
|
for line in text_content.split('\n'): |
|
el = ET.SubElement(tree, 'div') |
|
|
|
line = line.strip() |
|
if line != '': |
|
el.text = line |
|
else: |
|
ET.SubElement(el, 'br') |
|
|
|
return EV_NOTE_XML + ET.tostring(tree, pretty_print=True) |
|
|
|
def export_one(note, path, export_dt): |
|
tree = ET.Element('en-export', { |
|
'application': 'Tomboy Exporter', |
|
'version': '0.1', |
|
'export-date': export_dt.strftime(EV_DATE_FORMAT) |
|
}) |
|
|
|
noteTag = ET.SubElement(tree, 'note') |
|
|
|
titleTag = ET.SubElement(noteTag, 'title') |
|
titleTag.text = note['title'] |
|
|
|
contentTag = ET.SubElement(noteTag, 'content') |
|
contentTag.text = ET.CDATA(prepare_content(note['content'])) |
|
|
|
for key in ['created', 'updated']: |
|
dateTag = ET.SubElement(noteTag, key) |
|
dateTag.text = note[key].strftime(EV_DATE_FORMAT) |
|
|
|
for tag in note['tags']: |
|
tagEl = ET.SubElement(noteTag, 'tag') |
|
tagEl.text = tag |
|
|
|
with open(path, 'w') as f: |
|
f.write(EV_EXPORT_XML) |
|
ET.ElementTree(tree).write(f) |
|
f.write('\n') |
|
|
|
def main(): |
|
if len(sys.argv) < 2: |
|
print('usage: python tomboy-export.py <tomboy-dir>', file=sys.stderr) |
|
sys.exit(1) |
|
|
|
export_dt = datetime.datetime.now() |
|
|
|
count = 0 |
|
|
|
for path in glob.glob(sys.argv[1] + '/*.note'): |
|
note = extract_data(path) |
|
|
|
if not note: |
|
continue |
|
|
|
notePath = 'export/' |
|
if note['category']: |
|
notePath = os.path.join(notePath, note['category']) |
|
|
|
if not os.path.exists(notePath): |
|
os.makedirs(notePath) |
|
|
|
notePath = os.path.join(notePath, note['title'].replace('/', '|') + '.enex') |
|
|
|
export_one(note, notePath, export_dt) |
|
|
|
count += 1 |
|
|
|
print('Exported %s notes.' % count) |
|
|
|
main() |
@scribu It doesn't respect bold or italic format. When I import it through api, all formattings are lost.