C#的Gedcom阅读器

8

有没有人知道一个好的类可以读取.ged文件?

Gedcom是一种用于存储家谱信息的文件格式。

我的目标是编写一个程序,可以导入ged文件并导出.dot文件给graphviz,以便我可以制作一个家族树的可视化表示。

如果您能帮忙,感谢您!


2
笔误:genealogical 应为 geological。 - Rob Kam
6
GEDCOM是一种家谱文件格式,与地质学或地理位置无关。提到"家族树的视觉表示"可能会有所帮助... - GalacticCowboy
5个回答

6

这是我目前为止的最佳翻译。

虽然它似乎能满足我的需求,但显然并不完美(毕竟我的家谱相当庞大,这增加了一些复杂性)

如果您认为我可以做得更好,请告诉我。

struct INDI
        {
            public string ID;
            public string Name;
            public string Sex;
            public string BirthDay;
            public bool Dead;


        }
        struct FAM
        {
            public string FamID;
            public string type;
            public string IndiID;
        }
        List<INDI> Individuals = new List<INDI>();
        List<FAM> Family = new List<FAM>();
        private void button1_Click(object sender, EventArgs e)
        {
            string path = @"C:\mostrecent.ged";
            ParseGedcom(path);
        }

        private void ParseGedcom(string path)
        {
            //Open path to GED file
            StreamReader SR = new StreamReader(path);

            //Read entire block and then plit on 0 @ for individuals and familys (no other info is needed for this instance)
            string[] Holder = SR.ReadToEnd().Replace("0 @", "\u0646").Split('\u0646');

            //For each new cell in the holder array look for Individuals and familys
            foreach (string Node in Holder)
            {

                //Sub Split the string on the returns to get a true block of info
                string[] SubNode = Node.Replace("\r\n", "\r").Split('\r');
                //If a individual is found
                if (SubNode[0].Contains("INDI"))
                {
                    //Create new Structure
                    INDI I = new INDI();
                    //Add the ID number and remove extra formating
                    I.ID = SubNode[0].Replace("@", "").Replace(" INDI", "").Trim();
                    //Find the name remove extra formating for last name
                    I.Name = SubNode[FindIndexinArray(SubNode, "NAME")].Replace("1 NAME", "").Replace("/", "").Trim(); 
                    //Find Sex and remove extra formating
                    I.Sex = SubNode[FindIndexinArray(SubNode, "SEX")].Replace("1 SEX ", "").Trim();

                    //Deterine if there is a brithday -1 means no
                    if (FindIndexinArray(SubNode, "1 BIRT ") != -1)
                    {
                        // add birthday to Struct 
                        I.BirthDay = SubNode[FindIndexinArray(SubNode, "1 BIRT ") + 1].Replace("2 DATE ", "").Trim();
                    }

                    // deterimin if there is a death tag will return -1 if not found
                    if (FindIndexinArray(SubNode, "1 DEAT ") != -1)
                    {
                        //convert Y or N to true or false ( defaults to False so no need to change unless Y is found.
                        if (SubNode[FindIndexinArray(SubNode, "1 DEAT ")].Replace("1 DEAT ", "").Trim() == "Y")
                        {
                            //set death
                            I.Dead = true;
                        }
                    }
                    //add the Struct to the list for later use
                    Individuals.Add(I);
                }

                // Start Family section
                else if (SubNode[0].Contains("FAM"))
                {
                    //grab Fam id from node early on to keep from doing it over and over
                    string FamID = SubNode[0].Replace("@ FAM", "");

                    // Multiple children can exist for each family so this section had to be a bit more dynaimic

                    // Look at each line of node
                    foreach (string Line in SubNode)
                    {
                        // If node is HUSB
                        if (Line.Contains("1 HUSB "))
                        {

                            FAM F = new FAM();
                            F.FamID = FamID;
                            F.type = "PAR";
                            F.IndiID = Line.Replace("1 HUSB ", "").Replace("@","").Trim();
                            Family.Add(F);
                        }
                            //If node for Wife
                        else if (Line.Contains("1 WIFE "))
                        {
                            FAM F = new FAM();
                            F.FamID = FamID;
                            F.type = "PAR";
                            F.IndiID = Line.Replace("1 WIFE ", "").Replace("@", "").Trim();
                            Family.Add(F);
                        }
                            //if node for multi children
                        else if (Line.Contains("1 CHIL "))
                        {
                            FAM F = new FAM();
                             F.FamID = FamID;
                            F.type = "CHIL";
                            F.IndiID = Line.Replace("1 CHIL ", "").Replace("@", "");
                            Family.Add(F);
                        }
                    }
                }
            }
        }

        private int FindIndexinArray(string[] Arr, string search)
        {
            int Val = -1;
            for (int i = 0; i < Arr.Length; i++)
            {
                if (Arr[i].Contains(search))
                {
                    Val = i;
                }
            }
            return Val;
        }

4
在Codeplex上有一个非常漂亮的展示 FamilyShow (WPF展示)。它可以导入/导出GEDCOM 5.5,而且还有源代码。

家庭展示非常酷。我正在开发一个类似的工具来帮助可视化所有内容。 - Crash893
我现在和家人展示几天了。说实话,它糟透了。它非常漂亮,不要误会,但至少在 XP 中非常容易出现问题,而且无法很好地处理许多事情,其中最小的问题是 GEDCOM 导入。 - Crash893

4

如果没有至少开始的一个,我会感到惊讶。我很容易找到了Gedcom.NETsourceforge)。


我也发现了。这可能是因为我的经验完全不足,但类的结构似乎相当复杂。 - Crash893
1
在你的问题中提到这一点,以及你认为什么很复杂会更有帮助。最好尝试理解这个问题(也许联系作者或在这里提出另一个问题),而不是重新发明一个逐渐变得更加复杂的简化版本。 - Matthew Flaschen
@Matthew Flaschen 我在发布问题后找到了它。 - Crash893
1
它是在Monodevelop下开发的,因此任何错误可能是由于VS/.NET和Monodevelop/Mono之间的差异。这些只是小问题,不应该需要太多修复。 - David Knight

1

如果网络上有一个C#的读取器可以处理这种格式,我会相当惊讶,因为这是一种相当专业化的格式。好消息是,这个格式看起来很容易阅读,如果你需要创建自己的读取器,我建议你走这条路线,如果你对实现有具体的问题,再回到SO上提问。看一下System.IO.StreamReader类;用这种方式逐行读取文件非常简单,解析每一行也应该很简单。

祝你好运!


我知道那可能是即将发生的事情。如果可能的话,我想避免这种情况(无需重新发明轮子)。 - Crash893
我觉得我可能有一个想法,我想如何完成这个任务——每个个体都是有界限的。然后,每个家庭都通过指向涉及的个体进行了划分。我认为,如果只是阅读这些信息,我就可以完成。我希望它们能像其他文明格式一样采用XML。 - Crash893

0

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