有没有用Python编写的GEDCOM解析器?

18

GEDCOM是一种交换家谱数据的标准。

我找到了用以下语言编写的解析器:

但迄今为止还没有用Python编写的解析器。我找到的最接近的是GRAMPS项目中的libgedcom.py文件,但它包含太多对GRAMPS模块的引用,无法满足我的需求。

我只想要一个简单的、独立的、用Python编写的GEDCOM解析器库。这种解析器存在吗?

6个回答

10

几年前,我在一个大型项目中写了一个基于Python的简单GEDCOM到XML转换器。我发现将GEDCOM数据处理成XML格式要容易得多(特别是当下一步涉及XSLT时)。

目前我没有将代码发布在线上,但我已经将模块粘贴在了这条信息里。对我来说它是可用的,但不保证适用于所有情况。希望这能帮到您。

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()

7
我借鉴了mwhite的答案,并进行了一些扩展(好吧,不只是一点点),并在github上发布了:http://github.com/dijxtra/simplepyged。我欢迎关于还可以添加什么的建议 :-)

5

2

1

你可以使用SWIG工具通过本地语言接口来包含C库。你需要在Python中调用C api,但是你的其余代码可以只用Python。

听起来可能有点令人生畏,但一旦你设置好了,两者一起使用就不会太糟糕。根据C库的编写方式,可能会有一些怪癖,但无论你使用哪个选项,都必须处理一些问题。


或者使用ctypes或Cython(从Pyrex分叉)。 - Peter Hansen

0

请不要在明显与主题无关的问题上发布答案!参见:是否应该就与主题无关的问题提供建议? 与主题无关的问题可能会被关闭和删除,这可能会使您的贡献无效。在这里,问题正在寻求一个离线资源,并且正在被关闭。 - Kyll

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接