// Parser
        public static CSourceCallNumber Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string sSourceCallNumber;
            string sSourceMediaType = "";

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(nLevel, "CALN")) == null)
            {
                // Not one of us
                return null;
            }
            gedcom.IncrementLineIndex(1);
            sSourceCallNumber = gedcomLine.LineItem;

            if( (gedcomLine = gedcom.GetLine(nLevel+1, "MEDI")) != null  )
            {
                sSourceMediaType = gedcomLine.LineItem;
                gedcom.IncrementLineIndex(1);
            }
            else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
            {
                LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                gedcom.IncrementLineIndex(1);
            }

            // Parsing went ok. Construct a new object and return it.
            CSourceCallNumber scn = new CSourceCallNumber( gedcom );
            scn.m_sSourceCallNumber = sSourceCallNumber;
            scn.m_sSourceMediaType = sSourceMediaType;
            return scn;
        }
        // Parser
        public static CEventRecorded Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string eventRecorded;
            string datePeriod = "";
            string sourceJurisdictionPlace = "";

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(nLevel, "EVEN")) == null)
            {
                // Not one of us
                return null;
            }
            gedcom.IncrementLineIndex(1);
            eventRecorded = gedcomLine.LineItem;

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                if( (gedcomLine = gedcom.GetLine(nLevel+1, "DATE")) != null  )
                {
                    datePeriod = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "PLAC")) != null  )
                {
                    sourceJurisdictionPlace = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            // Parsing went ok. Construct a new object and return it.
            CEventRecorded er = new CEventRecorded( gedcom );
            er.m_sEventRecorded = eventRecorded;
            er.m_sDatePeriod = datePeriod;
            er.m_sSourceJurisdictionPlace = sourceJurisdictionPlace;
            return er;
        }
        public static CNameRomanizedVariation Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLIne;

            // Temporary holders for class members. Saves constructing a class early.
            string sNameRomanizedVariation;
            string sRomanizedType = "";
            CPersonalNamePieces pnp, personalNamePieces=null;

            // There must be one of these, it defines the object.
            if ((gedcomLIne = gedcom.GetLine(nLevel, "ROMN")) == null)
            {
                // Not one of us
                return null;
            }
            sNameRomanizedVariation = gedcomLIne.LineItem;
            gedcom.IncrementLineIndex(1);

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                if( (gedcomLIne = gedcom.GetLine(nLevel+1, "TYPE")) != null )
                {
                    sRomanizedType = gedcomLIne.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (pnp = CPersonalNamePieces.Parse( gedcom, nLevel+1 )) != null )
                {
                    personalNamePieces = pnp;
                    bParsingFinished = false;
                }
                else if( ( gedcomLIne = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLIne.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            // Parsing went ok. Construct a new object and return it.
            CNameRomanizedVariation nrv = new CNameRomanizedVariation( gedcom );
            nrv.m_sNameRomanizedVariation = sNameRomanizedVariation;
            nrv.m_sRomanizedType = sRomanizedType;
            nrv.m_personalNamePieces = personalNamePieces;
            return nrv;
        }
Example #4
0
        // Parser
        public bool ParseRecord( CGedcom gedcom, int level )
        {
            CGedcomLine line;
            CUserReferenceNumber urn;
            CChangeDate cd;
            bool bParsingFinished;
            bool bGotSomething = false;
            do
            {
                bParsingFinished = true;

                if( (line = gedcom.GetLine( level+1, "RIN" )) != null )
                {
                    m_sAutomatedRecordId = line.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                    bGotSomething = true;
                }
                else if( (urn = CUserReferenceNumber.Parse( gedcom, level+1 )) != null )
                {
                    m_alUserReferenceNumbers.Add( urn );
                    bParsingFinished = false;
                    bGotSomething = true;
                }
                else if( (cd = CChangeDate.Parse( gedcom, level+1 )) != null )
                {
                    m_changeDate = cd;
                    bParsingFinished = false;
                    bGotSomething = true;
                }
            }
            while( !bParsingFinished );

            return bGotSomething;
        }
        // Parser
        public static CRepositoryRecord Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;
            bool bParsingFinished;

            // Temporary holders for class members.
            CNoteStructure ns;
            CAddressStructure ads;

            // Without an xref header, we can't continue
            if ((gedcomLine = gedcom.GetLine(nLevel, "REPO")) == null)
            {
                // Not one of us
                return null;
            }

            CRepositoryRecord rr = new CRepositoryRecord( gedcom );

            rr.m_xref = gedcomLine.XrefID;
            gedcom.IncrementLineIndex(1);

            do
            {
                bParsingFinished = true;

                // Let Record have a go at parsing the rest
                if( rr.ParseRecord( gedcom, nLevel ) )
                {
                    bParsingFinished = false;
                    continue;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "NAME")) != null )
                {
                    rr.m_sNameOfRepository = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (ads = CAddressStructure.Parse( gedcom, nLevel+1)) != null )
                {
                    rr.m_addressStructure = ads;
                    bParsingFinished = false;
                }
                else if( (ns = CNoteStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    rr.m_alNoteStructures.Add( ns );
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            return rr;
        }
        // Parser
        public static CSourceRepositoryCitation Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string xrefRepo;
            ArrayList alSourceCallNumbers = new ArrayList();
            CSourceCallNumber sourceCallNumber = null;
            ArrayList alNoteStructures = new ArrayList();
            CNoteStructure noteStructure = null;

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(nLevel, "REPO")) == null)
            {
                // Not one of us
                return null;
            }
            xrefRepo = gedcomLine.LinePointer;
            gedcom.IncrementLineIndex(1);

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                if( (noteStructure = CNoteStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    alNoteStructures.Add( noteStructure );
                    bParsingFinished = false;
                }
                else if( (sourceCallNumber = CSourceCallNumber.Parse( gedcom, nLevel+1 )) != null )
                {
                    alSourceCallNumbers.Add( sourceCallNumber );
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            // Parsing went ok. Construct a new object and return it.
            CSourceRepositoryCitation src = new CSourceRepositoryCitation( gedcom );
            src.m_xrefRepo = xrefRepo;
            src.m_alSourceCallNumbers = alSourceCallNumbers;
            src.m_alNoteStructures = alNoteStructures;
            return src;
        }
        // Parser
        public static CUserReferenceNumber Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string sUserReferenceNumber = "";
            string sUserReferenceType = "";

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(nLevel, "REFN")) == null)
            {
                // Not one of us
                return null;
            }
            sUserReferenceNumber = gedcomLine.LineItem;

            // Parsing is going well enough to say that we definitely have one of these,
            // so we can adjust the gedcom now.
            gedcom.IncrementLineIndex(1);

            // There may be one of these, standard specifies {0:1}
            if( (gedcomLine = gedcom.GetLine(nLevel+1, "TYPE")) != null )
            {
                sUserReferenceType = gedcomLine.LineItem;
                gedcom.IncrementLineIndex(1);
            }
            else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
            {
                LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                gedcom.IncrementLineIndex(1);
            }

            // Parsing went ok. Construct a new object and return it.
            CUserReferenceNumber urn = new CUserReferenceNumber( gedcom );
            urn.m_sUserReferenceNumber = sUserReferenceNumber;
            urn.m_sUserReferenceType = sUserReferenceType;
            return urn;
        }
        // Parser
        public static new CMultimediaLinkXref Parse( CGedcom gedcom, int level )
        {
            CGedcomLine line;

            // Temporary holders for class members. Saves constructing a class early.
            string xref;
            string asid = "";

            // There must be one of these, it defines the object.
            if ((line = gedcom.GetLine(level, "OBJE")) == null)
            {
                // Not one of us
                return null;
            }
            xref = line.LinePointer;

            // Parsing is going well enough to say that we definitely have one of these,
            // so we can adjust the gedcom now.
            gedcom.IncrementLineIndex(1);

            if( (line = gedcom.GetLine(level+1, "_ASID")) != null )
            {
                asid = line.LineItem;
                gedcom.IncrementLineIndex(1);
            }
            else if( ( line = gedcom.GetLine()).Level > level )
            {
                LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, line.ToString() );
                gedcom.IncrementLineIndex(1);
            }

            // Parsing went ok. Construct a new object and return it.
            CMultimediaLinkXref ml = new CMultimediaLinkXref( gedcom );
            ml.m_xref = xref;
            ml.m_sAsid = asid;
            return ml;
        }
        // Parser
        public static CSpouseToFamilyLink Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string xrefFam;
            CNoteStructure noteStructure;
            ArrayList noteStructures = new ArrayList();

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(nLevel, "FAMS")) == null)
            {
                // Not one of us
                return null;
            }
            xrefFam = gedcomLine.LinePointer;

            // Parsing is going well enough to say that we definitely have one of these,
            // so we can adjust the gedcom now.
            gedcom.IncrementLineIndex(1);

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                if( (noteStructure = CNoteStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    noteStructures.Add( noteStructure );
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }

            }
            while( !bParsingFinished );

            // Parsing went ok. Construct a new object and return it.
            CSpouseToFamilyLink sfl = new CSpouseToFamilyLink( gedcom );
            sfl.m_xrefFam = xrefFam;
            sfl.m_alNoteStructures = noteStructures;
            return sfl;
        }
        // Parser
        public static new CNoteStructureXref Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string xref;
            ArrayList sourceCitations = new ArrayList();
            CSourceCitation sourceCitation;

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(nLevel, "NOTE")) == null)
            {
                // Not one of us
                return null;
            }

            xref = gedcomLine.LinePointer;

            // Parsing is going well enough to say that we definitely have one of these,
            // so we can adjust the gedcom now.
            gedcom.IncrementLineIndex(1);

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                if( (sourceCitation = CSourceCitation.Parse( gedcom, nLevel+1 )) != null )
                {
                    sourceCitations.Add( sourceCitation );
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            // Parsing went ok. Construct a new object and return it.
            CNoteStructureXref ns = new CNoteStructureXref( gedcom );
            ns.m_xref = xref;
            ns.m_alSourceCitations = sourceCitations;
            return ns;
        }
        // Parser
        public static CNoteStructure Parse( CGedcom gedcom, int level )
        {
            CGedcomLine line;

            // There must be one of these, it defines the object.
            if ((line = gedcom.GetLine(level, "NOTE")) == null)
            {
                return null; // Not one of us
            }

            // If bit after tag contains a pointer, it must be a reference sType of note
            if( line.LinePointer != null ) //TODO
            {
                return CNoteStructureXref.Parse( gedcom, level );
            }

            // Must be the inline version
            return CNoteStructureInLine.Parse( gedcom, level );
        }
        // Parser
        public static CSourceCitation Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(nLevel, "SOUR")) == null)
            {
                // Not one of us
                return null;
            }

            // If bit after tag contains a pointer, it must be a reference sType of note
            if( gedcomLine.LinePointer != null ) //TODO
            {
                return CSourceCitationXref.Parse( gedcom, nLevel );
            }

            // Must be the inline version
            return CSourceCitationInLine.Parse( gedcom, nLevel );
        }
        // Parser
        public static new CSourceCitationXref Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string xref;
            string sWhereWithinSource = "";
            string sEventTypeCitedFrom = "";
            string sRoleInEvent = "";
            string sEntryRecordingDate = "";
            ArrayList alTextsFromSource = new ArrayList();
            CMultimediaLink multimediaLink;
            ArrayList alMultimediaLinks = new ArrayList();
            CNoteStructure noteStructure;
            ArrayList alNoteStructures = new ArrayList();
            string sCertaintyAssessment = "";

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(nLevel, "SOUR")) == null)
            {
                // Not one of us
                return null;
            }
            xref = gedcomLine.LinePointer;

            // Parsing is going well enough to say that we definitely have one of these,
            // so we can adjust the gedcom now.
            gedcom.IncrementLineIndex(1);

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                // There may be one of these, standard specifies {0:1}
                if( (gedcomLine = gedcom.GetLine(nLevel+1, "PAGE")) != null )
                {
                    sWhereWithinSource = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "EVEN")) != null )
                {
                    sEventTypeCitedFrom = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    if( (gedcomLine = gedcom.GetLine(nLevel+2, "ROLE")) != null )
                    {
                        sRoleInEvent = gedcomLine.LineItem;
                        gedcom.IncrementLineIndex(1);
                    }
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "DATA")) != null )
                {
                    gedcom.IncrementLineIndex(1);

                    bool bParsingFinished2;
                    do
                    {
                        bParsingFinished2 = true;
                        if( (gedcomLine = gedcom.GetLine(nLevel+2, "DATE")) != null )
                        {
                            sEntryRecordingDate = gedcomLine.LineItem;
                            gedcom.IncrementLineIndex(1);
                            bParsingFinished2 = false;
                        }
                        else if( (gedcomLine = gedcom.GetLine(nLevel+2, "TEXT")) != null )
                        {
                            string textFromSource = gedcomLine.LineItem;
                            gedcom.IncrementLineIndex(1);

                            bool bParsingFinished3;
                            do
                            {
                                bParsingFinished3 = true;
                                if( (gedcomLine = gedcom.GetLine(nLevel+3, "CONC")) != null )
                                {
                                    textFromSource += gedcomLine.LineItem;
                                    gedcom.IncrementLineIndex(1);
                                    bParsingFinished3 = false;
                                }
                                else if( (gedcomLine = gedcom.GetLine(nLevel+3, "CONT")) != null )
                                {
                                    textFromSource += "\n" + gedcomLine.LineItem;
                                    gedcom.IncrementLineIndex(1);
                                    bParsingFinished3 = false;
                                }
                            }
                            while( !bParsingFinished3 );

                            alTextsFromSource.Add( textFromSource );
                            bParsingFinished2 = false;
                        }
                    }
                    while( !bParsingFinished2 );
                    bParsingFinished = false;
                }
                else if( (multimediaLink = CMultimediaLink.Parse( gedcom, nLevel+1 )) != null )
                {
                    alMultimediaLinks.Add( multimediaLink );
                    bParsingFinished = false;
                }
                else if( (noteStructure = CNoteStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    alNoteStructures.Add( noteStructure );
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "QUAY")) != null )
                {
                    sCertaintyAssessment = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            // Parsing went ok. Construct a new object and return it.
            CSourceCitationXref sc = new CSourceCitationXref( gedcom );
            sc.m_xref = xref;
            sc.m_sWhereWithinSource = sWhereWithinSource;
            sc.m_sEventTypeCitedFrom = sEventTypeCitedFrom;
            sc.m_sRoleInEvent = sRoleInEvent;
            sc.m_sEntryRecordingDate = sEntryRecordingDate;
            sc.m_alTextsFromSource = alTextsFromSource;
            sc.m_alMultimediaLinks = alMultimediaLinks;
            sc.m_alNoteStructures = alNoteStructures;
            sc.m_sCertaintyAssessment = sCertaintyAssessment;
            return sc;
        }
        // Parser
        public static CMultimediaFileReference Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string sMultimediaFileReference;
            string sMultimediaFormat = "";
            string sSourceMediaType = "";

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(nLevel, "FILE")) == null)
            {
                // Not one of us
                return null;
            }
            sMultimediaFileReference = gedcomLine.LineItem;
            gedcom.IncrementLineIndex(1);

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                // There must be one of these, standard specifies {1:1}
                if( (gedcomLine = gedcom.GetLine(nLevel+1, "FORM")) != null )
                {
                    sMultimediaFormat = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);

                    // There may be one of these, standard specifies {0:1}
                    if( (gedcomLine = gedcom.GetLine(nLevel+2, "TYPE")) != null )
                    {
                        sSourceMediaType = gedcomLine.LineItem;
                        gedcom.IncrementLineIndex(1);
                    }
                    else if( (gedcomLine = gedcom.GetLine(nLevel+2, "MEDI")) != null )
                    {
                        sSourceMediaType = gedcomLine.LineItem;
                        gedcom.IncrementLineIndex(1);
                    }

                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            // Parsing went ok. Construct a new object and return it.
            CMultimediaFileReference mfr = new CMultimediaFileReference( gedcom );
            mfr.m_sMultimediaFileReference = sMultimediaFileReference;
            mfr.m_sMultimediaFormat = sMultimediaFormat;
            return mfr;
        }
        // Parser
        public static CIndividualEventStructure Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string sType;
            string sValue;
            string sSubtype = "";
            CEventDetail ed, eventDetail=null;

            // There must be one of these, it defines the object.
            if(
                (gedcomLine = gedcom.GetLine(nLevel, "_NMR")) == null  // Never married (brother's keeper)
                && (gedcomLine = gedcom.GetLine(nLevel, "_AKA")) == null  // Also known as (brother's keeper)
                && (gedcomLine = gedcom.GetLine(nLevel, "_AKAN")) == null // Also known as (brother's keeper)
                && (gedcomLine = gedcom.GetLine(nLevel, "BIRT")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "CHR")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "DEAT"))  == null
                && (gedcomLine = gedcom.GetLine(nLevel, "BURI")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "CREM")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "ADOP")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "BAPM")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "BAP")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "BARM")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "BASM")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "BLES")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "CHRA")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "CONF")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "FCOM")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "ORDN")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "NATU")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "EMIG")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "IMMI")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "CENS")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "PROB")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "WILL")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "GRAD")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "RETI")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "EVEN")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "CAST")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "DSCR")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "EDUC")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "IDNO")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "NATI")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "NCHI")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "NMR")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "OCCU")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "PROP")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "RELI")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "RESI")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "SSN")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "TITL")) == null
                && (gedcomLine = gedcom.GetLine(nLevel, "FACT")) == null
                 )
            {
                return null;
            }
            sType = gedcomLine.Tag;
            if( sType == "BAP" )
            {
                sType = "BAPM";
            }
            sValue = gedcomLine.LineItem;
            gedcom.IncrementLineIndex(1);

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;
                if( (gedcomLine = gedcom.GetLine(nLevel+1, "TYPE")) != null )
                {
                    sSubtype = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                if( (gedcomLine = gedcom.GetLine(nLevel+1, "CONC")) != null )
                {
                    sValue += gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "CONT")) != null )
                {
                    sValue += "\n" + gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (ed = CEventDetail.Parse( gedcom, nLevel+1 )) != null )
                {
                    eventDetail = ed;
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            // Parsing went ok. Construct a new object and return it.
            CIndividualEventStructure ies = new CIndividualEventStructure( gedcom );
            ies.Type = sType;
            ies.m_sSubtype = sSubtype;
            ies.Value = sValue;
            ies.m_eventDetail = eventDetail;
            return ies;
        }
        // Parser
        public static CFamilyEventStructure Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string sType;
            string sValue;
            CEventDetail ed, eventDetail=null;
            string sSubtype = "";

            // There must be one of these, it defines the object.
            if( (gedcomLine = gedcom.GetLine(nLevel, "ANUL")) == null
             && (gedcomLine = gedcom.GetLine(nLevel, "CENS")) == null
             && (gedcomLine = gedcom.GetLine(nLevel, "DIV"))  == null
             && (gedcomLine = gedcom.GetLine(nLevel, "DIVF")) == null
             && (gedcomLine = gedcom.GetLine(nLevel, "ENGA")) == null
             && (gedcomLine = gedcom.GetLine(nLevel, "MARB")) == null
             && (gedcomLine = gedcom.GetLine(nLevel, "MARC")) == null
             && (gedcomLine = gedcom.GetLine(nLevel, "MARR")) == null
             && (gedcomLine = gedcom.GetLine(nLevel, "MARL")) == null
             && (gedcomLine = gedcom.GetLine(nLevel, "MARS")) == null
             && (gedcomLine = gedcom.GetLine(nLevel, "RESI")) == null
             && (gedcomLine = gedcom.GetLine(nLevel, "EVEN")) == null )
            {
                return null;
            }
            sType = gedcomLine.Tag;
            sValue = gedcomLine.LineItem;
            gedcom.IncrementLineIndex(1);

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;
                if( (gedcomLine = gedcom.GetLine(nLevel+1, "TYPE")) != null )
                {
                    sSubtype = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                if( (gedcomLine = gedcom.GetLine(nLevel+1, "CONC")) != null )
                {
                    sValue += gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "CONT")) != null )
                {
                    sValue += "\n" + gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (ed = CEventDetail.Parse( gedcom, nLevel+1 )) != null )
                {
                    eventDetail = ed;
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            // Parsing went ok. Construct a new object and return it.
            CFamilyEventStructure fes = new CFamilyEventStructure( gedcom );
            fes.Type = sType;
            fes.Value = sValue;
            fes.m_eventDetail = eventDetail;
            fes.m_sSubtype = sSubtype;
            return fes;
        }
        // Parser
        public static CChangeDate Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string sChangeDate = "";
            string sTimeValue = "";
            ArrayList alNoteStructures = new ArrayList();
            CNoteStructure noteStructure = null;

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(nLevel, "CHAN")) == null)
            {
                // Not one of us
                return null;
            }
            gedcom.IncrementLineIndex(1);

            bool bGotMandatoryItem = false;
            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                // There must be one of these, standard specifies {1:1}
                if( (gedcomLine = gedcom.GetLine(nLevel+1, "DATE")) != null  )
                {
                    sChangeDate = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    // There may be one of these, standard specifies {0:1}
                    if( (gedcomLine = gedcom.GetLine(nLevel+2, "TIME")) != null )
                    {
                        sTimeValue = gedcomLine.LineItem;
                        gedcom.IncrementLineIndex(1);
                    }
                    bParsingFinished = false;
                    bGotMandatoryItem = true;
                }
                else if( (noteStructure = CNoteStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    alNoteStructures.Add( noteStructure );
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            if( !bGotMandatoryItem )
            {
                LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Change Date is missing mandatory field." );
                return null;
            }

            // Parsing went ok. Construct a new object and return it.
            CChangeDate cd = new CChangeDate( gedcom );
            cd.m_sChangeDate = sChangeDate;
            cd.m_sTimeValue = sTimeValue;
            cd.m_alNoteStructures = alNoteStructures;
            return cd;
        }
        // Parser
        public static CIndividualRecord Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;
            bool bParsingFinished;

            // Temporary holders for class members.
            CPersonalNameStructure personalNameStructure;
            CIndividualEventStructure individualEventStructure;
            CLdsOrdinance ldsIndividualOrdinance;
            CChildToFamilyLink childToFamilyLink;
            CSpouseToFamilyLink spouseToFamilyLink;
            CAssociationStructure associationStructure;
            CNoteStructure noteStructure;
            CSourceCitation sourceCitation;
            CMultimediaLink multimediaLink;
            ArrayList alAliases = new ArrayList();

            // Without an xref header, we can't continue
            if ((gedcomLine = gedcom.GetLine(nLevel, "INDI")) == null)
            {
                // Not one of us
                return null;
            }

            CIndividualRecord ir = new CIndividualRecord( gedcom );

            ir.m_xref = gedcomLine.XrefID;
            gedcom.IncrementLineIndex(1);

            do
            {
                bParsingFinished = true;

                // Family Historian tag _FLGS
                if( (gedcomLine = gedcom.GetLine(nLevel+1, "_FLGS")) != null )
                {
                    gedcom.IncrementLineIndex(1);
                    if( (gedcomLine = gedcom.GetLine(nLevel+2, "__LIVING")) != null )
                    {
                        ir.m_sStillLiving = gedcomLine.LineItem;
                        gedcom.IncrementLineIndex(1);
                    }
                    bParsingFinished = false;
                }
                // Let Record have a go at parsing the rest
                else if( ir.ParseRecord( gedcom, nLevel ) )
                {
                    bParsingFinished = false;
                    continue;
                }
                else if( (gedcomLine = gedcom.GetLine( nLevel+1, "RESN" )) != null )
                {
                    ir.m_sRestrictionNotice = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (personalNameStructure = CPersonalNameStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    ir.m_alPersonalNameStructures.Add( personalNameStructure );
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "SEX")) != null )
                {
                    ir.m_sSexValue = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (individualEventStructure = CIndividualEventStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    ir.m_alIndividualEventStructures.Add( individualEventStructure );
                    bParsingFinished = false;

                    if( individualEventStructure.Type == "ADOP" )
                    {
                        gedcom.m_alAdoptedIndividuals.Add( ir );
                    }
                }
                else if( (ldsIndividualOrdinance = CLdsOrdinance.Parse( gedcom, nLevel+1 )) != null )
                {
                    ir.m_alLdsIndividualOrdinances.Add( ldsIndividualOrdinance );
                    bParsingFinished = false;
                }
                else if( (childToFamilyLink = CChildToFamilyLink.Parse( gedcom, nLevel+1 )) != null )
                {
                    ir.m_alChildToFamilyLinks.Add( childToFamilyLink );
                    bParsingFinished = false;
                }
                else if( (spouseToFamilyLink = CSpouseToFamilyLink.Parse( gedcom, nLevel+1 )) != null )
                {
                    ir.m_alSpouseToFamilyLinks.Add( spouseToFamilyLink );
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "SUBM")) != null )
                {
                    ir.m_alXrefSubms.Add( gedcomLine.LinePointer );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (associationStructure = CAssociationStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    ir.m_alAssociationStructures.Add( associationStructure );
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "ALIA")) != null )
                {
                    if( gedcomLine.LinePointer != null )
                    {
                        ir.m_alXrefAlias.Add( gedcomLine.LinePointer );
                        gedcom.IncrementLineIndex(1);
                        bParsingFinished = false;
                    }
                    else if( gedcomLine.LineItem != null && gedcomLine.LineItem.Length > 0 )
                    {
                        alAliases.Add( gedcomLine.LineItem );
                        gedcom.IncrementLineIndex(1);
                        bParsingFinished = false;
                    }
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "ANCI")) != null )
                {
                    ir.m_alXrefAncis.Add( gedcomLine.LinePointer );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "DESI")) != null )
                {
                    ir.m_alXrefDesis.Add( gedcomLine.LinePointer );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "RFN")) != null )
                {
                    ir.m_sPermanentRecordFileNumber = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "AFN")) != null )
                {
                    ir.m_sAncestralFileNumber = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (sourceCitation = CSourceCitation.Parse( gedcom, nLevel+1 )) != null )
                {
                    ir.m_alSourceCitations.Add( sourceCitation );
                    bParsingFinished = false;
                }
                else if( (multimediaLink = CMultimediaLink.Parse( gedcom, nLevel+1 )) != null )
                {
                    ir.m_alMultimediaLinks.Add( multimediaLink );
                    bParsingFinished = false;
                }
                else if( (noteStructure = CNoteStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    ir.m_alNoteStructures.Add( noteStructure );
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            // Workaround for GEDCOM that incorrectly contains this: ALIA Fred /Bloggs/ (instead of ALIA @I12@)
            if( alAliases.Count > 0 )
            {
                foreach( string sAlias in alAliases )
                {
                    sAlias.Trim();
                    if( sAlias.Length > 0 )
                    {
                        CPersonalNameStructure pns = new CPersonalNameStructure(gedcom);
                        pns.m_sNamePersonal = sAlias;
                        ir.m_alPersonalNameStructures.Add( pns );
                    }
                }
            }

            return ir;
        }
        // Parser
        public static CLdsOrdinance Parse( CGedcom gedcom, int level )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string sType;
            string sDateLdsOrd = "";
            string sTempleCode = "";
            string sPlaceLivingOrdinance = "";
            string xrefFam = "";
            string sLdsDateStatus = "";
            string sChangeDate = "";
            ArrayList noteStructures = new ArrayList();
            ArrayList sourceCitations = new ArrayList();

            CSourceCitation sourceCitation;
            CNoteStructure noteStructure;

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(level, "BAPL")) == null
              || (gedcomLine = gedcom.GetLine(level, "ENDL")) == null
              || (gedcomLine = gedcom.GetLine(level, "SLGC")) == null
              || (gedcomLine = gedcom.GetLine(level, "CONL")) == null
              || (gedcomLine = gedcom.GetLine(level, "SLGS")) == null)
            {
                // Not one of us
                return null;
            }

            sType = gedcomLine.Tag;
            gedcom.IncrementLineIndex(1);

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                if( (gedcomLine = gedcom.GetLine(level+1, "DATE")) != null )
                {
                    sDateLdsOrd = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(level+1, "TEMP")) != null )
                {
                    sTempleCode = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(level+1, "PLAC")) != null )
                {
                    sPlaceLivingOrdinance = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(level+1, "FAMC")) != null )
                {
                    xrefFam = gedcomLine.LinePointer;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(level+1, "STAT")) != null )
                {
                    sLdsDateStatus = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    if( (gedcomLine = gedcom.GetLine(level+2, "DATE")) != null )
                    {
                        sChangeDate = gedcomLine.LineItem;
                        gedcom.IncrementLineIndex(1);
                    }
                    bParsingFinished = false;
                }
                else if( (sourceCitation = CSourceCitation.Parse( gedcom, level+1 )) != null )
                {
                    sourceCitations.Add( sourceCitation );
                    bParsingFinished = false;
                }
                else if( (noteStructure = CNoteStructure.Parse( gedcom, level+1 )) != null )
                {
                    noteStructures.Add( noteStructure );
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > level )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            // Parsing went ok. Construct a new object and return it.
            CLdsOrdinance lss = new CLdsOrdinance( gedcom );
            lss.Type = sType;
            lss.m_sDateLdsOrd = sDateLdsOrd;
            lss.m_sTempleCode = sTempleCode;
            lss.m_sPlaceLivingOrdinance = sPlaceLivingOrdinance;
            lss.m_xrefFam = xrefFam;
            lss.m_sLdsDateStatus = sLdsDateStatus;
            lss.m_sChangeDate = sChangeDate;
            lss.m_alNoteStructures = noteStructures;
            lss.m_alSourceCitations = sourceCitations;
            return lss;
        }
        // Parser
        public static CAssociationStructure Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string xrefIndi;
            string sRelationIsDescriptor = "";
            CSourceCitation sourceCitation;
            ArrayList alSourceCitations = new ArrayList();
            CNoteStructure noteStructure;
            ArrayList alNoteStructures = new ArrayList();
            string sRecordType = "";

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(nLevel, "ASSO")) == null)
            {
                // Not one of us
                return null;
            }
            xrefIndi = gedcomLine.LinePointer;

            // Parsing is going well enough to say that we definitely have one of these,
            // so we can adjust the gedcom now.
            gedcom.IncrementLineIndex(1);

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                // There may be one of these, standard specifies {0:1}
                if( (gedcomLine = gedcom.GetLine(nLevel+1, "RELA")) != null )
                {
                    sRelationIsDescriptor = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (sourceCitation = CSourceCitation.Parse( gedcom, nLevel+1 )) != null )
                {
                    alSourceCitations.Add( sourceCitation );
                    bParsingFinished = false;
                }
                else if( (noteStructure = CNoteStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    alNoteStructures.Add( noteStructure );
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "TYPE")) != null )
                {
                    sRecordType = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            // Parsing went ok. Construct a new object and return it.
            CAssociationStructure ass = new CAssociationStructure( gedcom );
            ass.m_xrefIndi = xrefIndi;
            ass.m_sRelationIsDescriptor = sRelationIsDescriptor;
            ass.m_alSourceCitations = alSourceCitations;
            ass.m_alNoteStructures = alNoteStructures;
            ass.m_sRecordType = sRecordType;
            return ass;
        }
        // Parser
        public static new CSourceCitationInLine Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string sSourceDescription;
            ArrayList alTextsFromSource = new ArrayList();
            CMultimediaLink multimediaLink;
            ArrayList alMultimediaLinks = new ArrayList();
            CNoteStructure noteStructure;
            ArrayList alNoteStructures = new ArrayList();
            string sCertaintyAssessment = "";

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(nLevel, "SOUR")) == null)
            {
                // Not one of us
                return null;
            }
            sSourceDescription = gedcomLine.LineItem;

            // Parsing is going well enough to say that we definitely have one of these,
            // so we can adjust the gedcom now.
            gedcom.IncrementLineIndex(1);

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                if( (gedcomLine = gedcom.GetLine(nLevel+1, "CONC")) != null )
                {
                    sSourceDescription += gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "CONT")) != null )
                {
                    sSourceDescription += "\n" + gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "TEXT")) != null )
                {
                    string textFromSource = gedcomLine.LineItem;

                    gedcom.IncrementLineIndex(1);
                    bool bParsingFinished3;
                    do
                    {
                        bParsingFinished3 = true;
                        if( (gedcomLine = gedcom.GetLine(nLevel+2, "CONC")) != null )
                        {
                            textFromSource += gedcomLine.LineItem;
                            gedcom.IncrementLineIndex(1);
                            bParsingFinished3 = false;
                        }
                        else if( (gedcomLine = gedcom.GetLine(nLevel+2, "CONT")) != null )
                        {
                            textFromSource += "\n" + gedcomLine.LineItem;
                            gedcom.IncrementLineIndex(1);
                            bParsingFinished3 = false;
                        }
                    }
                    while( !bParsingFinished3 );

                    alTextsFromSource.Add( textFromSource );
                    bParsingFinished = false;
                }
                else if( (multimediaLink = CMultimediaLink.Parse( gedcom, nLevel+1 )) != null )
                {
                    alMultimediaLinks.Add( multimediaLink );
                    bParsingFinished = false;
                }
                else if( (noteStructure = CNoteStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    alNoteStructures.Add( noteStructure );
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "QUAY")) != null )
                {
                    sCertaintyAssessment = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            // Parsing went ok. Construct a new object and return it.
            CSourceCitationInLine sc = new CSourceCitationInLine( gedcom );
            sc.m_sSourceDescription = sSourceDescription;
            sc.m_alTextsFromSource = alTextsFromSource;
            sc.m_alMultimediaLinks = alMultimediaLinks;
            sc.m_alNoteStructures = alNoteStructures;
            sc.m_sCertaintyAssessment = sCertaintyAssessment;
            return sc;
        }
        // Parser
        public static CSubmitterRecord Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;
            bool bParsingFinished;

            // Temporary holders for class members.
            CNoteStructure ns;
            CMultimediaLink ml;
            CAddressStructure ads;

            // Without an xref header, we can't continue
            if ((gedcomLine = gedcom.GetLine(nLevel, "SUBM")) == null)
            {
                // Not one of us
                return null;
            }

            CSubmitterRecord sr = new CSubmitterRecord( gedcom );

            sr.m_xref = gedcomLine.XrefID;
            gedcom.IncrementLineIndex(1);

            do
            {
                bParsingFinished = true;

                // Let Record have a go at parsing the rest
                if( sr.ParseRecord( gedcom, nLevel ) )
                {
                    bParsingFinished = false;
                    continue;
                }
                else if( (gedcomLine = gedcom.GetLine( nLevel+1, "NAME" )) != null )
                {
                    sr.m_sSubmitterName = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine( nLevel+1, "LANG" )) != null )
                {
                    sr.m_alLanguagePreferences.Add( gedcomLine.LineItem );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (ads = CAddressStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    sr.m_addressStructure = ads;
                    bParsingFinished = false;
                }
                else if( (ml = CMultimediaLink.Parse( gedcom, nLevel+1 )) != null )
                {
                    sr.m_alMultimediaLinks.Add( ml );
                    bParsingFinished = false;
                }
                else if( (ns = CNoteStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    sr.m_alNoteStructures.Add( ns );
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            return sr;
        }
        // Parser
        public static CAddressStructure Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;
            string sAddressLine;

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(nLevel, "ADDR")) == null)
            {
                // Not one of us
                return null;
            }
            sAddressLine = gedcomLine.LineItem;
            gedcom.IncrementLineIndex(1);

            // Temporary holders for class members. Saves constructing a class early.
            string sAddressLine1 = "";
            string sAddressLine2 = "";
            string sAddressLine3 = "";
            string sAddressCity = "";
            string sAddressState = "";
            string sAddressPostalCode = "";
            string sAddressCountry = "";
            ArrayList alPhoneNumbers = new ArrayList();
            ArrayList alAddressEmails = new ArrayList();
            ArrayList alAddressFaxes = new ArrayList();
            ArrayList alAddressWebPages = new ArrayList();

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                if( (gedcomLine = gedcom.GetLine(nLevel+1, "CONT")) != null )
                {
                    sAddressLine += "\n" + gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "ADR1")) != null )
                {
                    sAddressLine1 = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "ADR2")) != null )
                {
                    sAddressLine2 = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "ADR3")) != null )
                {
                    sAddressLine3 = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "CITY")) != null )
                {
                    sAddressCity = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "STAE")) != null )
                {
                    sAddressState = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "POST")) != null )
                {
                    sAddressPostalCode = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "CTRY")) != null )
                {
                    sAddressCountry = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel, "PHON")) != null )
                {
                    alPhoneNumbers.Add( gedcomLine.LineItem );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel, "EMAIL")) != null )
                {
                    alAddressEmails.Add( gedcomLine.LineItem );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel, "FAX")) != null )
                {
                    alAddressFaxes.Add( gedcomLine.LineItem );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel, "WWW")) != null )
                {
                    alAddressWebPages.Add( gedcomLine.LineItem );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            // Parsing went ok. Construct a new object and return it.
            CAddressStructure ads = new CAddressStructure( gedcom );
            ads.m_sAddressLine = sAddressLine;
            ads.m_sAddressLine1 = sAddressLine1;
            ads.m_sAddressLine2 = sAddressLine2;
            ads.m_sAddressLine3 = sAddressLine3;
            ads.m_sAddressCity = sAddressCity;
            ads.m_sAddressState = sAddressState;
            ads.m_sAddressPostalCode = sAddressPostalCode;
            ads.m_sAddressCountry = sAddressCountry;
            ads.m_alPhoneNumbers = alPhoneNumbers;
            ads.m_alAddressEmails = alAddressEmails;
            ads.m_alAddressFaxes = alAddressFaxes;
            ads.m_alAddressWebPages = alAddressWebPages;
            return ads;
        }
        // Parser
        public static CMultimediaRecord Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;
            bool bParsingFinished;

            // Without an xref header, we can't continue
            if ((gedcomLine = gedcom.GetLine(nLevel, "OBJE")) == null)
            {
                // Not one of us
                return null;
            }

            CMultimediaRecord mr = new CMultimediaRecord( gedcom );
            mr.m_xref = gedcomLine.XrefID;
            gedcom.IncrementLineIndex(1);
            CMultimediaFileReference mfr = null;

            CNoteStructure ns;
            CSourceCitation sc;
            System.Text.StringBuilder blob = new System.Text.StringBuilder(256);

            do
            {
                bParsingFinished = true;

                // Family Historian style. Underscore, so check for this first
                if( (gedcomLine = gedcom.GetLine(nLevel+1, "_FILE" )) != null )
                {
                    if( mfr == null )
                        mfr = new CMultimediaFileReference( gedcom );

                    mfr.m_sMultimediaFileReference = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }

                // Let Record have a go at parsing the rest
                else if( mr.ParseRecord( gedcom, nLevel ) )
                {
                    bParsingFinished = false;
                    continue;
                }

                // 5.5 style
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "FORM")) != null  )
                {
                    if( mfr == null )
                        mfr = new CMultimediaFileReference( gedcom );

                    mfr.m_sMultimediaFormat = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);

                    // There may be one of these, standard specifies {0:1}
                    if( (gedcomLine = gedcom.GetLine(nLevel+2, "TITL")) != null )
                    {
                        mfr.m_sDescriptiveTitle = gedcomLine.LineItem;
                        gedcom.IncrementLineIndex(1);
                    }
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "BLOB")) != null  )
                {
                    if( mfr == null )
                        mfr = new CMultimediaFileReference( gedcom );

                    mfr.m_bEmbedded = true;

                    gedcom.IncrementLineIndex(1);

                    while( (gedcomLine = gedcom.GetLine(nLevel+2, "CONT")) != null )
                    {
                        blob.Append( gedcomLine.LineItem );
                        gedcom.IncrementLineIndex(1);
                    }
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "OBJE")) != null  )
                {
                    if( mfr == null )
                        mfr = new CMultimediaFileReference( gedcom );

                    mfr.m_xrefObj = gedcomLine.LinePointer;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                // GEDCOM 5.5 style
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "FILE" )) != null )
                {
                    if( mfr == null )
                        mfr = new CMultimediaFileReference( gedcom );

                    mfr.m_sMultimediaFileReference = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                // GEDCOM 5.5.1 style
                else if( (mfr == null) && ((mfr = CMultimediaFileReference.Parse( gedcom, nLevel+1 )) != null) )
                {
                    bParsingFinished = false;
                }
                else if( (ns = CNoteStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    mr.m_alNoteStructures.Add( ns );
                    bParsingFinished = false;
                }
                else if( (sc = CSourceCitation.Parse( gedcom, nLevel+1 )) != null )
                {
                    mr.m_alSourceCitations.Add( sc );
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "TITL")) != null )
                {
                    if( mfr == null )
                        mfr = new CMultimediaFileReference( gedcom );

                    mfr.m_sDescriptiveTitle = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            if (mfr != null)
            {
                mr.m_alMultimediaFileReferences.Add(mfr);
            }

            // Family Historian style
            // If any of the notes contain only _ASID and _AREA, move these values to the m_asidPairs
            ArrayList notesToRemove = new ArrayList();
            foreach( CNoteStructure nss in mr.m_alNoteStructures )
            {
                if( nss is CNoteStructureInLine )
                {
                    if( ((CNoteStructureInLine)nss).m_sSubmitterText == null || ((CNoteStructureInLine)nss).m_sSubmitterText == "" )
                    {
                        if( ((CNoteStructureInLine)nss).m_sAsid != ""
                            || ((CNoteStructureInLine)nss).m_sArea != "" )
                        {
                            string asid = ((CNoteStructureInLine)nss).m_sAsid;
                            CAsidPair asidPair = new CAsidPair( asid, ((CNoteStructureInLine)nss).m_sArea );
                            mr.m_htAsidPairs.Add( asid, asidPair );
                            notesToRemove.Add( nss );
                        }
                    }
                }
            }
            foreach( CNoteStructure nsss in notesToRemove )
            {
                mr.m_alNoteStructures.Remove( nsss );
            }

            if( blob.Length > 0 )
            {
                // Decode blob and overwrite sFilename with decoded blob sFilename
                try
                {
                    mfr.m_sMultimediaFileReference = gedcom.DecodeBlob( blob.ToString() );
                }
                catch( CBlobException )
                {
                    // Error decoding blob
                    mfr.m_sMultimediaFileReference = null;
                }
            }

            return mr;
        }
        // Parser
        public static CFamilyRecord Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;
            bool bParsingFinished;

            // Temporary holders for class members.
            CFamilyEventStructure fes;
            CLdsOrdinance lss;
            CNoteStructure ns;
            CSourceCitation sc;
            CMultimediaLink ml;
            int nChildPositionInFile = 0;

            // Without an xref header, we can't continue
            if ((gedcomLine = gedcom.GetLine(nLevel, "FAM")) == null)
            {
                // Not one of us
                return null;
            }

            CFamilyRecord fr = new CFamilyRecord( gedcom );

            fr.m_xref = gedcomLine.XrefID;
            gedcom.IncrementLineIndex(1);

            do
            {
                bParsingFinished = true;

                // Test for underscore items first so that parser doesn't skip them later
                if( (gedcomLine = gedcom.GetLine(nLevel+1, "_STAT")) != null || (gedcomLine = gedcom.GetLine(nLevel+1, "_MSTAT")) != null ) // Family tree maker (export as "FTW" format)
                {
                    fr.m_sStatus = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                // Let Record have a go at parsing the rest
                else if( fr.ParseRecord( gedcom, nLevel ) )
                {
                    bParsingFinished = false;
                    continue;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "RESN")) != null )
                {
                    fr.m_sRestrictionNotice = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (fes = CFamilyEventStructure.Parse( gedcom, nLevel+1)) != null )
                {
                    fr.m_alFamilyEventStructures.Add( fes );
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "HUSB")) != null )
                {
                    fr.m_xrefHusband = gedcomLine.LinePointer;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "WIFE")) != null )
                {
                    fr.m_xrefWife = gedcomLine.LinePointer;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "CHIL")) != null )
                {
                    fr.m_alXrefsChildren.Add( new CChildXref( nChildPositionInFile++, gedcomLine.LinePointer ) );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "NCHI")) != null )
                {
                    fr.m_sCountOfChildren = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "SUBM")) != null )
                {
                    fr.m_alXrefSubms.Add( gedcomLine.LinePointer );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (lss = CLdsOrdinance.Parse( gedcom, nLevel+1 )) != null )
                {
                    fr.m_alLdsSpouseSealings.Add( lss );
                    bParsingFinished = false;
                }
                else if( (sc = CSourceCitation.Parse( gedcom, nLevel+1 )) != null )
                {
                    fr.m_alSourceCitations.Add( sc );
                    bParsingFinished = false;
                }
                else if( (ml = CMultimediaLink.Parse( gedcom, nLevel+1 )) != null )
                {
                    fr.m_alMultimediaLinks.Add( ml );
                    bParsingFinished = false;
                }
                else if( (ns = CNoteStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    fr.m_alNoteStructures.Add( ns );
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            return fr;
        }
        // Parser
        public static CPersonalNamePieces Parse(CGedcom gedcom, int level)
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string sNamePiecePrefix="";
            string sNamePieceGiven="";
            string sNamePieceNickname="";
            string sNamePieceSurnamePrefix="";
            string sNamePieceSurname="";
            string sNamePieceSuffix="";
            ArrayList alNoteStructures = new ArrayList();
            ArrayList alSourceCitations = new ArrayList();

            CNoteStructure noteStructure;
            CSourceCitation sourceCitation;

            bool bGotSomething = false;
            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                if( (gedcomLine = gedcom.GetLine(level, "NPFX")) != null )
                {
                    sNamePiecePrefix = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                    bGotSomething = true;
                }
                else if( (gedcomLine = gedcom.GetLine(level, "GIVN")) != null )
                {
                    sNamePieceGiven = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                    bGotSomething = true;
                }
                else if( (gedcomLine = gedcom.GetLine(level, "NICK")) != null )
                {
                    sNamePieceNickname = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                    bGotSomething = true;
                }
                else if( (gedcomLine = gedcom.GetLine(level, "SPFX")) != null )
                {
                    sNamePieceSurnamePrefix = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                    bGotSomething = true;
                }
                else if( (gedcomLine = gedcom.GetLine(level, "SURN")) != null )
                {
                    sNamePieceSurname = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                    bGotSomething = true;
                }
                else if( (gedcomLine = gedcom.GetLine(level, "NSFX")) != null )
                {
                    sNamePieceSuffix = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                    bGotSomething = true;
                }
                else if( (noteStructure = CNoteStructure.Parse( gedcom, level )) != null )
                {
                    alNoteStructures.Add( noteStructure );
                    bParsingFinished = false;
                    bGotSomething = true;
                }
                else if( (sourceCitation = CSourceCitation.Parse( gedcom, level )) != null )
                {
                    alSourceCitations.Add( sourceCitation );
                    bParsingFinished = false;
                    bGotSomething = true;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level >= level )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            if( !bGotSomething )
            {
                return null;
            }

            // Parsing went ok. Construct a new object and return it.
            CPersonalNamePieces pnp = new CPersonalNamePieces( gedcom );
            pnp.m_sNamePiecePrefix = sNamePiecePrefix;
            pnp.m_sNamePieceGiven = sNamePieceGiven;
            pnp.m_sNamePieceNickname = sNamePieceNickname;
            pnp.m_sNamePieceSurnamePrefix = sNamePieceSurnamePrefix;
            pnp.m_sNamePieceSurname = sNamePieceSurname;
            pnp.m_sNamePieceSuffix = sNamePieceSuffix;
            pnp.m_alNoteStructures = alNoteStructures;
            pnp.m_alSourceCitations = alSourceCitations;
            return pnp;
        }
        // Parser
        public static CNoteRecord Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;
            bool bParsingFinished;

            // Temporary holders for class members.
            CSourceCitation sc;

            // Without an xref header, we can't continue
            if ((gedcomLine = gedcom.GetLine(nLevel, "NOTE")) == null)
            {
                // Not one of us
                return null;
            }

            CNoteRecord nr = new CNoteRecord( gedcom );

            nr.m_xref = gedcomLine.XrefID;
            nr.m_sSubmitterText += gedcomLine.LineItem;
            gedcom.IncrementLineIndex(1);

            int nLevelHack = nLevel; // This is because "Generations Grand Sierra" outputs NOTE->NOTE, ie. text as a sub-record
            bool bIncludeSpaceWithConc = false; // "Generations Grand Sierra" again misses out spaces on CONC lines.
            do
            {
                bParsingFinished = true;

                // Let Record have a go at parsing the rest
                if( nr.ParseRecord( gedcom, nLevelHack ) )
                {
                    bParsingFinished = false;
                    continue;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevelHack+1, "NOTE")) != null )
                {
                    nr.m_sSubmitterText += gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                    nLevelHack++;
                    bIncludeSpaceWithConc = true;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevelHack+1, "CONC")) != null )
                {
                    if( bIncludeSpaceWithConc )
                        nr.m_sSubmitterText += ' ';
                    nr.m_sSubmitterText += gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevelHack+1, "CONT")) != null )
                {
                    nr.m_sSubmitterText += "\n" + gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (sc = CSourceCitation.Parse( gedcom, nLevelHack+1 )) != null )
                {
                    nr.m_alSourceCitations.Add( sc );
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevelHack )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            return nr;
        }
        // Parser
        public static CPlaceStructure Parse( CGedcom gedcom, int level )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string sPlaceName;
            string sPlaceHierarchy = "";
            string sPlacePhoneticVariation = "";
            string sPlacePhoneticType = "";
            string sPlaceRomanizedVariation = "";
            string sPlaceRomanizedType = "";
            string sPlaceLatitude = "";
            string sPlaceLongitude = "";
            ArrayList noteStructures = new ArrayList();
            ArrayList sourceCitations = new ArrayList();

            CSourceCitation sourceCitation;
            CNoteStructure noteStructure;

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(level, "PLAC")) == null)
            {
                // Not one of us
                return null;
            }
            sPlaceName = gedcomLine.LineItem;
            gedcom.IncrementLineIndex(1);

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                if( (gedcomLine = gedcom.GetLine(level+1, "FORM")) != null )
                {
                    sPlaceHierarchy = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(level+1, "FONE")) != null ) // WRONG!! These are 0:M
                {
                    sPlacePhoneticVariation = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    if( (gedcomLine = gedcom.GetLine(level+2, "TYPE")) != null )
                    {
                        sPlacePhoneticType = gedcomLine.LineItem;
                        gedcom.IncrementLineIndex(1);
                    }
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(level+1, "ROMN")) != null ) // WRONG!! These are 0:M
                {
                    sPlaceRomanizedVariation = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    if( (gedcomLine = gedcom.GetLine(level+2, "TYPE")) != null )
                    {
                        sPlaceRomanizedType = gedcomLine.LineItem;
                        gedcom.IncrementLineIndex(1);
                    }
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(level+1, "MAP")) != null )
                {
                    gedcom.IncrementLineIndex(1);
                    bool bParsingFinished2;
                    do
                    {
                        bParsingFinished2 = true;
                        if( (gedcomLine = gedcom.GetLine(level+2, "LATI")) != null )
                        {
                            sPlaceLatitude = gedcomLine.LineItem;
                            gedcom.IncrementLineIndex(1);
                            bParsingFinished2 = false;
                        }
                        else if( (gedcomLine = gedcom.GetLine(level+2, "LONG")) != null )
                        {
                            sPlaceLongitude = gedcomLine.LineItem;
                            gedcom.IncrementLineIndex(1);
                            bParsingFinished2 = false;
                        }
                    }
                    while( !bParsingFinished2 );

                    bParsingFinished = false;
                }
                else if( (sourceCitation = CSourceCitation.Parse( gedcom, level+1 )) != null )
                {
                    sourceCitations.Add( sourceCitation );
                    bParsingFinished = false;
                }
                else if( (noteStructure = CNoteStructure.Parse( gedcom, level+1 )) != null )
                {
                    noteStructures.Add( noteStructure );
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > level )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            // Parsing went ok. Construct a new object and return it.
            CPlaceStructure ps = new CPlaceStructure( gedcom );
            ps.m_sPlaceName = sPlaceName;
            ps.m_sPlaceHierarchy = sPlaceHierarchy;
            ps.m_sPlacePhoneticVariation = sPlacePhoneticVariation;
            ps.m_sPlacePhoneticType = sPlacePhoneticType;
            ps.m_sPlaceRomanizedVariation = sPlaceRomanizedVariation;
            ps.m_sPlaceRomanizedType = sPlaceRomanizedType;
            ps.m_sPlaceLatitude = sPlaceLatitude;
            ps.m_sPlaceLongitude = sPlaceLongitude;
            ps.m_alNoteStructures = noteStructures;
            ps.m_alSourceCitations = sourceCitations;
            return ps;
        }
        // Parser
        public static CChildToFamilyLink Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string xrefFam;
            string sPedigreeLinkageType = "";
            string sChildLinkageStatus = "";
            CNoteStructure noteStructure;
            ArrayList alNoteStructures = new ArrayList();

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(nLevel, "FAMC")) == null)
            {
                // Not one of us
                return null;
            }
            xrefFam = gedcomLine.LinePointer;

            // Parsing is going well enough to say that we definitely have one of these,
            // so we can adjust the gedcom now.
            gedcom.IncrementLineIndex(1);

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                // There may be one of these, standard specifies {0:1}
                if( (gedcomLine = gedcom.GetLine(nLevel+1, "PEDI")) != null )
                {
                    sPedigreeLinkageType = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "STAT")) != null )
                {
                    sChildLinkageStatus = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (noteStructure = CNoteStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    alNoteStructures.Add( noteStructure );
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            // Parsing went ok. Construct a new object and return it.
            CChildToFamilyLink cfl = new CChildToFamilyLink( gedcom );
            cfl.m_xrefFam = xrefFam;
            cfl.m_sPedigreeLinkageType = sPedigreeLinkageType;
            cfl.m_sChildLinkageStatus = sChildLinkageStatus;
            cfl.m_alNoteStructures = alNoteStructures;
            return cfl;
        }
        // Parser
        public static CSourceRecord Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;
            bool bParsingFinished;

            // Temporary holders for class members.
            CEventRecorded er;
            CSourceRepositoryCitation src;
            CNoteStructure ns;
            CMultimediaLink ml;

            // Without an xref header, we can't continue
            if ((gedcomLine = gedcom.GetLine(nLevel, "SOUR")) == null)
            {
                // Not one of us
                return null;
            }

            CSourceRecord sr = new CSourceRecord( gedcom );

            System.Text.StringBuilder sbTextFromSource = new System.Text.StringBuilder( 64 );

            sr.m_xref = gedcomLine.XrefID;
            gedcom.IncrementLineIndex(1);

            do
            {
                bParsingFinished = true;

                // Let Record have a go at parsing the rest
                if( sr.ParseRecord( gedcom, nLevel ) )
                {
                    bParsingFinished = false;
                    continue;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "DATA")) != null )
                {
                    gedcom.IncrementLineIndex(1);
                    bool bParsingFinished2;
                    do
                    {
                        bParsingFinished2 = true;
                        if( (er = CEventRecorded.Parse( gedcom, nLevel+2)) != null )
                        {
                            sr.m_alEventsRecorded.Add( er );
                            bParsingFinished2 = false;
                        }
                        else if( (gedcomLine = gedcom.GetLine(nLevel+2, "AGNC")) != null )
                        {
                            sr.m_sResponsibleAgency = gedcomLine.LineItem;
                            gedcom.IncrementLineIndex(1);
                            bParsingFinished2 = false;
                        }
                        else if( (ns = CNoteStructure.Parse( gedcom, nLevel+2 )) != null )
                        {
                            sr.m_alDataNoteStructures.Add( ns );
                            bParsingFinished2 = false;
                        }
                    }
                    while( !bParsingFinished2 );
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "AUTH")) != null )
                {
                    sr.m_sSourceOriginator = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bool bParsingFinished2;
                    do
                    {
                        bParsingFinished2 = true;
                        if( (gedcomLine = gedcom.GetLine(nLevel+2, "CONC")) != null )
                        {
                            sr.m_sSourceOriginator += gedcomLine.LineItem;
                            gedcom.IncrementLineIndex(1);
                            bParsingFinished2 = false;
                        }
                        else if( (gedcomLine = gedcom.GetLine(nLevel+2, "CONT")) != null )
                        {
                            sr.m_sSourceOriginator += "\n" + gedcomLine.LineItem;
                            gedcom.IncrementLineIndex(1);
                            bParsingFinished2 = false;
                        }
                    }
                    while( !bParsingFinished2 );
                    bParsingFinished = false;
                }
                else if( ((gedcomLine = gedcom.GetLine(nLevel+1, "TITL")) != null) || ((gedcomLine = gedcom.GetLine(nLevel+1, "NAME")) != null) )
                {
                    sr.m_sSourceDescriptiveTitle = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bool bParsingFinished2;
                    do
                    {
                        bParsingFinished2 = true;
                        if( (gedcomLine = gedcom.GetLine(nLevel+2, "CONC")) != null )
                        {
                            sr.m_sSourceDescriptiveTitle += gedcomLine.LineItem;
                            gedcom.IncrementLineIndex(1);
                            bParsingFinished2 = false;
                        }
                        else if( (gedcomLine = gedcom.GetLine(nLevel+2, "CONT")) != null )
                        {
                            sr.m_sSourceDescriptiveTitle += "\n" + gedcomLine.LineItem;
                            gedcom.IncrementLineIndex(1);
                            bParsingFinished2 = false;
                        }
                    }
                    while( !bParsingFinished2 );
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "ABBR")) != null )
                {
                    sr.m_sSourceFiledByEntry = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "PUBL")) != null )
                {
                    sr.m_sSourcePublicationFacts = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bool bParsingFinished2;
                    do
                    {
                        bParsingFinished2 = true;
                        if( (gedcomLine = gedcom.GetLine(nLevel+2, "CONC")) != null )
                        {
                            sr.m_sSourcePublicationFacts += gedcomLine.LineItem;
                            gedcom.IncrementLineIndex(1);
                            bParsingFinished2 = false;
                        }
                        else if( (gedcomLine = gedcom.GetLine(nLevel+2, "CONT")) != null )
                        {
                            sr.m_sSourcePublicationFacts += "\n" + gedcomLine.LineItem;
                            gedcom.IncrementLineIndex(1);
                            bParsingFinished2 = false;
                        }
                    }
                    while( !bParsingFinished2 );
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "TEXT")) != null )
                {
                    // Actually want strcpy equiv here.
                    sbTextFromSource.Append( gedcomLine.LineItem );
                    gedcom.IncrementLineIndex(1);
                    bool bParsingFinished2;
                    do
                    {
                        bParsingFinished2 = true;
                        if( (gedcomLine = gedcom.GetLine(nLevel+2, "CONC")) != null )
                        {
                            sbTextFromSource.Append( gedcomLine.LineItem );
                            gedcom.IncrementLineIndex(1);
                            bParsingFinished2 = false;
                        }
                        else if( (gedcomLine = gedcom.GetLine(nLevel+2, "CONT")) != null )
                        {
                            sbTextFromSource.Append( "\n" + gedcomLine.LineItem );
                            gedcom.IncrementLineIndex(1);
                            bParsingFinished2 = false;
                        }
                    }
                    while( !bParsingFinished2 );
                    bParsingFinished = false;
                }
                else if( (src = CSourceRepositoryCitation.Parse( gedcom, nLevel+1 )) != null )
                {
                    sr.m_alSourceRepositoryCitations.Add( src );
                    bParsingFinished = false;
                }
                else if( (ml = CMultimediaLink.Parse( gedcom, nLevel+1 )) != null )
                {
                    sr.m_alMultimediaLinks.Add( ml );
                    bParsingFinished = false;
                }
                else if( (ns = CNoteStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    sr.m_alNoteStructures.Add( ns );
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            sr.m_sTextFromSource = sbTextFromSource.ToString();

            return sr;
        }