XBEL2Moin

This script takes a bookmarks file in XBEL format on the command line and spits out a Wiki page in MoinMoin format on standard out. Bookmark folder titles are rendered as headings with increasing levels according to the hierarchy depth of the folders. Run xbel2moin.py -h for help on command line options.

The script requires Python >= 2.3 and the ElementTree library

Download: xbel2moin.py

   1 #!/usr/bin/env python
   2 # -*- coding: UTF-8 -*-
   3 """Converts an XBEL bookmark file into a flat listing in MoinMoin wiki format.
   4 """
   5 
   6 # standard-library modules
   7 import os
   8 import re
   9 import sys
  10 from optparse import OptionParser
  11 
  12 # third-party modules
  13 import elementtree.ElementTree as ET
  14 
  15 __program__   = "xbel2moin.py"
  16 __author__    = "Christopher Arndt"
  17 __version__   = "0.1"
  18 __revision__  = "$Rev: 142 $"
  19 __date__      = "$Date: 2007-06-13 23:34:39 +0200 (Mi, 13 Jun 2007) $"
  20 __copyright__ = "MIT license"
  21 
  22 __usage__ = """\
  23 %prog [OPTIONS] <XBEL file>
  24 """
  25 
  26 FOOTER = """\
  27 
  28 ----
  29 
  30 ''generated by [attachment:xbel2moin.py xbel2moin.py] on %(date)s from
  31 [attachment:%(source)s %(source)s]''
  32 """
  33 
  34 
  35 def usage():
  36     optparser.print_help()
  37 
  38 mangle_re = re.compile(r'\s+', re.DOTALL)
  39 def manglews(text):
  40     return mangle_re.sub(u' ', text.strip())
  41 
  42 def make_heading(text, lvl):
  43     return u"%s %s %s\n" % ('=' * lvl, text, '=' * lvl)
  44 
  45 def make_bookmark(elem):
  46     title = elem.find('title')
  47     if ET.iselement(title):
  48         titletext = title.text.strip()
  49     else:
  50         titletext = u'Unnamed bookmark'
  51     desc = elem.find('desc')
  52     if ET.iselement(desc):
  53         desctext = u'\n\n  ' + manglews(desc.text)
  54     else:
  55         desctext = u""
  56     return u"'''[%s %s]'''%s\n" % (elem.get('href', u'#'), titletext,
  57       desctext)
  58 
  59 def parse_folder(elem, headlvl):
  60     text = []
  61     title = elem.find('title')
  62     if ET.iselement(title):
  63         text.append(make_heading(title.text, headlvl+1))
  64     elif headlvl != 0:
  65         text.append(make_heading(u'Unnamed folder', headlvl+1))
  66     if headlvl == 0 and options.toc:
  67         text.append(u'[[TableOfContents([%i])]]\n' % options.tocdepth)
  68     for subelem in elem:
  69         if subelem.tag == 'folder':
  70             text.append(parse_folder(subelem, headlvl+1))
  71         if subelem.tag == 'bookmark':
  72             text.append(make_bookmark(subelem))
  73     return u"\n".join(text)
  74 
  75 def xbel2moin(filename):
  76     tree = ET.parse(filename)
  77     root = tree.getroot()
  78     headlvl = 0
  79     doc = parse_folder(root, headlvl)
  80     if options.footer:
  81         import locale
  82         import time
  83         locale.setlocale(locale.LC_ALL, '')
  84         doc += FOOTER % dict(date=time.strftime('%x %X'), source=filename)
  85     return doc
  86 
  87 def main(args):
  88     global options, optparser
  89 
  90     optparser = OptionParser(prog=__program__, usage=__usage__,
  91       version=__version__, description=__doc__)
  92     # optparser.add_option("-v", "--verbose",
  93       # action="store_true", dest="verbose", default=False,
  94       # help="Print what's going on to stdout.")
  95     optparser.add_option("-t", "--toc",
  96       action="store_true", dest="toc", default=False,
  97       help="Add a table of contents macro after the first heading.")
  98     optparser.add_option("-d", "--toc-depth",
  99       action="store", type="int", dest="tocdepth", default=3,
 100       help="How many heading levels to display in the TOC (default 3).")
 101     optparser.add_option("-f", "--add-footer",
 102       action="store_true", dest="footer", default=False,
 103       help='Add a footer with a "generated by" notice.')
 104 
 105     (options, args) = optparser.parse_args(args=args)
 106     if args:
 107         print xbel2moin(args[0])
 108     else:
 109         usage()
 110         return 2
 111     return 0
 112 
 113 if __name__ == '__main__':
 114     sys.exit(main(sys.argv[1:]))

MoinMoin: Xbel2MoinConverter (last edited 2007-10-29 19:08:39 by localhost)