族谱数据来源杂乱,是修谱工具在数据导入环节面对的第一道坎。一个宗族修谱,各房交上来的材料格式五花八门:长房用Excel表格,列名写“父亲”;二房用CSV,列名写“爸爸”;三房从其他家谱软件导出GEDCOM文件;海外分支发来一份JSON,键名全是英文。如果修谱工具要求用户先把所有材料统一成一种格式再导入,那这个工具在实际修谱场景中基本不可用。
本文从架构设计的角度,拆解修谱工具如何用程序解析不同格式、如何做统一结构映射,让任意来源的数据都能进入同一套数据模型。重点在解析器层与映射层的设计,不在具体某一种格式的语法细节。
一、多格式解析的架构:三层分离
面对多种格式,最容易想到的做法是“每种格式写一套导入逻辑”,从解析到入库一条龙。这个做法在格式少、需求稳定时可行,但格式一多、字段映射规则一变,代码就会变成一团乱麻——Excel的导入逻辑里嵌着姓名解析,GEDCOM的导入逻辑里又重复一遍。
我们的做法是把导入架构拆成三层,每层只做一件事:
第一层,格式解析器层。每种格式对应一个解析器,职责单一:读取原始文件,输出一个统一的中性数据帧。解析器不关心字段映射,不关心业务规则,它只负责把Excel的行、CSV的记录、JSON的对象、GEDCOM的层级记录,转成同一种中间结构。
第二层,中性数据帧层。这是三层架构的核心。中性数据帧是一个与源格式无关的中间结构,包含两个部分:人员记录列表和关系记录列表。人员记录里存放从源文件读出的原始键值对,关系记录里存放从源文件识别出的父子、配偶关联。中性数据帧的字段名是统一的内部命名,与源文件的列名无关。
第三层,映射与业务层。这一层读取中性数据帧,执行列名映射、关系补全、字辈推算、校验等业务逻辑,最终写入数据库。
三层分离的收益是:新增一种格式,只需要写一个解析器,映射层和业务层完全复用。修改映射规则,不影响解析器。各层可以独立测试——解析器用样例文件测,映射层用构造的中性数据帧测,互不依赖。
二、格式解析器的实现差异
四种格式的解析器,实现方式各不相同,但输出统一。
Excel解析器。Excel文件本质是一个压缩的XML包,解析时用openpyxl逐工作表读取。难点在于表头行位置不固定——有的文件第一行是标题,第二行才是表头;有的文件前面还有说明文字。解析器的处理方式是扫描前若干行,找到包含“姓名”“父亲”“世代”等关键词密度最高的那一行作为表头,其余行按数据行处理。多工作表的情况,解析器逐一读取,每个工作表产出一组人员记录,关系记录在映射层再做关联。
CSV解析器。CSV的解析看似简单,实际有两个坑。第一是编码——国内修谱材料常见GBK和GB18030编码,海外材料多为UTF-8,解析器需要自动探测编码,探测失败时回退到用户手动指定。第二是分隔符——标准CSV用逗号,但实际文件中逗号、制表符、分号都有。解析器通过统计每行各候选分隔符的出现次数来推断,推断结果写入解析日志,用户可在导入预览中确认。
JSON解析器。JSON的解析依赖结构化约定。我们定义了一套内部Schema,解析器读取JSON后先做结构校验,检查必需的键是否存在。缺失的键填充默认值,多余的键存入扩展属性中不丢弃。JSON的嵌套结构(比如一个人的配偶列表嵌套在人员对象内)由解析器展平为人员记录加关系记录。
GEDCOM解析器。GEDCOM是层级化文本格式,每行以层级号开头,通过缩进表达嵌套关系。解析器逐行读取,维护一个层级栈,遇到INDI记录开启一个人员,遇到FAM记录开启一个家庭,遇到CHIL、HUSB、WIFE等标签记录关系。GEDCOM的Family结构在解析器内部被转换为人员记录加关系记录,不保留Family作为中间实体——这与我们的数据模型一致,关系直接建立在人与人间。
三、列名智能映射:从“父亲”“爸爸”到“father”
解析器输出的中性数据帧,人员记录的键名是源文件的原始列名。映射层的任务,是把这些原始列名对应到内部字段。
映射层的核心是一份别名词典。词典覆盖常见列名变体:父亲、爸爸、爹、父、老爹、father、Dad、Parent,全部映射到father_id;姓名、名字、name、full_name映射到name;出生年、生年、birth、year_of_birth映射到birth_year。词典条目按类别组织,每个类别有主字段名和一组别名。
映射执行分两步。第一步,对原始列名做归一化——去除空白、统一大小写、繁简转换、去除标点。第二步,归一化后的列名在词典中查找,命中则建立映射。未命中的列名进入待映射列表,在导入预览界面中呈现给用户,由用户手动指定该列对应的内部字段。用户确认后,映射规则被缓存,下次导入同结构文件时自动复用。
映射层还处理两种特殊情况。第一种是横向数据转置:海外亲属整理的表格常以“一行一个家庭”的形式存在,列名是“父亲”“母亲”“子女1”“子女2”“子女3”。映射层识别到这种结构后,把每个子女列拆成独立的人员记录,与父母建立关系。第二种是姓/名分列:源文件把姓和名分开存储,映射层在读取时拼接为全名,同时保留原始分列信息供按姓或名检索。
四、海外寻根场景的格式兼容
海外亲友常发来GEDCOM、Excel、CSV或手写谱扫描件,修谱软件需要把这些不同格式的跨境家族资料归拢到同一套结构中。
跨境资料的格式兼容有两个额外难点。第一是姓名的罗马化:海外资料中的姓名常以拼音或方言罗马字记录,“Chen Ming”对应“陈明”,“Tan Ah Kow”对应闽南语“陈亚九”。映射层内置了常见姓氏和地名的罗马化对照表,在拼接姓名时尝试还原为中文,还原结果标记为“待确认”,不强制采用。第二是世代的隐式表达:海外资料可能不写“第几世”,而是写“祖父的祖父”,映射层需要根据亲属关系链推算世代数,推算结果同样标记为待确认。
手写谱扫描件的处理不在解析器的职责范围内——扫描件需要先经过OCR转录为文本,再交给解析器。修谱工具在这一环节提供的是导入后的线索管理,而非OCR本身。
五、结语
修谱工具兼容任意来源数据导入的能力,本质上是架构设计的问题。格式解析器层负责把不同格式转成统一结构,中性数据帧层提供与源格式无关的中间表达,映射与业务层负责列名对应和业务规则。三层分离,各司其职,新增格式的成本被压到最低。
知烛的数据导入模块按这套架构实现,四种格式的解析器共享同一条下游处理管线。知烛作为一款面向大型宗族数据管理的修谱软件,在导入架构上的设计思路是:格式是入口,结构是核心。入口可以多变,结构必须统一。家谱软件的价值不仅在于能录入新数据,更在于能把不同来源的旧数据接得住、理得清。
注:本文所述的数据架构与算法,均已应用于《知烛宗族管理系统》。该软件已获国家版权局计算机软件著作权登记(登记号:2026SR0967638),并已通过 Microsoft Store 官方审核,面向全球 240 个国家和地区发行。知烛致力于为海内外华人提供纯本地化(不上云/不注册)的修谱工具与海外寻根中转站。