diff --git a/src/plugins/lib/libgedcom.py b/src/plugins/lib/libgedcom.py index e3ee9bfbc..1b3a819d0 100644 --- a/src/plugins/lib/libgedcom.py +++ b/src/plugins/lib/libgedcom.py @@ -1772,8 +1772,18 @@ class GedcomParser(UpdateCallback): self.nid2id = {} # - # Parse table for SUBM tag + # Parse table for <> below the level 0 SUBM tag # + # n @@ SUBM {1:1} + # +1 NAME {1:1} + # +1 <> {0:1} + # +1 <> {0:M} + # +1 LANG {0:3} + # +1 RFN {0:1} + # +1 RIN {0:1} + # +1 <> {0:1} + + # (N.B. GEDCOM allows multiple SUBMitter records) self.subm_parse_tbl = { # +1 NAME TOKEN_NAME : self.__subm_name, @@ -1789,8 +1799,32 @@ class GedcomParser(UpdateCallback): } # - # Parse table for INDI tag + # Parse table for <> below the level 0 INDI tag # + # n @@ INDI {1:1} + # +1 RESN {0:1} + # +1 <> {0:M} + # +1 SEX {0:1} + # +1 <> {0:M} + # +1 <> {0:M} + # +1 <> {0:M} + # +1 <> {0:M} + # +1 <> {0:M} + # +1 SUBM @@ {0:M} + # +1 <> {0:M} + # +1 ALIA @@ {0:M} + # +1 ANCI @@ {0:M} + # +1 DESI @@ {0:M} + # +1 <> {0:M} + # +1 <> {0:M} + # +1 <> {0:M} + # +1 RFN {0:1} + # +1 AFN {0:1} + # +1 REFN {0:M} + # +2 TYPE {0:1} + # +1 RIN {0:1} + # +1 <> {0:1} + self.indi_parse_tbl = { # +1 RESN {0:1} TOKEN_RESN : self.__person_resn, @@ -1854,9 +1888,6 @@ class GedcomParser(UpdateCallback): TOKEN_TITL : self.__person_titl, } - # - # Parse table for INDI.NAME - # self.name_parse_tbl = { # +1 NPFX {0:1} TOKEN_NPFX : self.__name_npfx, @@ -1883,6 +1914,18 @@ class GedcomParser(UpdateCallback): TOKEN_BIRT : self.__ignore, } + # + # Parse table for <> below the level 0 REPO tag + # + # n @@ REPO {1:1} + # +1 NAME {0:1} + # +1 <> {0:1} + # +1 <> {0:M} + # +1 REFN {0:M} + # +2 TYPE {0:1} + # +1 RIN {0:1} + # +1 <> {0:1} + self.repo_parse_tbl = { TOKEN_NAME : self.__repo_name, TOKEN_ADDR : self.__repo_addr, @@ -2066,8 +2109,23 @@ class GedcomParser(UpdateCallback): } # - # FAM + # Parse table for <> below the level 0 FAM tag # + # n @@ FAM {1:1} + # +1 <> {0:M} + # +1 HUSB @@ {0:1} + # +1 WIFE @@ {0:1} + # +1 CHIL @@ {0:M} + # +1 NCHI {0:1} + # +1 SUBM @@ {0:M} + # +1 <> {0:M} + # +1 <> {0:M} + # +1 <> {0:M} + # +1 <> {0:M} + # +1 REFN {0:M} + # +1 RIN {0:1} + # +1 <> {0:1} + self.family_func = { # +1 <> {0:M} TOKEN_GEVENT : self.__family_std_event, @@ -2110,6 +2168,33 @@ class GedcomParser(UpdateCallback): TOKEN__STAT : self.__family_stat, } + # + # Parse table for <> below the level 0 SOUR tag + # + # n @@ SOUR {1:1} + # +1 DATA {0:1} + # +2 EVEN {0:M} + # +3 DATE {0:1} + # +3 PLAC {0:1} + # +2 AGNC {0:1} + # +2 <> {0:M} + # +1 AUTH {0:1} + # +2 [CONT|CONC] {0:M} + # +1 TITL {0:1} + # +2 [CONT|CONC] {0:M} + # +1 ABBR {0:1} + # +1 PUBL {0:1} + # +2 [CONT|CONC] {0:M} + # +1 TEXT {0:1} + # +2 [CONT|CONC] {0:M} + # +1 <> {0:1} + # +1 <> {0:M} + # +1 <> {0:M} + # +1 REFN {0:M} + # +2 TYPE {0:1} + # +1 RIN {0:1} + # +1 <> {0:1} + self.source_func = { TOKEN_TITL : self.__source_title, TOKEN_TAXT : self.__source_taxt_peri, @@ -2135,6 +2220,21 @@ class GedcomParser(UpdateCallback): TOKEN_IGNORE : self.__ignore, } + # + # Parse table for <> below the level 0 OBJE tag + # + # n @@ OBJE {1:1} + # +1 FORM {1:1} + # +1 TITL {0:1} + # +1 <> {0:M} + # +1 <> {0:M} + # +1 BLOB {1:1} + # +2 CONT {1:M} + # +1 OBJE @@ /* chain to continued object */ {0:1} + # +1 REFN {0:M} + # +2 TYPE {0:1} + # +1 RIN {0:1} + self.obje_func = { TOKEN_FORM : self.__obje_form, TOKEN_TITL : self.__obje_title, @@ -2216,10 +2316,44 @@ class GedcomParser(UpdateCallback): TOKEN_ROLE : self.__citation_even_role, } + # + # Parse table for <
> record below the level 0 HEAD tag + # + # n HEAD {1:1} + # +1 SOUR {1:1} + # +2 VERS {0:1} + # +2 NAME {0:1} + # +2 CORP {0:1} + # +3 <> {0:1} + # +2 DATA {0:1} + # +3 DATE {0:1} + # +3 COPR {0:1} + # +1 DEST {0:1*} + # +1 DATE {0:1} + # +2 TIME {0:1} + # +1 SUBM @@ {1:1} + # +1 SUBN @@ {0:1} + # +1 FILE {0:1} + # +1 COPR {0:1} + # +1 GEDC {1:1} + # +2 VERS {1:1} + # +2 FORM {1:1} + # +1 CHAR {1:1} + # +2 VERS {0:1} + # +1 LANG {0:1} + # +1 PLAC {0:1} + # +2 FORM {1:1} + # +1 NOTE {0:1} + # +2 [CONT|CONC] {0:M} + + # * NOTE: Submissions to the Family History Department for Ancestral + # File submission or for clearing temple ordinances must use a + # DESTination of ANSTFILE or TempleReady. + self.header_sour = { TOKEN_SOUR : self.__header_sour, TOKEN_NAME : self.__ignore, - TOKEN_VERS : self.__header_vers, + TOKEN_VERS : self.__header_vers, # This should be below SOUR TOKEN_FILE : self.__header_file, TOKEN_COPR : self.__header_copr, TOKEN_SUBM : self.__header_subm, @@ -2283,6 +2417,13 @@ class GedcomParser(UpdateCallback): def parse_gedcom_file(self, use_trans=False): """ Parses the opened GEDCOM file. + + LINEAGE_LINKED_GEDCOM: = + 0 <
> {1:1} + 0 <> {0:1} + 0 <> {1:M} + 0 TRLR {1:1} + """ no_magic = self.maxpeople < 1000 with DbTxn(_("GEDCOM import"), self.dbase, not use_trans, @@ -2592,13 +2733,13 @@ class GedcomParser(UpdateCallback): Parses the submitter data n @@ SUBM - +1 NAME - +1 <> - +1 <> - +1 LANG - +1 RFN - +1 RIN - +1 <> + +1 NAME + +1 <> + +1 <> + +1 LANG + +1 RFN + +1 RIN + +1 <> """ researcher = gen.lib.Researcher() state = CurrentState() @@ -2610,6 +2751,25 @@ class GedcomParser(UpdateCallback): def __parse_record(self): """ Parse the top level (0 level) instances. + RECORD: = + [ + n <> {1:1} + | + n <> {1:1} + | + n <> {1:M} + | + n <> {1:1} + | + n <> {1:1} + | + n <> {1:1} + | + n <> {1:1} + ] + + This also deals with the SUBN (submission) record, of which there should + be exactly one. """ while True: line = self.__get_next_line() @@ -2685,34 +2845,35 @@ class GedcomParser(UpdateCallback): # INDI parsing # #---------------------------------------------------------------------- + def __parse_indi(self, line): """ Handling of the GEDCOM INDI tag and all lines subordinate to the current line. n @XREF:INDI@ INDI {1:1} - +1 RESN {0:1} - +1 <> {0:M} - +1 SEX {0:1} - +1 <> {0:M} - +1 <> {0:M} - +1 <> {0:M} - +1 <> {0:M} - +1 <> {0:M} - +1 SUBM @@ {0:M} - +1 <> {0:M} - +1 ALIA @@ {0:M} - +1 ANCI @@ {0:M} - +1 DESI @@ {0:M} - +1 <> {0:M} - +1 <> {0:M} - +1 <> {0:M} - +1 RFN {0:1} - +1 AFN {0:1} - +1 REFN {0:M} - +2 TYPE {0:1} - +1 RIN {0:1} - +1 <> {0:1} + +1 RESN {0:1} + +1 <> {0:M} + +1 SEX {0:1} + +1 <> {0:M} + +1 <> {0:M} + +1 <> {0:M} + +1 <> {0:M} + +1 <> {0:M} + +1 SUBM @@ {0:M} + +1 <> {0:M} + +1 ALIA @@ {0:M} + +1 ANCI @@ {0:M} + +1 DESI @@ {0:M} + +1 <> {0:M} + +1 <> {0:M} + +1 <> {0:M} + +1 RFN {0:1} + +1 AFN {0:1} + +1 REFN {0:M} + +2 TYPE {0:1} + +1 RIN {0:1} + +1 <> {0:1} """ # find the person @@ -3771,13 +3932,13 @@ class GedcomParser(UpdateCallback): #------------------------------------------------------------------- # - # Family parsing + # FAM parsing # #------------------------------------------------------------------- def __parse_fam(self, line): """ - n @@ FAM {1:1} + n @@ FAM {1:1} +1 <> {0:M} +1 HUSB @@ {0:1} +1 WIFE @@ {0:1} @@ -4970,9 +5131,15 @@ class GedcomParser(UpdateCallback): """ self.__parse_note(line, state.citation, state.level+1) + #---------------------------------------------------------------------- + # + # SOUR parsing + # + #---------------------------------------------------------------------- + def __parse_source(self, name, level): """ - n @@ SOUR {1:1} + n @@ SOUR {1:1} +1 DATA {0:1} +2 EVEN {0:M} +3 DATE {0:1} @@ -5171,9 +5338,15 @@ class GedcomParser(UpdateCallback): if state.source.get_title() == "": state.source.set_title(line.data.replace('\n', ' ')) + #---------------------------------------------------------------------- + # + # OBJE parsing + # + #---------------------------------------------------------------------- + def __parse_obje(self, line): """ - n @XREF:OBJE@ OBJE {1:1} + n @XREF:OBJE@ OBJE {1:1} +1 FORM {1:1} p.* +1 TITL {0:1} p.* +1 <> {0:M} p.* @@ -5344,16 +5517,16 @@ class GedcomParser(UpdateCallback): # REPO parsing # #---------------------------------------------------------------------- + def __parse_repo(self, line): """ - REPOSITORY_RECORD:= - n @@ REPO {1:1} - +1 NAME {0:1} p.* - +1 <> {0:1} p.* - +1 <> {0:M} p.* - +1 REFN {0:M} p.* - +1 RIN {0:1} p.* - +1 <> {0:1} p. + n @@ REPO {1:1} + +1 NAME {0:1} p.* + +1 <> {0:1} p.* + +1 <> {0:M} p.* + +1 REFN {0:M} p.* + +1 RIN {0:1} p.* + +1 <> {0:1} p. """ repo = self.__find_or_create_repository(line.token_text) @@ -5589,7 +5762,48 @@ class GedcomParser(UpdateCallback): """ self.__parse_note(line, state.obj, state.level) + #---------------------------------------------------------------------- + # + # HEAD parsing + # + #---------------------------------------------------------------------- + def __parse_header_source(self): + """ + Handling of the lines subordinate to the HEAD GEDCOM tag + + n HEAD {1:1} + +1 SOUR {1:1} + +2 VERS {0:1} + +2 NAME {0:1} + +2 CORP {0:1} + +3 <> {0:1} + +2 DATA {0:1} + +3 DATE {0:1} + +3 COPR {0:1} + +1 DEST {0:1*} + +1 DATE {0:1} + +2 TIME {0:1} + +1 SUBM @@ {1:1} + +1 SUBN @@ {0:1} + +1 FILE {0:1} + +1 COPR {0:1} + +1 GEDC {1:1} + +2 VERS {1:1} + +2 FORM {1:1} + +1 CHAR {1:1} + +2 VERS {0:1} + +1 LANG {0:1} + +1 PLAC {0:1} + +2 FORM {1:1} + +1 NOTE {0:1} + +2 [CONT|CONC] {0:M} + + * NOTE: Submissions to the Family History Department for Ancestral + File submission or for clearing temple ordinances must use a + DESTination of ANSTFILE or TempleReady. + + """ state = CurrentState(level=1) self.__parse_level(state, self.header_sour, self.__undefined) @@ -5732,7 +5946,24 @@ class GedcomParser(UpdateCallback): self.__skip_subordinate_levels(level+1) obj.add_note(new_note.get_handle()) + #---------------------------------------------------------------------- + # + # NOTE parsing + # + #---------------------------------------------------------------------- + def __parse_inline_note(self, line, level): + """ + Handling of lines subordinate to the NOTE GEDCOM tag + + n @@ NOTE {1:1} + +1 [ CONC | CONT] {0:M} + +1 <> {0:M} + +1 REFN {0:M} + +2 TYPE {0:1} + +1 RIN {0:1} + +1 <> {0:1} + """ gid = self.nid_map[line.token_text] handle = self.nid2id.get(gid) if not line.data and handle is None: