2009-12-17 22 views
16

GEDCOM è uno standard per lo scambio di dati genealogici.Esiste un parser GEDCOM scritto in Python?

ho trovato parser scritti in

ma nessuno finora scritti in Python. Il più vicino che ho ricevuto è il file libgedcom.py dal progetto GRAMPS, ma è così pieno di riferimenti ai moduli GRAMPS da non essere utilizzabile per me.

Voglio solo una semplice libreria di parser GEDCOM scritta in Python. Questo esiste?

risposta

8

Alcuni anni fa ho scritto un semplicistico convertitore da GEDCOM a XML in Python come parte di larger project. Ho scoperto che trattare i dati GEDCOM in un formato XML era molto più facile (specialmente quando il passo successivo riguardava XSLT).

Non ho il codice online al momento, quindi ho incollato il modulo in questo messaggio. Questo funziona per me; nessuna garanzia. Spero che questo aiuti però.

import codecs, os, re, sys 
from xml.sax.saxutils import escape 

fn = sys.argv[1] 

ged = codecs.open(fn, encoding="cp437") 
xml = codecs.open(fn+".xml", "w", "utf8") 
xml.write("""<?xml version="1.0"?>\n""") 
xml.write("<gedcom>") 
sub = [] 
for s in ged: 
    s = s.strip() 
    m = re.match(r"(\d+) (@(\w+)@)?(\w+)((.*))?", s) 
    if m is None: 
     print "Error: unmatched line:", s 
    level = int(m.group(1)) 
    id = m.group(3) 
    tag = m.group(4) 
    data = m.group(6) 
    while len(sub) > level: 
     xml.write("</%s>\n" % (sub[-1])) 
     sub.pop() 
    if level != len(sub): 
     print "Error: unexpected level:", s 
    sub += [tag] 
    if id is not None: 
     xml.write("<%s id=\"%s\">" % (tag, id)) 
    else: 
     xml.write("<%s>" % (tag)) 
    if data is not None: 
     m = re.match(r"@(\w+)@", data) 
     if m: 
      xml.write(m.group(1)) 
     elif tag == "NAME": 
      m = re.match(r"(.*?)/(.*?)/$", data) 
      if m: 
       xml.write("<forename>%s</forename><surname>%s</surname>" % (escape(m.group(1).strip()), escape(m.group(2)))) 
      else: 
       xml.write(escape(data)) 
     elif tag == "DATE": 
      m = re.match(r"(((\d+)?\s+)?(\w+)?\s+)?(\d{3,})", data) 
      if m: 
       if m.group(3) is not None: 
        xml.write("<day>%s</day><month>%s</month><year>%s</year>" % (m.group(3), m.group(4), m.group(5))) 
       elif m.group(4) is not None: 
        xml.write("<month>%s</month><year>%s</year>" % (m.group(4), m.group(5))) 
       else: 
        xml.write("<year>%s</year>" % m.group(5)) 
      else: 
       xml.write(escape(data)) 
     else: 
      xml.write(escape(data)) 
while len(sub) > 0: 
    xml.write("</%s>" % sub[-1]) 
    sub.pop() 
xml.write("</gedcom>\n") 
ged.close() 
xml.close() 
1

È possibile utilizzare lo strumento SWIG per includere le librerie C attraverso l'interfaccia della lingua nativa. Dovrai effettuare chiamate contro il C api da Python, ma il resto del codice può essere solo Python.

Può sembrare un po 'scoraggiante, ma una volta ottenuta la configurazione delle cose, usare i due insieme non sarà male. Potrebbero esserci alcune stranezze a seconda di come è stata scritta la libreria C, ma dovresti gestirne alcune, indipendentemente dall'opzione che hai usato.

+0

o utilizzare ctypes o Cython (biforcuta da Pyrex). –

-1

Un altro parser di base per il formato GEDCOM 5.5: https://github.com/rootsdev/python-gedcom-parser

+0

Si prega di non pubblicare risposte su domande ovviamente fuori tema! [Vedi: ** Si dovrebbe consigliare su domande fuori tema? **] (http://meta.stackoverflow.com/q/276572/1768232) Le domande fuori tema possono essere chiuse e cancellate, il che potrebbe annullare il tuo contributo. Qui, la domanda è chiedere una risorsa fuori sito ed è in via di chiusura. –