// 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 CPersonalNameStructure Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string sNamePersonal;
            string sNameTempSuffix="";
            string sNameType="";
            string sUsedName = "";
            CPersonalNamePieces pnp, personalNamePiece=null;
            ArrayList alNamePhoneticVariations = new ArrayList();
            ArrayList alNameRomanizedVariations = new ArrayList();

            CNamePhoneticVariation namePhoneticVariation;
            CNameRomanizedVariation nameRomanizedVariation;

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

            // Some sw outputs name suffixes in the personal name, e.g. Fred /Bloggs/ Snr
            // Store the suffix, and let caller subsequently move the suffix to a proper class.
            int i = sNamePersonal.LastIndexOf('/') + 1;
            int l = sNamePersonal.Length;
            if (i != l)
            {
                int j = i;
                while ( j<l && (Char.IsWhiteSpace(sNamePersonal[j]) || sNamePersonal[j] == ','))
                {
                    ++j;
                }
                if (j < l)
                {
                    sNameTempSuffix = sNamePersonal.Substring(j);

                    personalNamePiece = new CPersonalNamePieces(gedcom);
                    personalNamePiece.m_sNamePieceSuffix = sNameTempSuffix;
                    sNamePersonal = sNamePersonal.Substring(0, i);
                }
            }
            gedcom.IncrementLineIndex(1);

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                // Test for underscore items first so that parser doesn't skip them later
                if( (gedcomLine = gedcom.GetLine(nLevel+1, "_USED")) != null )
                {
                    sUsedName = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "TYPE")) != null )
                {
                    sNameType = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( (pnp = CPersonalNamePieces.Parse( gedcom, nLevel+1 ) ) != null )
                {
                    personalNamePiece = pnp;
                    bParsingFinished = false;
                }
                else if( (namePhoneticVariation = CNamePhoneticVariation.Parse( gedcom, nLevel+1 ) ) != null )
                {
                    alNamePhoneticVariations.Add( namePhoneticVariation );
                    bParsingFinished = false;
                }
                else if( (nameRomanizedVariation = CNameRomanizedVariation.Parse( gedcom, nLevel+1 ) ) != null )
                {
                    alNameRomanizedVariations.Add( nameRomanizedVariation );
                    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.
            CPersonalNameStructure pns = new CPersonalNameStructure( gedcom );
            pns.m_sNamePersonal = sNamePersonal;
            pns.m_sNameType = sNameType;
            pns.m_sUsedName = sUsedName;
            pns.m_personalNamePieces = personalNamePiece;
            pns.m_alNamePhoneticVariations = alNamePhoneticVariations;
            pns.m_alNameRomanizedVariations = alNameRomanizedVariations;
            return pns;
        }