【问题标题】:Parse Gedcom to SQLite-Database将 Gedcom 解析为 SQLite 数据库
【发布时间】:2015-09-01 07:15:37
【问题描述】:

我是一个爱好 Xojo 用户。我想将 Gedcom 文件导入我的程序,尤其是 SQLite 数据库。

数据库结构

表格

人员

 - ID: Integer
 - Gender: Varchar // M, F or U
 - Surname: Varchar
 - Givenname: Varchar

关系

 - ID: Integer
 - Husband: Integer
 - Wife: Integer

儿童

 - ID: Integer
 - PersonID: Integer
 - FamilyID: Integer
 - Order: Integer

人物事件

 - ID: Integer
 - PersonID: Integer
 - EventType: Varchar // e.g. BIRT, DEAT, BURI, CHR
 - Date: Varchar
 - Description: Varchar
 - Order: Integer

关系事件

 - ID: Integer
 - RelationshipID: Integer
 - EventType: Varchar // e.g. MARR, DIV, DIVF
 - Date: Varchar
 - Description: Integer
 - Order: Integer

我写了一个有效的 Gedcom-Line-Parser。他将单个 Gedcomline 拆分为:

 - Level As Integer
 - Reference As String // optional
 - Tag As String
 - Value As String // optional

我通过 TextInputStream 加载 Gedcom 文件(工作正常)。不,我需要解析每一行。

Gedcom-个人样本

0 @I1@ INDI
1 NAME George /Clooney/
2 GIVN George
2 SURN Clooney
1 BIRT
2 DATE 6 MAY 1961
2 PLAC Lexington, Fayette County, Kentucky, USA

你会看到,Level-Numbers 向我们展示了一个“树状结构”。所以我认为将文件解析为分离的对象(PersonObj、RelationshipObj、EventObj 等)到 JSONItem 中是最好和最简单的方法,因为它很容易获得节点的子节点。稍后,我可以简单地读取节点、子节点来创建数据库条目。但我不知道如何创建这样的算法。

谁能帮帮我?

【问题讨论】:

  • 由于这个问题相当复杂和个别,可能需要一些来回讨论,我认为这个问题最好在 Xojo 论坛中提出。
  • 嗨 Thomas Tempelmann ;) 我以前做过很多次,但看起来,没有人对这个领域真正感兴趣:/ 这就是我在这里问的原因。也许你可以给我更多的意见?
  • 我什至不明白你的困难在哪里。一方面,你可以描述算法,但你说你不能编码。有很多事情你可能知道也可能不知道,我假设你什么都不知道,问的有点太多了,我在这里提供了一个完整的解决方案,可能要花半个小时。
  • 好吧,我花了整个晚上来编写和描述一个结构和一个简单的解析器。它工作正常但我认为,如果 Gedcom 文件有 10000 或更多行,应用程序将冻结。我会通知你的!
  • 是的,如果您有一些工作并需要优化或修复它的想法,这是人们更愿意提供帮助的地方,因为他们可以确切地看到您所做的事情。

标签: algorithm vb6 realbasic xojo gedcom


【解决方案1】:

要以良好的速度解析 Gedcom 行,请尝试以下想法:

将整个文件读入一个字符串并拆分行:

dim f as FolderItem = ...
dim fileContent as String = TextInputStream.Open(f).ReadAll
fileContent = fileContent.DefineEncoding (Encodings.WindowsLatin1)
dim lines() as String = ReplaceLineEndings(fileContent,EndOfLine).Split(EndOfLine)

使用 RegEx 解析每一行以提取其 3 列

dim re as new RegEx
re.SearchPattern = "^(\d+) ([^ ]+)(.*)$"
for each line as String in lines
  dim rm as RegExMatch = re.Search (line)
  if rm = nil then
    // nothing found in this line. Is this correct?
    break
    continue // -> onward with next line
  end
  dim level as Integer = rm.SubExpressionString(1).Val
  dim code as String = rm.SubExpressionString(2)
  dim value as String = rm.SubExpressionString(3).Trim
  ... process the level, code and value
next

RegEx 搜索模式意味着它会查找行首 ("^"),然后查找一个或多个数字 ("\d")、一个空白、一个或多个非空白字符 ("[^ ]"),最后是字符串结尾之前的任何字符 (".") ("$")。每个组周围的括号用于使用 SubExpression() 提取它们的结果。

只要该行不包含至少一个数字、一个空格和至少一个字符,就会对 rm = nil 进行检查。如果 Gedcom 文件格式错误或有空行,则可能是这种情况。

希望这会有所帮助。

【讨论】:

  • 谢谢你,Thomas,我以前就是这样使用 RegEx。 ;) 我会继续我的解析器,如果还有更多问题,我会告诉你的。当然,讨论还没有结束……:D
  • 如果我的回答对您有帮助,请不要忘记点赞。这就是你给别人加分的方式,也是你最终在这里得到一些分的方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-27
  • 1970-01-01
  • 1970-01-01
  • 2016-08-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多