gedcom

package module
v38.0.0+incompatible Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 23, 2020 License: MIT Imports: 19 Imported by: 20

README

github.com/elliotchance/gedcom

Build Status codecov GitHub release Maintainability


github.com/elliotchance/gedcom is an advanced Go-style library and set of command-line tools for dealing with GEDCOM files.

You can download the latest binaries for macOS, Windows and Linux on the Releases page. This will not require you to install Go or any other dependencies.

What Can It Do?

  • Decode and encode GEDCOM files.

  • Traverse and manipulate GEDCOM files with the provided API.

  • A powerful query language called gedcomq lets you query GEDCOM files with a CLI tool. It can output CSV, JSON and other GEDCOM files.

  • Render GEDCOM files as fully static HTML websites.

  • Compare GEDCOM files from the same or different providers to find differences using the very advanced and configurable tool: gedcomdiff.

  • Merge GEDCOM files using the same advanced Compare algorithm with gedcomq.

Packages

Package Description
GoDoc
gedcom
Package gedcom contains functionality for encoding, decoding, traversing, manipulating and comparing of GEDCOM data.
GoDoc
gedcom/gedcom2html
Gedcom2html renders a GEDCOM file into HTML pages that can be shared and published easily.
GoDoc
gedcom/gedcomdiff
Gedcomdiff is a tool for comparing GEDCOM files and producing a HTML report.
GoDoc
gedcom/q
Package q is the gedcomq parser and engine.
GoDoc
gedcom/gedcomq
Gedcomq is a command line tool and query language for GEDCOM files heavily inspired by jq, in name and syntax.
GoDoc
gedcom/gedcomtune
Gedcomtune is used to calculate the ideal weights and similarities for the main gedcom package.
GoDoc
gedcom/html
Package html is shared HTML rendering components that are shared by the other packages.
GoDoc
gedcom/util
Package util contains shared functions used by several packages.

Documentation

Overview

Copying

All nodes (since they implement the Node interface) also implement the NodeCopier interface which provides the ShallowCopy() function.

A shallow copy returns a new node with all the same properties, but no children.

On the other hand there is a DeepCopy function which returns a new node with all recursive children also copied. This ensures that the new returned node can be manipulated without affecting the original node or any of its children.

Dates

Dates in GEDCOM files can be very complex as they can cater for many scenarios:

1. Incomplete, like "Dec 1943"

2. Anchored, like "Aft. 3 Sep 2003" or "Before 1923"

3. Ranges, like "Bet. 4 Apr 1823 and 8 Apr 1823"

4. Phrases, like "(Foo Bar)"

This package provides a very rich API for dealing with all kind of dates in a meaningful and sensible way. Some notable features include:

1. All dates, even though that specify an specific day have a minimum and maximum value that are their true bounds. This is especially important for larger date ranges like the whole month of "Jun 1945".

2. Upper and lower bounds of dates can be converted to the native Go time.Time object.

3. There is a Years function that provides a convenient way to normalise a date range into a number for easier distance and comparison measurements.

4. Algorithms for calculating the similarity of dates on a configurable parabola.

Decoding a Document

Decoding a GEDCOM stream:

ged := "0 HEAD\n1 CHAR UTF-8"

decoder := gedcom.NewDecoder(strings.NewReader(ged))
document, err := decoder.Decode()
if err != nil {
  panic(err)
}

If you are reading from a file you can use NewDocumentFromGEDCOMFile:

document, err := gedcom.NewDocumentFromGEDCOMFile("family.ged")
if err != nil {
    panic(err)
}

Package gedcom contains functionality for encoding, decoding, traversing, manipulating and comparing of GEDCOM data.

Installation

You can download the latest binaries for macOS, Windows and Linux on the Releases page: https://github.com/elliotchance/gedcom/releases

This will not require you to install Go or any other dependencies.

If you wish to build it from source you must install the dependencies with:

dep ensure

Traversing a Document

On top of the raw document is a powerful API that takes care of the complex traversing of the Document. Here is a simple example:

for _, individual := range document.Individuals() {
  fmt.Println(individual.Name().String())
}

Some of the nodes in a GEDCOM file have been replaced with more function rich types, such as names, dates, families and more.

Encoding a Document

buf := bytes.NewBufferString("")

encoder := NewEncoder(buf, doc)
err := encoder.Encode()
if err != nil {
  panic(err)
}

If you need the GEDCOM data as a string you can simply using fmt.Stringer:

data := document.String()

Filtering and Tree Walking

The Filter function recursively removes or manipulates nodes with a FilterFunction:

newNodes := gedcom.Filter(node, func (node gedcom.Node) (gedcom.Node, bool) {
  if node.Tag().Is(gedcom.TagIndividual) {
    // false means it will not traverse children, since an
    // individual can never be inside of another individual.
    return node, false
  }

  return nil, false
})

// Remove all tags that are not official.
newNodes := gedcom.Filter(node, gedcom.OfficialTagFilter())

Some examples of Filter functions include BlacklistTagFilter, OfficialTagFilter, SimpleNameFilter and WhitelistTagFilter.

Merging

There are several functions available that handle different kinds of merging:

- MergeNodes(left, right Node) Node: returns a new node that merges children from both nodes.

- MergeNodeSlices(left, right Nodes, mergeFn MergeFunction) Nodes: merges two slices based on the mergeFn. This allows more advanced merging when dealing with slices of nodes.

- MergeDocuments(left, right *Document, mergeFn MergeFunction) *Document: creates a new document with their respective nodes merged. You can use IndividualBySurroundingSimilarityMergeFunction with this to merge individuals, rather than just appending them all.

The MergeFunction is a type that can be received in some of the merging functions. The closure determines if two nodes should be merged and what the result would be. Alternatively it can also describe when two nodes should not be merged.

You may certainly create your own MergeFunction, but there are some that are already included:

- IndividualBySurroundingSimilarityMergeFunction creates a MergeFunction that will merge individuals if their surrounding similarity is at least minimumSimilarity.

- EqualityMergeFunction is a MergeFunction that will return a merged node if the node are considered equal (with Equals).

Equality

Node.Equals performs a shallow comparison between two nodes. The implementation is different depending on the types of nodes being compared. You should see the specific documentation for the Node.

Equality is not to be confused with the Is function seen on some of the nodes, such as Date.Is. The Is function is used to compare exact raw values in nodes.

DeepEqual tests if left and right are recursively equal.

Comparing and Diffing

CompareNodes recursively compares two nodes. For example:

0 INDI @P3@           |  0 INDI @P4@
1 NAME John /Smith/   |  1 NAME J. /Smith/
1 BIRT                |  1 BIRT
2 DATE 3 SEP 1943     |  2 DATE Abt. Sep 1943
1 DEAT                |  1 BIRT
2 PLAC England        |  2 DATE 3 SEP 1943
1 BIRT                |  1 DEAT
2 DATE Abt. Oct 1943  |  2 DATE Aft. 2001
                      |  2 PLAC Surry, England

Produces a *NodeDiff than can be rendered with the String method:

LR 0 INDI @P3@
L  1 NAME John /Smith/
LR 1 BIRT
L  2 DATE Abt. Oct 1943
LR 2 DATE 3 SEP 1943
 R 2 DATE Abt. Sep 1943
LR 1 DEAT
L  2 PLAC England
 R 2 DATE Aft. 2001
 R 2 PLAC Surry, England
 R 1 NAME J. /Smith/

Index

Constants

View Source
const (
	DateWordsBetween = "Bet.|bet|between|from"
	DateWordsAnd     = "and|to|-"
	DateWordsAbout   = "Abt.|abt|about|c.|ca|ca.|cca|cca.|circa"
	DateWordsAfter   = "Aft.|aft|after"
	DateWordsBefore  = "Bef.|bef|before"
)

The constants are used in regular expressions and documented on DateNode.

Pipes are used to separate the values to make the options easier to use in regular expressions. The first value of each constant is important as it is the default when converting back to a string.

View Source
const (
	// There is no constraint. The date is at the value specified.
	DateConstraintExact = DateConstraint(iota)

	// The date is approximate. There is no defined error margin (how much the
	// date may be off by) but in mose cases it is save to assume it is
	// proportional to how precise the date is. That is, usually a date that
	// provides a day, month and year will have a smaller error margin than a
	// day that only provides a year.
	DateConstraintAbout

	// The real date is before the specified date value. This often (but not
	// always) follows the same proportional rules as DateConstraintApprox.
	DateConstraintBefore

	// The real date is after the specified date value. This often (but not
	// always) follows the same proportional rules as DateConstraintApprox.
	DateConstraintAfter
)
View Source
const (
	// DateRangeComparisonInvalid is only used in cases of an error.
	DateRangeComparisonInvalid = DateRangeComparison(iota)

	// Equal means that both date ranges are exactly the same in start and end
	// date, or they have an equivalent other value:
	//
	//   Yes:
	//     3 Sep 1943            3 Sep 1943
	//     Sep 1943 - Mar 1944   Sep 1943 - Mar 1944
	//     (world war 2)         (world war 2)
	//
	//   No:
	//     3 Sep 1943            Sep 1943
	//     Sep 1943 - Mar 1944   Sep 1943 - 3 Mar 1944
	//     (world war 2)         (world war 1)
	//
	DateRangeComparisonEqual = iota

	// Inside means that the right operand is both smaller and encapsulated by
	// the greater range in both directions of the left operand. The Start and
	// End derivatives represent if certain boundaries are also equal.
	//
	//   Yes:
	//     3 Sep 1943 - 20 Sep 1943   5 Sep 1943 - 17 Sep 1943
	//     Sep 1943                   3 Sep 1943 - 20 Sep 1943
	//   No:
	//     3 Sep 1943 - 20 Sep 1943   1 Sep 1943 - 5 Sep 1943
	//     Sep 1943                   20 Sep 1943 - 10 Oct 1943
	//     (world war 2)              (world war 2)
	//
	DateRangeComparisonInside      = iota
	DateRangeComparisonInsideStart = iota
	DateRangeComparisonInsideEnd   = iota

	// Outside means that the right operand is larger in both directions. The
	// opposite of Inside. The Start and End derivatives represent if certain
	// boundaries are also equal.
	//
	//   Yes:
	//     3 Sep 1943 - 20 Sep 1943   1 Sep 1943 - 25 Sep 1943
	//     Sep 1943                   14 Jul 1943 - 10 Oct 1943
	//   No:
	//     3 Sep 1943 - 20 Sep 1943   1 Sep 1943 - 5 Sep 1943
	//     Sep 1943                   20 Sep 1943 - 10 Oct 1943
	//     (world war 2)              (world war 2)
	//
	DateRangeComparisonOutside      = iota
	DateRangeComparisonOutsideStart = iota
	DateRangeComparisonOutsideEnd   = iota

	// PartiallyBefore means the right operand range surrounds the start of the
	// left operand.
	//
	//   Yes:
	//     3 Sep 1943 - 20 Sep 1943   1 Sep 1943 - 5 Sep 1943
	//     Sep 1943                   14 Jul 1943 - 10 Sep 1943
	//   No:
	//     3 Sep 1943 - 20 Sep 1943   1 Sep 1943 - 25 Sep 1943
	//     Sep 1943                   20 Sep 1943 - 10 Oct 1943
	//     (world war 2)              (world war 2)
	//
	DateRangeComparisonPartiallyBefore = iota

	// PartiallyAfter means the right operand range surrounds the end of the
	// left operand.
	//
	//   Yes:
	//     3 Sep 1943 - 20 Sep 1943   17 Sep 1943 - 25 Sep 1943
	//     Sep 1943                   10 Sep 1943 - 10 Oct 1943
	//   No:
	//     3 Sep 1943 - 20 Sep 1943   10 Sep 1943 - 15 Sep 1943
	//     Sep 1943                   20 Sep 1943 - 25 Sep 1943
	//     (world war 2)              (world war 2)
	//
	DateRangeComparisonPartiallyAfter = iota

	// Before means the right operand range starts before the left operand's
	// before, but ends at the same value as the start of the left operand.
	//
	//   Yes:
	//     3 Sep 1943 - 20 Sep 1943   1 Sep 1943 - 3 Sep 1943
	//     Sep 1943                   14 Jul 1943 - 1 Sep 1943
	//   No:
	//     3 Sep 1943 - 20 Sep 1943   1 Sep 1943 - 4 Sep 1943
	//     Sep 1943                   14 Jul 1943 - 10 Sep 1943
	//     (world war 2)              (world war 2)
	//
	DateRangeComparisonBefore = iota

	// After means the right operand starts at the end of the left operand and
	// ends somewhere thereafter.
	//
	//   Yes:
	//     3 Sep 1943 - 20 Sep 1943   20 Sep 1943 - 25 Sep 1943
	//     Sep 1943                   30 Sep 1943 - 10 Oct 1943
	//   No:
	//     3 Sep 1943 - 20 Sep 1943   19 Sep 1943 - 25 Sep 1943
	//     Sep 1943                   20 Sep 1943 - 25 Sep 1943
	//     (world war 2)              (world war 2)
	//
	DateRangeComparisonAfter = iota

	// EntirelyBefore means that the full range of the right operand is before
	// any of the range of the left operand.
	//
	//   Yes:
	//     3 Sep 1943 - 20 Sep 1943   1 Sep 1943 - 2 Sep 1943
	//     Sep 1943                   3 Jul 1943 - 10 Jul 1943
	//   No:
	//     3 Sep 1943 - 20 Sep 1943   19 Sep 1943 - 25 Sep 1943
	//     Sep 1943                   20 Sep 1943 - 25 Sep 1943
	//     (world war 2)              (world war 2)
	//
	DateRangeComparisonEntirelyBefore = iota

	// EntirelyAfter means that the full range of the right operand is after
	// any of the range of the left operand.
	//
	//   Yes:
	//     3 Sep 1943 - 20 Sep 1943   25 Sep 1943 - 30 Sep 1943
	//     Sep 1943                   3 Oct 1943 - 10 Oct 1943
	//   No:
	//     3 Sep 1943 - 20 Sep 1943   19 Sep 1943 - 25 Sep 1943
	//     Sep 1943                   20 Sep 1943 - 25 Sep 1943
	//     (world war 2)              (world war 2)
	//
	DateRangeComparisonEntirelyAfter = iota
)

Each of the constants below represent how the ranges cross over. See DateRangeComparison for a visual explanation.

View Source
const (
	// DefaultMaxLivingAge is used when creating a new document. See
	// Document.MaxLivingAge for a full description.
	DefaultMaxLivingAge = 100.0

	// DefaultMaxMarriageAge is the default age in which a spouse will begin to
	// produce MarriedTooOldWarnings.
	DefaultMaxMarriageAge = 100.0

	// DefaultMinMarriageAge is the default minimum age that a spouse is allowed
	// to be married.
	DefaultMinMarriageAge = 16.0
)
View Source
const (
	DefaultJaroWinklerBoostThreshold = 0.0
	DefaultJaroWinklerPrefixSize     = 8
)

Theses constants are used with JaroWinkler. They have been calculated using the gedcomtune command.

View Source
const (
	NameTypeNormal      = NameType("")
	NameTypeMarriedName = NameType("married")
	NameTypeAlsoKnownAs = NameType("aka")
	NameTypeMaidenName  = NameType("maiden")
	NameTypeNickname    = NameType("nick")
)
View Source
const (
	// Phonetic method for sounding Korean glifs.
	PhoneticVariationTypeHangul = "hangul"

	// Hiragana and/or Katakana characters were used in sounding the Kanji
	// character used by japanese.
	PhoneticVariationTypeKana = "kana"
)

Indicates the method used in transforming the text to the phonetic variation.

These constants can be used for PhoneticVariationNode.Type.Value. The value is not limited to these constants. Any user defined value is also valid.

View Source
const (
	RomanizedVariationTypePinyin    = "pinyin"
	RomanizedVariationTypeRomaji    = "romaji"
	RomanizedVariationTypeWadegiles = "wadegiles"
)

Indicates the method used in transforming the text to a romanized variation.

These constants can be used for RomanizedVariationNode.Type.Value. The value is not limited to these constants. Any user defined value is also valid.

View Source
const (
	SexMale    = "M"
	SexFemale  = "F"
	SexUnknown = "U"
)
View Source
const DefaultMaxYearsForSimilarity = float64(3)

DefaultMaxYearsForSimilarity is a sensible default for the Similarity function (maxYears) when comparing dates. The importance of maxYears is explained in DateNode.Similarity.

Unless you need to ensure similarity values are retained correctly through versions you should use this constant instead of specifying a raw value to DateNode.Similarity. This value may change in time if a more accurate default is found.

The gedcomtune tool was used to find an ideal value for this. Generally speaking 2 - 3 years yielded much the same result. Any further in either direction led to a drop in accuracy for matching individuals.

View Source
const DefaultMinimumSimilarity = 0.733

DefaultMinimumSimilarity is a sensible value to provide to the minimumSimilarity parameter of IndividualNodes.Similarity.

It is quite possible that this value will change in the future if a more accurate figure is found or the algorithm is generally tuned with different weightings.

The value was chosen by running comparison experiments with gedcomtune, a tool to try and find ideal values for constants like this.

View Source
const NoIndent = -1

NoIndent can be used with GEDCOMLine and GEDCOMString so that the output does not contain the indent-levels.

View Source
const Year = time.Duration(float64(time.Hour) * 24 * 365.25)

Year is an approximation for the duration of a year.

This should not be used in calculations that require more than month-level precision.

A year is approximated at 365.25 to take into account leap years.

Variables

View Source
var (
	// A short name of a title, description, or name.
	TagAbbreviation = newTag("ABBR", "Abbreviation", tagOptionNone, tagSortIndividualInfo)

	// The contemporary place, usually required for postal purposes, of an
	// individual, a submitter of information, a repository, a business, a
	// school, or a company.
	TagAddress = newTag("ADDR", "Address", tagOptionNone, tagSortIndividualInfo)

	// The first line of an address.
	TagAddress1 = newTag("ADR1", "Address Line 1", tagOptionNone, tagSortIndividualInfo)

	// The second line of an address.
	TagAddress2 = newTag("ADR2", "Address Line 2", tagOptionNone, tagSortIndividualInfo)

	// Pertaining to creation of a child-parent relationship that does not exist
	// biologically.
	TagAdoption = newTag("ADOP", "Adoption", tagOptionEvent, tagSortIndividualEvents)

	// Ancestral File Number, a unique permanent record file number of an
	// individual record stored in Ancestral File.
	TagAncestralFileNumber = newTag("AFN", "Ancestral File Number", tagOptionNone, tagSortIndividualInfo)

	// The age of the individual at the time an event occurred, or the age
	// listed in the document.
	TagAge = newTag("AGE", "Age", tagOptionNone, tagSortIndividualInfo)

	// The institution or individual having authority and/or responsibility to
	// manage or govern.
	TagAgency = newTag("AGNC", "Agency", tagOptionNone, tagSortIndividualInfo)

	// An indicator to link different record descriptions of a person who may be
	// the same person.
	TagAlias = newTag("ALIA", "Alias", tagOptionNone, tagSortIndividualInfo)

	// Pertaining to forbearers of an individual.
	TagAncestors = newTag("ANCE", "Ancestors", tagOptionNone, tagSortIndividualInfo)

	// Indicates an interest in additional research for ancestors of this
	// individual. (See also DESI)
	TagAncestorsInterest = newTag("ANCI", "Ancestors Interest", tagOptionNone, tagSortIndividualInfo)

	// Declaring a marriage void from the beginning (never existed).
	TagAnnulment = newTag("ANUL", "Annulment", tagOptionEvent, tagSortIndividualEvents)

	// An indicator to link friends, neighbors, relatives, or associates of an
	// individual.
	TagAssociates = newTag("ASSO", "Associates", tagOptionNone, tagSortIndividualInfo)

	// The name of the individual who created or compiled information.
	TagAuthor = newTag("AUTH", "Author", tagOptionNone, tagSortIndividualInfo)

	// The event of baptism performed at age eight or later by priesthood
	// authority of the LDS Church. (See also BAPM)
	TagLDSBaptism = newTag("BAPL", "LDS Baptism", tagOptionEvent, tagSortIndividualEvents)

	// See BaptismNode.
	TagBaptism = newTag("BAPM", "Baptism", tagOptionEvent, tagSortIndividualEvents)

	// The ceremonial event held when a Jewish boy reaches age 13.
	TagBarMitzvah = newTag("BARM", "Bar Mitzvah", tagOptionEvent, tagSortIndividualEvents)

	// The ceremonial event held when a Jewish girl reaches age 13, also known
	// as "Bat Mitzvah."
	TagBasMitzvah = newTag("BASM", "Bas Mitzvah", tagOptionEvent, tagSortIndividualEvents)

	// See BirthNode.
	TagBirth = newTag("BIRT", "Birth", tagOptionEvent, tagSortIndividualBirth)

	// A religious event of bestowing divine care or intercession. Sometimes
	// given in connection with a naming ceremony.
	TagBlessing = newTag("BLES", "Blessing", tagOptionEvent, tagSortIndividualEvents)

	// A grouping of data used as input to a multimedia system that processes
	// binary data to represent images, sound, and video. Deleted in Gedcom
	// 5.5.1
	TagBinaryObject = newTag("BLOB", "Binary Object", tagOptionNone, tagSortIndividualInfo)

	// See BurialNode.
	TagBurial = newTag("BURI", "Burial", tagOptionEvent, tagSortIndividualBurial)

	// The number used by a repository to identify the specific items in its
	// collections.
	TagCallNumber = newTag("CALN", "Call Number", tagOptionNone, tagSortIndividualInfo)

	// The name of an individual's rank or status in society, based on racial or
	// religious differences, or differences in wealth, inherited rank,
	// profession, occupation, etc.
	TagCaste = newTag("CAST", "Caste", tagOptionNone, tagSortIndividualInfo)

	// A description of the cause of the associated event or fact, such as the
	// cause of death.
	TagCause = newTag("CAUS", "Cause", tagOptionNone, tagSortIndividualInfo)

	// The event of the periodic count of the population for a designated
	// locality, such as a national or state Census.
	TagCensus = newTag("CENS", "Census", tagOptionEvent, tagSortIndividualEvents)

	// Indicates a change, correction, or modification. Typically used in
	// connection with a DATE to specify when a change in information occurred.
	TagChange = newTag("CHAN", "Change", tagOptionNone, tagSortIndividualInfo)

	// An indicator of the character set used in writing this automated
	// information.
	TagCharacterSet = newTag("CHAR", "Character Set", tagOptionNone, tagSortIndividualInfo)

	// See ChildNode.
	TagChild = newTag("CHIL", "Child", tagOptionNone, tagSortIndividualInfo)

	// The religious event (not LDS) of baptizing and/or naming a child.
	TagChristening = newTag("CHR", "Christening", tagOptionEvent, tagSortIndividualEvents)

	// The religious event (not LDS) of baptizing and/or naming an adult person.
	TagAdultChristening = newTag("CHRA", "Adult Christening", tagOptionEvent, tagSortIndividualEvents)

	// A lower level jurisdictional unit. Normally an incorporated municipal
	// unit.
	TagCity = newTag("CITY", "City", tagOptionNone, tagSortIndividualInfo)

	// An indicator that additional data belongs to the superior value. The
	// information from the CONC value is to be connected to the value of the
	// superior preceding line without a space and without a carriage return
	// and/or new line character. Values that are split for a CONC tag must
	// always be split at a non-space. If the value is split on a space the
	// space will be lost when concatenation takes place. This is because of the
	// treatment that spaces get as a GEDCOM delimiter, many GEDCOM values are
	// trimmed of trailing spaces and some systems look for the first non-space
	// starting after the tag to determine the beginning of the value.
	TagConcatenation = newTag("CONC", "Concatenation", tagOptionNone, tagSortIndividualInfo)

	// The religious event (not LDS) of conferring the gift of the Holy Ghost
	// and, among protestants, full church membership.
	TagConfirmation = newTag("CONF", "Confirmation", tagOptionEvent, tagSortIndividualEvents)

	// The religious event by which a person receives membership in the LDS
	// Church.
	TagLDSConfirmation = newTag("CONL", "LDS Confirmation", tagOptionEvent, tagSortIndividualEvents)

	//  An indicator that additional data belongs to the superior value. The
	// information from the CONT value is to be connected to the value of the
	// superior preceding line with a carriage return and/or new line character.
	// Leading spaces could be important to the formatting of the resultant
	// text. When importing values from CONT lines the reader should assume only
	// one delimiter character following the CONT tag. Assume that the rest of
	// the leading spaces are to be a part of the value.
	TagContinued = newTag("CONT", "Continued", tagOptionNone, tagSortIndividualInfo)

	// A statement that accompanies data to protect it from unlawful duplication
	// and distribution.
	TagCopyright = newTag("COPR", "Copyright", tagOptionNone, tagSortIndividualInfo)

	// A name of an institution, agency, corporation, or company.
	TagCorporate = newTag("CORP", "Corporate", tagOptionNone, tagSortIndividualInfo)

	// Disposal of the remains of a person's body by fire.
	TagCremation = newTag("CREM", "Cremation", tagOptionEvent, tagSortIndividualEvents)

	// The name or code of the country.
	TagCountry = newTag("CTRY", "Country", tagOptionNone, tagSortIndividualInfo)

	// Pertaining to stored automated information.
	TagData = newTag("DATA", "Data", tagOptionNone, tagSortIndividualInfo)

	// The time of an event in a calendar format.
	TagDate = newTag("DATE", "Date", tagOptionNone, tagSortIndividualInfo)

	// See DeathNode.
	TagDeath = newTag("DEAT", "Death", tagOptionEvent, tagSortIndividualDeath)

	// Pertaining to offspring of an individual.
	TagDescendants = newTag("DESC", "Descendants", tagOptionNone, tagSortIndividualInfo)

	// Indicates an interest in research to identify additional descendants of
	// this individual. (See also ANCI)
	TagDescendantsInterest = newTag("DESI", "Descendants Interest", tagOptionNone, tagSortIndividualInfo)

	// A system receiving data.
	TagDestination = newTag("DEST", "Destination", tagOptionNone, tagSortIndividualInfo)

	// An event of dissolving a marriage through civil action.
	TagDivorce = newTag("DIV", "Divorce", tagOptionEvent, tagSortIndividualEvents)

	// An event of filing for a divorce by a spouse.
	TagDivorceFiled = newTag("DIVF", "Divorce Filed", tagOptionEvent, tagSortIndividualEvents)

	// The physical characteristics of a person, place, or thing.
	TagPhysicalDescription = newTag("DSCR", "Physical Description", tagOptionNone, tagSortIndividualInfo)

	// Indicator of a level of education attained.
	TagEducation = newTag("EDUC", "Education", tagOptionNone, tagSortIndividualInfo)

	// An electronic address that can be used for contact such as an email
	// address. New in Gedcom 5.5.1.
	TagEmail = newTag("EMAIL", "Email", tagOptionNone, tagSortIndividualInfo)

	// An event of leaving one's homeland with the intent of residing elsewhere.
	TagEmigration = newTag("EMIG", "Emigration", tagOptionEvent, tagSortIndividualEvents)

	// A religious event where an endowment ordinance for an individual was
	// performed by priesthood authority in an LDS temple.
	TagEndowment = newTag("ENDL", "Endowment", tagOptionEvent, tagSortIndividualEvents)

	// An event of recording or announcing an agreement between two people to
	// become married.
	TagEngagement = newTag("ENGA", "Engagement", tagOptionEvent, tagSortIndividualEvents)

	// See EventNode.
	TagEvent = newTag("EVEN", "Event", tagOptionEvent, tagSortIndividualEvents)

	// Pertaining to a noteworthy attribute or fact concerning an individual, a
	// group, or an organization. A structure is usually qualified or classified
	// by a subordinate use of the TYPE tag. New in Gedcom 5.5.1.
	TagFact = newTag("FACT", "Fact", tagOptionNone, tagSortIndividualInfo)

	// Identifies a legal, common law, or other customary relationship of man
	// and woman and their children, if any, or a family created by virtue of
	// the birth of a child to its biological father and mother.
	TagFamily = newTag("FAM", "Family", tagOptionNone, tagSortIndividualInfo)

	// Identifies the family in which an individual appears as a child.
	TagFamilyChild = newTag("FAMC", "Family Child", tagOptionNone, tagSortIndividualInfo)

	// Pertaining to, or the name of, a family file. Names stored in a file that
	// are assigned to a family for doing temple ordinance work.
	TagFamilyFile = newTag("FAMF", "Family File", tagOptionNone, tagSortIndividualInfo)

	// Identifies the family in which an individual appears as a spouse.
	TagFamilySpouse = newTag("FAMS", "Family Spouse", tagOptionNone, tagSortIndividualInfo)

	// A FAX telephone number appropriate for sending data facsimiles. New in
	// Gedcom 5.5.1.
	TagFax = newTag("FAX", "Fax", tagOptionNone, tagSortIndividualInfo)

	// A religious rite, the first act of sharing in the Lord's supper as part
	// of church worship.
	TagFirstCommunion = newTag("FCOM", "First Communion", tagOptionEvent, tagSortIndividualEvents)

	// An information storage place that is ordered and arranged for
	// preservation and reference.
	TagFile = newTag("FILE", "File", tagOptionNone, tagSortIndividualInfo)

	// See PhoneticNode.
	TagPhonetic = newTag("FONE", "Phonetic", tagOptionNone, tagSortIndividualInfo)

	// See FormatNode.
	TagFormat = newTag("FORM", "Format", tagOptionNone, tagSortIndividualInfo)

	// Information about the use of GEDCOM in a transmission.
	TagGedcomInformation = newTag("GEDC", "GEDCOM Information", tagOptionNone, tagSortIndividualInfo)

	// A given or earned name used for official identification of a person. It
	// is also commonly known as the "first name".
	//
	// The NameNode provides a GivenName() function.
	TagGivenName = newTag("GIVN", "Given Name", tagOptionNone, tagSortIndividualInfo)

	// An event of awarding educational diplomas or degrees to individuals.
	TagGraduation = newTag("GRAD", "Graduation", tagOptionEvent, tagSortIndividualEvents)

	// Identifies information pertaining to an entire GEDCOM transmission.
	TagHeader = newTag("HEAD", "Header", tagOptionNone, tagSortIndividualInfo)

	// See HusbandNode.
	TagHusband = newTag("HUSB", "Husband", tagOptionNone, tagSortIndividualInfo)

	// A number assigned to identify a person within some significant external
	// system.
	TagIdentityNumber = newTag("IDNO", "Identity Number", tagOptionNone, tagSortIndividualInfo)

	// An event of entering into a new locality with the intent of residing
	// there.
	TagImmigration = newTag("IMMI", "Immigration", tagOptionEvent, tagSortIndividualEvents)

	// A person.
	TagIndividual = newTag("INDI", "Individual", tagOptionNone, tagSortIndividualInfo)

	// Defines label for given fact.
	TagLabel = newTag("LABL", "Label", tagOptionNone, tagSortIndividualInfo)

	// The name of the language used in a communication or transmission of
	// information.
	TagLanguage = newTag("LANG", "Language", tagOptionNone, tagSortIndividualInfo)

	// See LatitudeNode.
	TagLatitude = newTag("LATI", "Latitude", tagOptionNone, tagSortIndividualInfo)

	// A role of an individual acting as a person receiving a bequest or legal
	// devise.
	TagLegatee = newTag("LEGA", "Legatee", tagOptionNone, tagSortIndividualInfo)

	// See LongitudeNode.
	TagLongitude = newTag("LONG", "Longitude", tagOptionNone, tagSortIndividualInfo)

	// See MapNode.
	TagMap = newTag("MAP", "Map", tagOptionNone, tagSortIndividualInfo)

	// An event of an official public notice given that two people intend to
	// marry.
	TagMarriageBann = newTag("MARB", "Marriage Bann", tagOptionEvent, tagSortIndividualEvents)

	// An event of recording a formal agreement of marriage, including the
	// prenuptial agreement in which marriage partners reach agreement about the
	// property rights of one or both, securing property to their children.
	TagMarriageContract = newTag("MARC", "Marriage Contract", tagOptionEvent, tagSortIndividualEvents)

	// An event of obtaining a legal license to marry.
	TagMarriageLicence = newTag("MARL", "Marriage Licence", tagOptionEvent, tagSortIndividualEvents)

	// A legal, common-law, or customary event of creating a family unit of a
	// man and a woman as husband and wife.
	TagMarriage = newTag("MARR", "Marriage", tagOptionEvent, tagSortIndividualEvents)

	// An event of creating an agreement between two people contemplating
	// marriage, at which time they agree to release or modify property rights
	// that would otherwise arise from the marriage.
	TagMarriageSettlement = newTag("MARS", "Marriage Settlement", tagOptionEvent, tagSortIndividualEvents)

	// Identifies information about the media or having to do with the medium in
	// which information is stored.
	TagMedia = newTag("MEDI", "Media", tagOptionNone, tagSortIndividualInfo)

	// A word or combination of words used to help identify an individual,
	// title, or other item. More than one NAME line should be used for people
	// who were known by multiple names.
	//
	// NAME tags will be interpreted with the NameNode type.
	TagName = newTag("NAME", "Name", tagOptionNone, tagSortIndividualName)

	// The national heritage of an individual.
	TagNationality = newTag("NATI", "Nationality", tagOptionNone, tagSortIndividualInfo)

	// The event of obtaining citizenship.
	TagNaturalization = newTag("NATU", "Naturalization", tagOptionEvent, tagSortIndividualEvents)

	// The number of children that this person is known to be the parent of (all
	// marriages) when subordinate to an individual, or that belong to this
	// family when subordinate to a FAM_RECORD.
	TagChildrenCount = newTag("NCHI", "Children Count", tagOptionNone, tagSortIndividualInfo)

	// See NicknameNode.
	TagNickname = newTag("NICK", "Nickname", tagOptionNone, tagSortIndividualInfo)

	// The number of times this person has participated in a family as a spouse
	// or parent.
	TagMarriageCount = newTag("NMR", "Marriage Count", tagOptionNone, tagSortIndividualInfo)

	// See NoteNode.
	TagNote = newTag("NOTE", "Note", tagOptionNone, tagSortIndividualInfo)

	// Text which appears on a name line before the given and surname parts of a
	// name. i.e. ( Lt. Cmndr. ) Joseph /Allen/ jr. In this example Lt. Cmndr.
	// is considered as the name prefix portion.
	//
	// The NameNode provides a Prefix() function.
	TagNamePrefix = newTag("NPFX", "Name Prefix", tagOptionNone, tagSortIndividualInfo)

	// Text which appears on a name line after or behind the given and surname
	// parts of a name. i.e. Lt. Cmndr. Joseph /Allen/ ( jr. ) In this example
	// jr. is considered as the name suffix portion.
	//
	// The NameNode provides a Suffix() function.
	TagNameSuffix = newTag("NSFX", "Name Suffix", tagOptionNone, tagSortIndividualInfo)

	// Pertaining to a grouping of attributes used in describing something.
	// Usually referring to the data required to represent a multimedia object,
	// such an audio recording, a photograph of a person, or an image of a
	// document.
	TagObject = newTag("OBJE", "Object", tagOptionNone, tagSortIndividualInfo)

	// The type of work or profession of an individual.
	TagOccupation = newTag("OCCU", "Occupation", tagOptionNone, tagSortIndividualInfo)

	// Pertaining to a religious ordinance in general.
	TagOrdinance = newTag("ORDI", "Ordinance", tagOptionNone, tagSortIndividualInfo)

	// A religious event of receiving authority to act in religious matters.
	TagOrdination = newTag("ORDN", "Ordination", tagOptionEvent, tagSortIndividualEvents)

	// A number or description to identify where information can be found in a
	// referenced work.
	TagPage = newTag("PAGE", "Page", tagOptionNone, tagSortIndividualInfo)

	// Information pertaining to an individual to parent lineage chart.
	TagPedigree = newTag("PEDI", "Pedigree", tagOptionNone, tagSortIndividualInfo)

	// A unique number assigned to access a specific telephone.
	TagPhone = newTag("PHON", "Phone", tagOptionNone, tagSortIndividualInfo)

	// See PlaceNode.
	TagPlace = newTag("PLAC", "Place", tagOptionNone, tagSortIndividualInfo)

	// A code used by a postal service to identify an area to facilitate mail
	// handling.
	TagPostalCode = newTag("POST", "Postal Code", tagOptionNone, tagSortIndividualInfo)

	// An event of judicial determination of the validity of a will. May
	// indicate several related court activities over several dates.
	TagProbate = newTag("PROB", "Probate", tagOptionEvent, tagSortIndividualEvents)

	// Pertaining to possessions such as real estate or other property of
	// interest.
	TagProperty = newTag("PROP", "Property", tagOptionNone, tagSortIndividualInfo)

	// Refers to when and/or were a work was published or created.
	TagPublication = newTag("PUBL", "Publication", tagOptionNone, tagSortIndividualInfo)

	// An assessment of the certainty of the evidence to support the conclusion
	// drawn from evidence.
	TagQualityOfData = newTag("QUAY", "Quality Of Data", tagOptionNone, tagSortIndividualInfo)

	// A description or number used to identify an item for filing, storage, or
	// other reference purposes.
	TagReference = newTag("REFN", "Reference", tagOptionNone, tagSortIndividualInfo)

	// A relationship value between the indicated contexts.
	TagRelationship = newTag("RELA", "Relationship", tagOptionNone, tagSortIndividualInfo)

	// A religious denomination to which a person is affiliated or for which a
	// record applies.
	TagReligion = newTag("RELI", "Religion", tagOptionNone, tagSortIndividualInfo)

	// An institution or person that has the specified item as part of their
	// collection(s).
	TagRepository = newTag("REPO", "Repository", tagOptionNone, tagSortIndividualInfo)

	// See ResidenceNode.
	TagResidence = newTag("RESI", "Residence", tagOptionEvent, tagSortIndividualEvents)

	// A processing indicator signifying access to information has been denied
	// or otherwise restricted.
	TagRestriction = newTag("RESN", "Restriction", tagOptionNone, tagSortIndividualInfo)

	// An event of exiting an occupational relationship with an employer after a
	// qualifying time period.
	TagRetirement = newTag("RETI", "Retirement", tagOptionEvent, tagSortIndividualEvents)

	// A permanent number assigned to a record that uniquely identifies it
	// within a known file.
	TagRecordFileNumber = newTag("RFN", "Record File Number", tagOptionNone, tagSortIndividualInfo)

	// A number assigned to a record by an originating automated system that can
	// be used by a receiving system to report results pertaining to that
	// record.
	TagRecordIDNumber = newTag("RIN", "Record ID Number", tagOptionNone, tagSortIndividualInfo)

	// A name given to a role played by an individual in connection with an
	// event.
	TagRole = newTag("ROLE", "Role", tagOptionNone, tagSortIndividualInfo)

	// A romanized variation of a superior text string. New in Gedcom 5.5.1.
	TagRomanized = newTag("ROMN", "Romanized", tagOptionNone, tagSortIndividualInfo)

	// See SexNode.
	TagSex = newTag("SEX", "Sex", tagOptionNone, tagSortIndividualInfo)

	// A religious event pertaining to the sealing of a child to his or her
	// parents in an LDS temple ceremony.
	TagSealingChild = newTag("SLGC", "Sealing Child", tagOptionEvent, tagSortIndividualEvents)

	// A religious event pertaining to the sealing of a husband and wife in an
	// LDS temple ceremony.
	TagSealingSpouse = newTag("SLGS", "Sealing Spouse", tagOptionEvent, tagSortIndividualEvents)

	// The initial or original material from which information was obtained.
	TagSource = newTag("SOUR", "Source", tagOptionNone, tagSortIndividualInfo)

	// A name piece used as a non-indexing pre-part of a surname.
	TagSurnamePrefix = newTag("SPFX", "Surname Prefix", tagOptionNone, tagSortIndividualInfo)

	// A number assigned by the United States Social Security Administration.
	// Used for tax identification purposes.
	TagSocialSecurityNumber = newTag("SSN", "Social Security Number", tagOptionNone, tagSortIndividualInfo)

	// A geographical division of a larger jurisdictional area, such as a State
	// within the United States of America.
	TagState = newTag("STAE", "State", tagOptionNone, tagSortIndividualInfo)

	// An assessment of the state or condition of something.
	TagStatus = newTag("STAT", "Status", tagOptionNone, tagSortIndividualInfo)

	// An individual or organization who contributes genealogical data to a file
	// or transfers it to someone else.
	TagSubmitter = newTag("SUBM", "Submitter", tagOptionNone, tagSortIndividualInfo)

	// Pertains to a collection of data issued for processing.
	TagSubmission = newTag("SUBN", "Submission", tagOptionNone, tagSortIndividualInfo)

	// A family name passed on or used by members of a family.
	//
	// The NameNode provides a Surname() function.
	TagSurname = newTag("SURN", "Surname", tagOptionNone, tagSortIndividualInfo)

	// The name or code that represents the name a temple of the LDS Church.
	TagTemple = newTag("TEMP", "Temple", tagOptionNone, tagSortIndividualInfo)

	// The exact wording found in an original source document.
	TagText = newTag("TEXT", "Text", tagOptionNone, tagSortIndividualInfo)

	// A time value in a 24-hour clock format, including hours, minutes, and
	// optional seconds, separated by a colon (:). Fractions of seconds are
	// shown in decimal notation.
	TagTime = newTag("TIME", "Time", tagOptionNone, tagSortIndividualInfo)

	// A description of a specific writing or other work, such as the title of a
	// book when used in a source context, or a formal designation used by an
	// individual in connection with positions of royalty or other social
	// status, such as Grand Duke.
	//
	// The NameNode provides a Title() function.
	TagTitle = newTag("TITL", "Title", tagOptionNone, tagSortIndividualInfo)

	// At level 0, specifies the end of a GEDCOM transmission.
	TagTrailer = newTag("TRLR", "Trailer", tagOptionNone, tagSortIndividualInfo)

	// See TypeNode.
	TagType = newTag("TYPE", "Type", tagOptionNone, tagSortIndividualInfo)

	// Indicates which version of a product, item, or publication is being used
	// or referenced.
	TagVersion = newTag("VERS", "Version", tagOptionNone, tagSortIndividualInfo)

	// See WifeNode.
	TagWife = newTag("WIFE", "Wife", tagOptionNone, tagSortIndividualInfo)

	// World Wide Web home page. New in Gedcom 5.5.1.
	TagWWW = newTag("WWW", "WWW", tagOptionNone, tagSortIndividualInfo)

	// A legal document treated as an event, by which a person disposes of his
	// or her estate, to take effect after death. The event date is the date the
	// will was signed while the person was alive. (See also PROBate)
	TagWill = newTag("WILL", "Will", tagOptionEvent, tagSortIndividualEvents)
)

http://wiki-en.genealogy.net/GEDCOM-Tags

Definition of all standard GEDCOM-Tags

List of all field names (tags), used in GEDCOM Specification 5.5, or (with a special comment) or added/deleted in GEDCOM 5.5.1. These field names are used in a hierarchical structure to describe e.g. single persons in connection with their families. Field names may have different meaning and content depending on their position in the data structure.

GEDCOM-standard permits user defined field names (one of the major causes of "misunderstandings" of different GEDCOM-compliant programs!). They have to begin with an underscore _ .

View Source
var (

	// See FamilySearchIDNode
	UnofficialTagFamilySearchID1 = newTag("_FID", "FamilySearch ID", tagOptionNone, tagSortIndividualUnofficial)
	UnofficialTagFamilySearchID2 = newTag("_FSFTID", "FamilySearch ID", tagOptionNone, tagSortIndividualUnofficial)

	// Unofficial. Latitude degrees. This has been seen exported from
	// MacFamilyFree.
	UnofficialTagLatitudeDegrees = newTag("_LAD", "Latitude Degrees", tagOptionNone, tagSortIndividualUnofficial)

	// Unofficial. Latitude minutes. This has been seen exported from
	// MacFamilyFree.
	UnofficialTagLatitudeMinutes = newTag("_LAM", "Latitude Minutes", tagOptionNone, tagSortIndividualUnofficial)

	// Unofficial. Latitude seconds. This has been seen exported from
	// MacFamilyFree.
	UnofficialTagLatitudeSeconds = newTag("_LAS", "Latitude Seconds", tagOptionNone, tagSortIndividualUnofficial)

	// Unofficial. Longitude degrees. This has been seen exported from
	// MacFamilyFree.
	UnofficialTagLongitudeDegress = newTag("_LOD", "Longitude Degress", tagOptionNone, tagSortIndividualUnofficial)

	// Unofficial. Longitude minutes. This has been seen exported from
	// MacFamilyFree.
	UnofficialTagLongitudeMinutes = newTag("_LOM", "Longitude Minutes", tagOptionNone, tagSortIndividualUnofficial)

	// Unofficial. Longitude north? This has been seen exported from
	// MacFamilyFree.
	UnofficialTagLongitudeNorth = newTag("_LON", "Longitude North", tagOptionNone, tagSortIndividualUnofficial)

	// Unofficial. Longitude seconds. This has been seen exported from
	// MacFamilyFree.
	UnofficialTagLongitudeSeconds = newTag("_LOS", "Longitude Seconds", tagOptionNone, tagSortIndividualUnofficial)

	// Unofficial. Used to group the _LA* and _LO* tags for latitude and
	// longitude. This has been seen exported from MacFamilyFree.
	UnofficialTagCoordinates = newTag("_COR", "Coordinates", tagOptionNone, tagSortIndividualUnofficial)

	// Unofficial. The created date and/or time. This has been seen exported
	// from Ancestry.com.
	UnofficialTagCreated = newTag("_CRE", "Created", tagOptionNone, tagSortIndividualUnofficial)

	// See UniqueIDNode.
	UnofficialTagUniqueID = newTag("_UID", "Unique ID", tagOptionNone, tagSortIndividualUnofficial)
)
View Source
var Countries = []string{}/* 205 elements not displayed */

Countries is a list of all the known current and historical countries.

These are used to help identify countries in place names. See PlaceNode.Country().

https://www.searchify.ca/list-of-countries/

Functions

func Atoi

func Atoi(s string) int

Atoi is a fault tolerant way to convert a string to an integer.

Atoi ultimately uses strconv.Atoi to do the conversion, but will clean the string by removing any surrounding spaces or processing "0" characters.

It is usually the logic behind any function in this package that expects to receive an integer from a string value.

If the string cannot be parsed to an integer then 0 is returned.

func CleanSpace

func CleanSpace(s string) string

CleanSpace works similar to strings.TrimSpace except that it also replaces consecutive spaces anywhere in the string with a single space.

"  Foo   bar BAZ" -> "Foo bar BAZ"

CleanSpace is used in many places throughout the library to clean values that are known to not place any significance on their spaces. Such as individual and place names.

func DateAndPlace

func DateAndPlace(nodes ...Node) (date *DateNode, place *PlaceNode)

DateAndPlace is a convenience method for fetching a date and place from a list of nodes.

If multiple dates and places exist it will choose the first respective one.

func DeepEqual

func DeepEqual(left, right Node) bool

DeepEqual tests if left and right are recursively equal.

If either left or right is nil (including both) then false is always returned.

If left does not equal right (see Node.Equals) or both sides do not contain exactly the same amount of child nodes then false is returned.

The GEDCOM standard allows nodes to appear in any order. So the children are compared in this way as well. For example the following root nodes are equal:

0 INDI @P1@        |  0 INDI @P1@
1 BIRT             |  1 BIRT
2 DATE 3 SEP 1943  |  2 PLAC England
2 PLAC England     |  2 DATE 3 SEP 1943

DeepEqual heavily depends on the logic of the Equals method for each kind of node. Equals may or may not take into consideration child nodes to determine if the parent itself is equal. You should see the specific documentation for Equals on each node type.

If Equals is not implemented it will fall back to SimpleNode.Equals.

If an equal node appears multiple times on either side it will also have to appear the same number of times on the opposite side for the DeepEqual to be true.

func DeepEqualNodes

func DeepEqualNodes(left, right Nodes) bool

DeepEqualNodes allows two slices of nodes to be compared.

The slices must have the same length (including zero) or the result will always be false. If both slices contain zero elements then the result is always true.

Every node in the left must DeepEqual a node on the right. The same node cannot be used twice in a comparison. The slices are allowed to have duplicate nodes (by reference or value) as long as the other side has an equal amount of duplicates.

See DeepEqual for semantics on how nodes are compared.

func DeleteNodesWithTag

func DeleteNodesWithTag(node Node, tag Tag)

func GEDCOMLine

func GEDCOMLine(value GEDCOMLiner, indent int) string

GEDCOMLine is the safer alternative to GEDCOMLiner.GEDCOMLine. It will handle nils gracefully, returning an empty string.

func GEDCOMString

func GEDCOMString(value GEDCOMStringer, indent int) string

GEDCOMString is the safer alternative to GEDCOMStringer.GEDCOMString. It will handle nils gracefully, returning an empty string.

func HasNestedNode

func HasNestedNode(node Node, lookingFor Node) bool

HasNestedNode checks if node contains lookingFor at any depth. If node and lookingFor are the same false is returned. If either node or lookingFor is nil then false is always returned.

Nodes are matched by reference, not value so nodes that represent exactly the same value will not be considered equal.

func IsNil

func IsNil(node interface{}) bool

IsNil is the safe and reliable way to check if a node is nil. You should not compare Node values with an untyped nil as it will lead to unexpected results.

As a side node IsNil cannot be part of the Node interface because more specific node types (such as DateNode) use SimpleNode as an instance variable and that would cause a nil pointer panic.

func JaroWinkler

func JaroWinkler(a, b string, boostThreshold float64, prefixSize int) float64

JaroWinkler distance. JaroWinkler returns a number between 0 and 1 where 1 means perfectly equal and 0 means completely different. It is commonly used on Record Linkage stuff, thus it tries to be accurate for real names and common typos. You should consider it on data such as person names and street names.

JaroWinkler is sensitive to punctuation and capitalization of strings. If you are comparing names or places you may want to use StringSimilarity instead. StringSimilarity removes punctuation, extra whitespace and normalises capitalization before performing the comparison which almost always delivers more desirable results.

JaroWinkler is a more accurate version of the Jaro algorithm. It works by boosting the score of exact matches at the beginning of the strings. By doing this, Winkler says that typos are less common to happen at the beginning. For this to happen, it introduces two more parameters: the boostThreshold and the prefixSize. These are commonly set to 0.7 and 4, respectively. However, you should use DefaultJaroWinklerBoostThreshold and DefaultJaroWinklerPrefixSize as they have been calcuated by the gedcomtune command.

The code and comment above has been copied from:

https://github.com/xrash/smetrics/blob/master/jaro-winkler.go

A big thanks to Felipe (@xrash) for the explanation and code. It you read this, I copied the code to avoid the need to have a dependency manager for this project.

func Pointer

func Pointer(node Node) string

Pointer is a safe way to fetch the Pointer() from a node. If the node is nil then an empty string will be returned.

func String

func String(node Node) string

String is a safe way to fetch the String() from a node. If the node is nil then an empty string will be returned.

func StringSimilarity

func StringSimilarity(a, b string, boostThreshold float64, prefixSize int) float64

StringSimilarity is a less sensitive version of a JaroWinkler string comparison. It is the ideal choice to compare strings that represent individual names, places, etc as it does not take into account capitalization, punctuation and extra spaces.

func Value

func Value(node Node) string

Value is a safe way to fetch the Value() from a node. If the node is nil then an empty string will be returned.

func Years

func Years(v interface{}) float64

Years is a safe way to fetch the Years() value from a value. If the value is nil or does not implement Yearer then 0.0 will be returned. Otherwise the value of Years() is returned.

Types

type Age

type Age struct {
	// Age is the duration of time from the point where the birth was
	// determined.
	//
	// The age may be an estimation, see IsEstimate. The age might also be
	// greater than the maximum living age of the individual, see IsAfterDeath.
	Age time.Duration

	// IsEstimate will be true when there was no birth event or the birth event
	// is a range (like "Between 1943 to 1947").
	IsEstimate bool

	// IsKnown will be true if the age can be determined (either as exact or an
	// estimation). The age cannot be determined if no estimated birth date is
	// found or an event does not contain a usable date.
	//
	// When IsKnown is false you should not use the value of Age.
	IsKnown bool

	// See the AgeConstraint constants for a full explanation.
	Constraint AgeConstraint
}

Age represents an age of an individual at a point in time.

An Age is often paired with another Age to allow a range of time. For example an event could be an absolute like a christening, or it could represent a range such as the start and end age during a residence that spans multiple years.

You should avoid initializing the struct directly, and instead use the most appropriate constructor.

func NewAge

func NewAge(age time.Duration, isEstimate bool, constraint AgeConstraint) Age

NewAge will initialise a new known exact or estimate age age with the provided attributes.

func NewAgeWithYears

func NewAgeWithYears(years float64, isEstimate bool, constraint AgeConstraint) Age

NewAgeWithYears creates an age by using the number of years.

This is not precise as a year is averaged out at 365.25 days (see Year constant) but is useful when only whole years matter.

func NewUnknownAge

func NewUnknownAge() Age

NewUnknownAge returns a value that represents an age that is not known.

func (Age) IsAfter

func (age Age) IsAfter(age2 Age) bool

IsAfter is true if the right age is after (greater than) the left age. If both ages are equal this will return false.

func (Age) String

func (age Age) String() string

String returns an age in one of the following forms:

unknown     -- if IsKnown is false
20y         -- living age is very close to the whole year
20y 5m      -- living age with 5 months
~ 25y       -- if IsEstimated is true
~ 22y 11m   -- same as above

String will not consider the age constraint.

A special case is 0. When the age duration is zero (or less than half of one month) the estimate marker ("~") will not be shown because this would not make sense.

func (Age) Years

func (age Age) Years() float64

Years returns the approximate amount of years.

The value is approximate because a year is both a variable amount of time and has to be combined with a point in time to be practical.

Years can be used when 1 month resolution is enough. However, it's not recommended to use this for calculations. Instead use the Age value.

type AgeConstraint

type AgeConstraint int

AgeConstraint is used to describe if the individual was living during the calculated age.

See the AgeConstraint constants for more information.

const (
	// The constraint is not known. This is the case if none of the other
	// options can be determined to be true.
	AgeConstraintUnknown AgeConstraint = iota

	// The age represents a time before the known birth. This would be
	// represented as a negative age.
	AgeConstraintBeforeBirth

	// The age represents the number of years since the known birth of the
	// individual. Even if the age is an approximation or a wide range it can
	// still be considered as fully or partly within their lifetime.
	AgeConstraintLiving

	// The age is after the known death of the individual. Like the "before
	// birth" constraint it can be sometimes useful to know the age of the
	// individual if they were still living or subtract their death age to see
	// how many years after their death the event may have occurred.
	//
	// You can use IndividualNode.Age() to fetch the maximum living age of a now
	// deceased individual.
	AgeConstraintAfterDeath
)

func (AgeConstraint) String

func (ac AgeConstraint) String() string

Strings returns a human-readable form of the constant, like "After Death".

type BaptismNode

type BaptismNode struct {
	*SimpleNode
}

BaptismNode is event of baptism (not LDS), performed in infancy or later.

See also BAPL and CHR.

func NewBaptismNode

func NewBaptismNode(value string, children ...Node) *BaptismNode

NewBaptismNode creates a new BAPM node.

func (*BaptismNode) Dates

func (node *BaptismNode) Dates() DateNodes

Dates returns zero or more dates associated with the Baptism.

When more than one date is returned you should not assume that the order has any significance for the importance of the dates.

If the node is nil the result will also be nil.

func (*BaptismNode) Equals

func (node *BaptismNode) Equals(node2 Node) bool

Equal will always return true if both nodes are not nil.

If either node is nil (including both) or if the right side is not a BaptismNode then false is always returned. Otherwise Equals will always return true.

The reason Equals always returns true is because Equals is a shallow test and an individual can only ever have one baptism event. Therefore it is safe to assume that baptism events themselves are equal, even if the children they contain are not.

This logic is especially important for CompareNodes.

type BirthNode

type BirthNode struct {
	*SimpleNode
}

BirthNode is the event of entering into life.

func NewBirthNode

func NewBirthNode(value string, children ...Node) *BirthNode

NewBirthNode creates a new BIRT node.

func (*BirthNode) Dates

func (node *BirthNode) Dates() DateNodes

Dates returns zero or more dates associated with the Birth.

When more than one date is returned you should not assume that the order has any significance for the importance of the dates.

If the node is nil the result will also be nil.

func (*BirthNode) Equals

func (node *BirthNode) Equals(node2 Node) bool

Equal will always return true if both nodes are not nil.

If either node is nil (including both) or if the right side is not a BirthNode then false is always returned. Otherwise Equals will always return true.

The reason Equals always returns true is because Equals is a shallow test and an individual can only ever have one birth event. Therefore it is safe to assume that birth events themselves are equal, even if the children they contain are not.

This logic is especially important for CompareNodes.

type BurialNode

type BurialNode struct {
	*SimpleNode
}

BurialNode is the event of the proper disposing of the mortal remains of a deceased person.

func NewBurialNode

func NewBurialNode(value string, children ...Node) *BurialNode

NewBurialNode creates a new BURI node.

func (*BurialNode) Dates

func (node *BurialNode) Dates() DateNodes

Dates returns zero or more dates associated with the burial.

When more than one date is returned you should not assume that the order has any significance for the importance of the dates.

If the node is nil the result will also be nil.

func (*BurialNode) Equals

func (node *BurialNode) Equals(node2 Node) bool

Equal will always return true if both nodes are not nil.

If either node is nil (including both) or if the right side is not a BurialNode then false is always returned. Otherwise Equals will always return true.

The reason Equals always returns true is because Equals is a shallow test and an individual can only ever have one burial event. Therefore it is safe to assume that burial events themselves are equal, even if the children they contain are not.

This logic is especially important for CompareNodes.

type ChildBornBeforeParentWarning

type ChildBornBeforeParentWarning struct {
	SimpleWarning
	Parent *IndividualNode
	Child  *ChildNode
}

func NewChildBornBeforeParentWarning

func NewChildBornBeforeParentWarning(parent *IndividualNode, child *ChildNode) *ChildBornBeforeParentWarning

func (*ChildBornBeforeParentWarning) Name

func (*ChildBornBeforeParentWarning) String

type ChildNode

type ChildNode struct {
	*SimpleNode
	// contains filtered or unexported fields
}

ChildNode is the natural, adopted, or sealed (LDS) child of a father and a mother.

func (*ChildNode) Family

func (node *ChildNode) Family() *FamilyNode

func (*ChildNode) Father

func (node *ChildNode) Father() *HusbandNode

func (*ChildNode) Individual

func (node *ChildNode) Individual() *IndividualNode

func (*ChildNode) Mother

func (node *ChildNode) Mother() *WifeNode

func (*ChildNode) String

func (node *ChildNode) String() string

type ChildNodes

type ChildNodes []*ChildNode

func (ChildNodes) ByPointer

func (nodes ChildNodes) ByPointer(pointer string) *ChildNode

func (ChildNodes) IndividualByPointer

func (nodes ChildNodes) IndividualByPointer(pointer string) *IndividualNode

func (ChildNodes) Individuals

func (nodes ChildNodes) Individuals() (individuals IndividualNodes)

func (ChildNodes) Similarity

func (nodes ChildNodes) Similarity(other ChildNodes, options SimilarityOptions) float64

type Date

type Date struct {
	// Day of the month. When the day is not provided (like "Feb 1990") this
	// will be 0.
	Day int

	// Month of the year. When the month is not provided (like "1999") this will
	// be 0.
	Month time.Month

	// Year number. Go only allows for date ranges of the year between 0 and
	// 9999. If this year is outside of that date you will not be able to use
	// the Time() function and you will probably run into all sort of other
	// trouble.
	Year int

	// IsEndOfRange signifies is this date is the start or end of the range
	// (provided by DateNode). This is important for Time() to create a
	// timestamp that is constrained to the lower or upper bound.
	//
	// For example if the date was "Feb 1822" the Time() function would return:
	//
	//    1 Feb 1822 00:00:00.000000000 // IsEndOfRange = false
	//   29 Feb 1822 23:59:59.999999999 // IsEndOfRange = true
	//
	IsEndOfRange bool

	// Constraint indicates if the date is the exact value specified,
	// approximate or bound to before or after its value. See the documentation
	// for DateConstraint for a full explanation.
	//
	// This value does not affect the value calculated by Time() but it may be
	// important in some cases to know the date may not be the value returned by
	// Time().
	Constraint DateConstraint

	// If the date cannot be parsed this will contain the error.
	ParseError error
}

Date is a single point in time.

A date in GEDCOM always represents a range contained between the StartDate() and EndDate(), even when it represents a single day, like "23 Jan 1921".

Before diving into the full specs below you should be aware of the known limitations:

1. Only the Gregorian calendar with the English language (for month names) is currently supported.

2. You should only expect dates that are valid and within the range of Go's supported libraries will work correctly. That is years between 0 and 9999. It is possible that dates outside of this range may be interpreted correctly but you should not rely on that remaining the same.

3. There are surly more keyword combinations used in GEDCOM files than are documented below. Interpreting these dates is not necessarily guaranteed to work, not work or retain the same behaviour between releases. If you believe there are other known cases please open an issue or pull request.

Now into the specification. There are two basic forms of a DATE value:

between date and date
date

The second case is actually equivalent to the first case the the same "date" substituted twice.

The "between" keyword can be any of (non case sensitive):

between
bet
bet.
from

The "and" keyword can be one of (non case sensitive):

-
and
to

A "date" has three basic forms:

prefix? day month year
prefix? month year
prefix? year

The "prefix" is optional and can be used to indicate if the date is approximate or not with one of the following keywords:

abt
abt.
about
c.
circa

Or, the "prefix" can be used to signify unbounded dates with one of the following keywords:

after
aft
aft.
before
bef
bef.

The "day" must be an integer between 1 and 31 and can have a single proceeding zero, like "03". The day should be valid against the month used. The behavior is unexpected when using invalid dates like "31 Feb 1999", but you will likely not receive a date at all if it's invalid.

The "month" must be one of the following strings (case in-sensitive):

apr
april
aug
august
dec
december
feb
february
jan
january
jul
july
jun
june
mar
march
may
nov
november
oct
october
sep
september

The "year" must be an integer with a value between 0 and 9999 (as to conform to the restrictions of the Go time package). It may be possible to parse dates outside of this range but they behaviour is not defined.

The "year" may be 1 to 4 digits but it always treated as the absolute year. The year 89 is treated as the year 89, not 1989, for example.

Values represented by a Date instance must be compatible with Go's time package. This only allows for date ranges of the year between 0 and 9999. So Date would not allow for BC/BCE dates.

You should be careful about directly creating dates from the defined instance variables because they may contain 0 to signify that a date component was not provided. Unless you have a very special case you should use Time() to convert to a usable date.

func NewDateWithTime

func NewDateWithTime(t time.Time, isEndOfRange bool) Date

NewDateWithTime creates a new Date with the provided time.Time.

It is important to note that a Date only has a resolution of a single day and does not take into account timezone information.

The isEndOfRange must be provided to signal if the Date returned represents the start or end of the day since the minimum resolution is one day.

The returned Date will have an Exact constraint.

If t IsZero then a zero Date will be returned (see Date.IsZero).

func NewZeroDate

func NewZeroDate() Date

func (Date) Equals

func (date Date) Equals(date2 Date) bool

Equals compares two dates.

Unlike Is(), Equals() takes into what the date and its constraint represents, rather than just its raw value.

For example, "3 Sep 1943" == "Bef. Oct 1943" returns true because 3 Sep 1943 is before Oct 1943.

If either date (including both) is IsZero then false is always returned.

If Is() is true when comparing both dates then true is always returned.

Otherwise the comparison used is selected from the following matrix:

        ----------- Left ----------
        Exact  About  Before  After
 Exact    A      A      B       C
 About    A      A      D       D
Before    C      D      C       D
 After    B      D      D       B

A. A match if the day, month and year are all equal.

B. Match if left.Years() > right.Years().

C. Match if left.Years() < right.Years().

D. Never a match.

func (Date) Is

func (date Date) Is(date2 Date) bool

Is compares two dates. Dates are only considered to be the same if the day, month, year and constraint are all the same.

The IsEndOfRange property is not used as part of the comparison because it only affects the behaviour of Time().

func (Date) IsAfter

func (date Date) IsAfter(date2 Date) bool

func (Date) IsBefore

func (date Date) IsBefore(date2 Date) bool

func (Date) IsExact

func (date Date) IsExact() bool

IsExact will return true all parts of the date are complete and the date constraint is exact.

This is to say that is points to a specific day.

func (Date) IsZero

func (date Date) IsZero() bool

IsZero returns true if the day, month and year are not provided. No other attributes are taken into consideration.

func (Date) String

func (date Date) String() string

String returns the date in one of the three forms:

17 Jul 1890
Jul 1890
1890

All forms of the date may also be proceeded with one of the constraints:

Abt.
Aft.
Bef.

func (Date) Sub

func (date Date) Sub(date2 Date) Duration

func (Date) Time

func (date Date) Time() time.Time

Time returns the minimum or maximum (depending on IsEndOfRange) representation of the Date as a Go Time instance.

func (Date) Years

func (date Date) Years() float64

Years returns the number of years of a date as a floating-point. It can be used as an approximation to get a general idea of how far apart dates are but should not be treated as an accurate representation of time.

The smallest date unit in a GEDCOM is a day. For specific dates it is calculated as the number of days that have past, divided by the number of days in that year (to correct for leap years). For example "10 Oct 2009" would return 2009.860274.

Since some date components can be missing (like the day or month) Years compensates by returning the midpoint (average) of the maximum and minimum value in days. For example the date "Mar 1945" is the equivalent to the average Years value of "1 Mar 1945" and "31 Mar 1945", returning 1945.205479.

When only a year is provided 0.5 will be added to the year. For example, "1845" returns 1845.5. This is not the exact midpoint of the year but will be close enough for general calculations. You should not rely on 0.5 being returned (as part of a check) as this may change in the future.

The value returned from Years is not effected by any other component of the date. Such as if the date is approximate ("Abt.", etc) or directional ("Bef.", "Aft.", etc). If this property is important to you will need to take it into account in an appropriate way.

type DateConstraint

type DateConstraint int

DateConstraint describes if a date is constrained by a particular range. See Date for full explanation.

func DateConstraintFromString

func DateConstraintFromString(word string) DateConstraint

DateConstraintFromString will return the constraint for the provided keyword based on the keywords described in the specification of DateNode.

If the word is not understood DateConstraintExact will be returned.

This function is not case sensitive so "before" and "Before" are treated the same.

func (DateConstraint) String

func (constraint DateConstraint) String() string

String returns the constraint abbreviation for non-exact dates. Exact dates will return an empty string.

The chosen (default) abbreviation is the first value in the appropriate DateWords constant.

If the constraint is invalid then an empty string will be returned.

type DateNode

type DateNode struct {
	*SimpleNode
	// contains filtered or unexported fields
}

DateNode represents a DATE node.

See the full specification for dates in the documentation for Date.

func NewDateNode

func NewDateNode(value string, children ...Node) *DateNode

NewDateNode creates a new DATE node.

func (*DateNode) DateRange

func (node *DateNode) DateRange() (dateRange DateRange)

If the node is nil both results will be zero dates.

func (*DateNode) EndDate

func (node *DateNode) EndDate() Date

func (*DateNode) Equals

func (node *DateNode) Equals(node2 Node) bool

func (*DateNode) IsAfter

func (node *DateNode) IsAfter(node2 *DateNode) bool

func (*DateNode) IsBefore

func (node *DateNode) IsBefore(node2 *DateNode) bool

func (*DateNode) IsExact

func (node *DateNode) IsExact() bool

func (*DateNode) IsPhrase

func (node *DateNode) IsPhrase() bool

func (*DateNode) IsValid

func (node *DateNode) IsValid() bool

func (*DateNode) Similarity

func (node *DateNode) Similarity(node2 *DateNode, maxYears float64) float64

func (*DateNode) StartAndEndDates

func (node *DateNode) StartAndEndDates() (Date, Date)

func (*DateNode) StartDate

func (node *DateNode) StartDate() Date

func (*DateNode) String

func (node *DateNode) String() string

String returns the date range as defined in the specification of DateNode.

There are too many combinations to document here, but the two main formats you will receive will look like:

Bet. Feb 1956 and Mar 1956
Abt. 13 Nov 1983

func (*DateNode) Sub

func (node *DateNode) Sub(node2 *DateNode) (min Duration, max Duration, errs error)

func (*DateNode) Warnings

func (node *DateNode) Warnings() Warnings

func (*DateNode) Years

func (node *DateNode) Years() float64

Years fulfils the Yearer interface and is a convenience for:

node.DateRange().Years()

type DateNodes

type DateNodes []*DateNode

DateNodes is a slice of zero or more DateNodes. It may also be nil as other slice.

func Dates

func Dates(nodes ...Node) (result DateNodes)

Dates returns the shallow DateNodes.

Dates is safe to use with nil nodes.

Dates will always return all dates, even dates that are invalid.

func (DateNodes) Maximum

func (dates DateNodes) Maximum() *DateNode

Maximum returns the date node with the maximum Years value from the provided slice.

For date ranges the end value is used. For example "Between 1924 and 1934" is considered greater than "Between 1923 and 1943" because 1924 is greater than 1923. Even though the Years value (which is an average) would place them in the opposite order.

If the slice is nil or contains zero elements then nil will be returned.

func (DateNodes) Minimum

func (dates DateNodes) Minimum() *DateNode

Minimum returns the date node with the minimum Years value from the provided slice.

For date ranges the start value is used. For example "Between 1923 and 1943" is considered less than "Between 1924 and 1934" because 1923 is less than 1924. Even though the Years value (which is an average) would place them in the opposite order.

If the slice is nil or contains zero elements then nil will be returned.

func (DateNodes) Range

func (dates DateNodes) Range() DateRange

func (DateNodes) StripZero

func (dates DateNodes) StripZero() (validDates DateNodes)

StripZero returns a new slice that only contains dates that are not zero.

A "zero date" (Date.IsZero) is a date that is missing the year, month and day. Even if there is other associated information this date is considered to be useless for most purposes.

type DateRange

type DateRange struct {
	// contains filtered or unexported fields
}

A DateRange represents a period of time.

The minimum possible period is 1 day and ranges only have a resolution of a single day.

DateRanges should be considered immutable and are passed by value because of this. You should create a new DateRange to represent a new range rather than mutating an existing DateRange.

func NewDateRange

func NewDateRange(start, end Date) DateRange

NewDateRange creates a new date range between two provided dates. It is expected that the start date be less than or equal to the end date.

func NewDateRangeWithNow

func NewDateRangeWithNow() DateRange

NewDateWithNow creates a two Dates that represents the the start and end of the current day. See NewDateWithTime for implementation details.

func NewDateRangeWithString

func NewDateRangeWithString(s string) (dr DateRange)

func NewZeroDateRange

func NewZeroDateRange() DateRange

func (DateRange) Compare

func (dr DateRange) Compare(dr2 DateRange) DateRangeComparison

func (DateRange) Duration

func (dr DateRange) Duration() Duration

func (DateRange) EndDate

func (dr DateRange) EndDate() Date

End is the upper boundary of the date range.

func (DateRange) Equals

func (dr DateRange) Equals(dr2 DateRange) bool

Equals compares the values of two dates taking into consideration the date constraint.

If either date is nil then false is always returned. Even if both dates are nil.

A DateNode is considered to be equal only when its StartDate() and EndDate() both equal their respective values in the other DateNode.

The comparisons of dates is quite complicated. See the documentation for Date.Equals for a full explanation.

func (DateRange) IsAfter

func (dr DateRange) IsAfter(dr2 DateRange) bool

After returns true if the end date is after the other end date.

See Before for a more detailed explanation.

func (DateRange) IsBefore

func (dr DateRange) IsBefore(dr2 DateRange) bool

Before returns true if the start date is before the other start date.

The idea of "before" in the context of overlapping date ranges is ambiguous. The simplest way to think treat all these situations is to only look at the start date for each range. No matter when the end dates are or how much of each other then end up overlapping.

func (DateRange) IsExact

func (dr DateRange) IsExact() bool

IsExact will return true if the date range represents a single day with an exact constraint.

See Date.IsExact for more information.

func (DateRange) IsPhrase

func (dr DateRange) IsPhrase() bool

IsPhrase returns true if the date value is a phrase.

A phrase is any statement offered as a date when the year is not recognizable to a date parser, but which gives information about when an event occurred. The date phrase is enclosed in matching parentheses.

IsPhrase is safe to use on a nil DateNode, and will return false.

func (DateRange) IsValid

func (dr DateRange) IsValid() bool

IsValid returns true only when the node is not nil and the start and end date are non-zero.

A "zero date" (Date.IsZero) is a date that is missing the year, month and day. Even if there is other associated information this date is considered to be useless for most purposes.

It is safe and completely valid to use IsValid on a nil node.

func (DateRange) ParseError

func (dr DateRange) ParseError() error

func (DateRange) Similarity

func (dr DateRange) Similarity(dr2 DateRange, maxYears float64) float64

Similarity returns a value from 0.0 to 1.0 to identify how similar two dates (or date ranges) are to each other. 1.0 would mean that the dates are exactly the same, whereas 0.0 would mean that they are not similar at all.

Similarity is safe to use when either date is nil. If either side is nil then 0.5 is returned. Not because they are similar but because there is not enough information to make the distinction either way. This is important when using date comparisons in combination or part of larger calculations where missing data on both sides does not lead to very low scores unnecessarily.

The returned value is calculated on a parabola that awards higher values to dates that are proportionally closer to each other. That is, dates that are twice as close will have more than twice the score. This attempts to satisfy a usable comparison values for close specific dates as well as more relaxed values (such as those that one provide an approximate year).

Only the difference between dates is used in the calculation so it is not affected by time lines. That is to say that the difference between the years 500 and 502 would return the same similarity as the years 2000 to 2002.

The maxYears allows the error margin to be adjusted. Dates that are further apart (in any direction) than maxYears will always return 0.0.

A greater maxYears can be used when dates are less exact (such as ancient dates that could be commonly off by 10 years or more) or a smaller value when dealing with recent dates that are provided in a more exact form.

A sensible default value for maxYears is provided with DefaultMaxYearsForSimilarity. You should use this if you are unsure. There is also more explanation on the constant.

func (DateRange) StartAndEndDates

func (dr DateRange) StartAndEndDates() (Date, Date)

func (DateRange) StartDate

func (dr DateRange) StartDate() Date

Start is the lower boundary of the date range.

func (DateRange) String

func (dr DateRange) String() string

func (DateRange) Sub

func (dr DateRange) Sub(dr2 DateRange) DurationRange

func (DateRange) Years

func (dr DateRange) Years() float64

Years works in a similar way to Date.Years() but also takes into consideration the StartDate() and EndDate() values of a whole date range, like "Bet. 1943 and 1945". It does this by averaging out the Years() value of the StartDate() and EndDate() values.

If the DateNode has a single date, like "Mar 1937" then Years will return the same value as the Years on the start or end date (no average will be used.)

You can read the specific conversion rules in Date.Years() but be aware that the returned value is an approximation and should not be used in date calculations.

type DateRangeComparison

type DateRangeComparison int

DateRangeComparison describe how two date ranges (each can be described with a DateNode) relate to each other.

Since we are comparing ranges of time, rather than absolute points there are several variations of results to be considered. It's easiest to explain visually where Left and Right are the date range operands respectively:

                                                    Method returns true:
Left:                        |========|
Right:
  Equal:                     |========|             IsEqual()
  Inside:                    | <====> |             IsPartiallyEqual()
  InsideStart:               |======> |             IsPartiallyEqual()
  InsideEnd:                 | <======|             IsPartiallyEqual()
  Outside:               <===+========+===>         IsPartiallyEqual()
  OutsideStart:              |========+===>         IsPartiallyEqual()
  OutsideEnd:            <===+========|             IsPartiallyEqual()
  PartiallyBefore:       <===+===>    |             IsPartiallyEqual()
  PartiallyAfter:            |     <==+===>         IsPartiallyEqual()
  Before:                <===|        |             IsNotEqual()
  After:                     |        |===>         IsNotEqual()
  EntirelyBefore:        <=> |        |             IsNotEqual()
  EntirelyAfter:             |        | <=>         IsNotEqual()

The Simplified value is the DateRangeComparisonSimplified value which is derived from DateRangeComparison.Simplified().

func (DateRangeComparison) IsEqual

func (c DateRangeComparison) IsEqual() bool

IsEqual returns true only if both date ranges are exactly the same.

It's important to note that a DateRangeComparison can be in one of three simplified states: Equal, PartiallyEqual or NotEqual. So !IsEqual() is not the same as IsNotEqual().

func (DateRangeComparison) IsNotEqual

func (c DateRangeComparison) IsNotEqual() bool

IsNotEqual returns true if the two date ranges do not intersect at any point.

It's important to note that a DateRangeComparison can be in one of three simplified states: Equal, PartiallyEqual or NotEqual. So !IsNotEqual() is not the same as IsEqual().

func (DateRangeComparison) IsPartiallyEqual

func (c DateRangeComparison) IsPartiallyEqual() bool

IsPartiallyEqual returns true if any part of the date range touches or intersects another.

func (DateRangeComparison) String

func (c DateRangeComparison) String() string

String returns the name of the constant like "DateRangeComparisonInsideStart".

type Dater

type Dater interface {
	Dates() DateNodes
}

Dater is implemented by nodes that are reasonably expected to have dates associated with them, such as events.

type DeathNode

type DeathNode struct {
	*SimpleNode
}

DeathNode is the event when mortal life terminates.

func NewDeathNode

func NewDeathNode(value string, children ...Node) *DeathNode

NewDeathNode creates a new DEAT node.

func (*DeathNode) Dates

func (node *DeathNode) Dates() DateNodes

Dates returns zero or more dates associated with the death.

When more than one date is returned you should not assume that the order has any significance for the importance of the dates.

If the node is nil the result will also be nil.

func (*DeathNode) Equals

func (node *DeathNode) Equals(node2 Node) bool

Equal will always return true if both nodes are not nil.

If either node is nil (including both) or if the right side is not a DeathNode then false is always returned. Otherwise Equals will always return true.

The reason Equals always returns true is because Equals is a shallow test and an individual can only ever have one death event. Therefore it is safe to assume that death events themselves are equal, even if the children they contain are not.

This logic is especially important for CompareNodes.

type Decoder

type Decoder struct {

	// It is not valid for GEDCOM values to contain new lines or carriage
	// returns. However, some application dump data without correctly using the
	// CONT tags.
	//
	// Strictly speaking we should bail out with an error but there are too many
	// cases that are difficult to clean up for consumers so we offer and option
	// to permit it.
	//
	// When enabled any line than cannot be parsed will be considered an
	// extension of the previous line (including the new line character).
	AllowMultiLine bool

	// AllowInvalidIndents allows a child node to have an indent greater than +1
	// of the parent. AllowInvalidIndents is disabled by default because if this
	// happens the GEDCOM file is broken in some possibly serious way and
	// certainly not a valid GEDCOM file.
	//
	// The biggest problem with having the indents wrongly aligned is that nodes
	// that are expected to be a certain depth (such as NPFX inside a NAME) will
	// probably break or interfere with a traversal algorithm that is not
	// expecting the node to be there/at that level.
	//
	// Another important thing to note is that the incorrect indent level will
	// not be retained when writing the Document back to a GEDCOM.
	AllowInvalidIndents bool
	// contains filtered or unexported fields
}

Decoder represents a GEDCOM decoder.

func NewDecoder

func NewDecoder(r io.Reader) *Decoder

Create a new decoder to parse a reader that contain GEDCOM data.

func (*Decoder) Decode

func (dec *Decoder) Decode() (*Document, error)

Decode will parse the entire GEDCOM stream (until EOF is reached) and return a Document. If the GEDCOM stream is not valid then the document node will be nil and the error is returned.

A blank GEDCOM or a GEDCOM that only contains empty lines is valid and a Document will be returned with zero nodes.

type Document

type Document struct {
	// HasBOM controls if the encoded stream will start with the Byte Order
	// Mark.
	//
	// This is not recommended by the UTF-8 standard and many applications will
	// have problems reading the data. However, streams that were decoded
	// containing the BOM will retain it so that the re-encoded stream is as
	// compatible and similar to the original stream as possible.
	//
	// Also see Decoder.consumeOptionalBOM().
	HasBOM bool

	// MaxLivingAge is used by Individual.IsLiving to determine if an individual
	// without a DeathNode should be considered living.
	//
	// 100 is chosen as a reasonable default. If you set it to 0 then an
	// individual will never be considered dead without a DeathNode.
	MaxLivingAge float64
	// contains filtered or unexported fields
}

Document represents a whole GEDCOM document. It is possible for a Document to contain zero Nodes, this means the GEDCOM file was empty. It may also (and usually) contain several Nodes.

You should not instantiate a Document yourself because there are sensible defaults and cache that need to be setup. Use one of the NewDocument constructors instead.

func MergeDocuments

func MergeDocuments(left, right *Document, mergeFn MergeFunction) *Document

MergeDocuments creates a new document with their respective nodes merged.

The MergeFunction must not be nil, but may return nil. See MergeFunction for usage.

The left and right may be nil. This is treated as an empty document.

The result document will have a deep copy of all nodes. So it's safe to manipulate the nodes without affecting the original nodes.

Individuals will not be merged amongst each other, only appended to the final document. To merge similar individuals see MergeDocumentsAndIndividuals.

func MergeDocumentsAndIndividuals

func MergeDocumentsAndIndividuals(left, right *Document, mergeFn MergeFunction, options *IndividualNodesCompareOptions) (*Document, error)

MergeDocumentsAndIndividuals merges two documents while also merging similar individuals.

The MergeFunction must not be nil, but may return nil. It will only be used for nodes that are not individuals. See MergeFunction for usage.

The options must be provided, see

func NewDocument

func NewDocument() *Document

NewDocument returns an empty document.

func NewDocumentFromGEDCOMFile

func NewDocumentFromGEDCOMFile(path string) (*Document, error)

NewDocumentFromGEDCOMFile returns a decoded Document from the provided file.

If the file does not exist, be read or parse then an error is returned and the document will be nil.

func NewDocumentFromString

func NewDocumentFromString(gedcom string) (*Document, error)

NewDocumentFromString creates a document from a string containing GEDCOM data.

An error is returned if a line cannot be parsed.

func NewDocumentWithNodes

func NewDocumentWithNodes(nodes Nodes) *Document

NewDocumentWithNodes creates a new document with the provided root nodes.

func (*Document) AddFamily

func (doc *Document) AddFamily(pointer string) *FamilyNode

func (*Document) AddFamilyWithHusbandAndWife

func (doc *Document) AddFamilyWithHusbandAndWife(pointer string, husband, wife *IndividualNode) *FamilyNode

func (*Document) AddIndividual

func (doc *Document) AddIndividual(pointer string, children ...Node) *IndividualNode

func (*Document) AddNode

func (doc *Document) AddNode(node Node)

AddNode appends a node to the document.

If the node is nil this function has no effect.

If the node already exists it will be added again. This will cause problems with duplicate references.

func (*Document) DeleteNode

func (doc *Document) DeleteNode(node Node) (didDelete bool)

func (*Document) Families

func (doc *Document) Families() (families FamilyNodes)

Families returns the family entities in the document.

func (*Document) GEDCOMString

func (doc *Document) GEDCOMString(indent int) string

GEDCOMString will render the entire GEDCOM document.

func (*Document) Individuals

func (doc *Document) Individuals() IndividualNodes

Individuals returns all of the people in the document.

func (*Document) NodeByPointer

func (doc *Document) NodeByPointer(ptr string) Node

NodeByPointer returns the Node for a pointer value.

If the pointer does not exist nil is returned.

func (*Document) Nodes

func (doc *Document) Nodes() Nodes

Nodes returns the root nodes for the document.

It is important that the slice returned is not manually manipulated (such as appending) because it may cause the internal cache to all out of sync. You may manipulate the nodes themselves.

func (*Document) Places

func (doc *Document) Places() map[*PlaceNode]Node

TODO: needs tests

func (*Document) SetNodes

func (doc *Document) SetNodes(nodes Nodes)

func (*Document) Sources

func (doc *Document) Sources() []*SourceNode

TODO: Needs tests

func (*Document) String

func (doc *Document) String() string

String will render the entire GEDCOM document.

It is a shorthand for the more proper GEDCOMString() function.

func (*Document) Warnings

func (doc *Document) Warnings() (warnings Warnings)

type DocumentNoder

type DocumentNoder interface {
	Document() *Document
}

type Duration

type Duration struct {
	Duration time.Duration

	// IsEstimate and IsKnown work the same way as described in Age.
	IsEstimate, IsKnown bool
}

A duration that only considers whole-day resolution.

func NewDuration

func NewDuration(duration time.Duration, isKnown, isEstimate bool) Duration

func NewExactDuration

func NewExactDuration(duration time.Duration) Duration

func (Duration) String

func (d Duration) String() string

type DurationRange

type DurationRange struct {
	Min, Max Duration
}

func NewDurationRange

func NewDurationRange(min, max Duration) DurationRange

func (DurationRange) Age

func (dr DurationRange) Age() (Age, Age)

type Encoder

type Encoder struct {
	// contains filtered or unexported fields
}

Encoder represents a GEDCOM encoder.

func NewEncoder

func NewEncoder(w io.Writer, document *Document) *Encoder

Create a new encoder to generate GEDCOM data.

func (*Encoder) Encode

func (enc *Encoder) Encode() (err error)

Encode will write the GEDCOM document to the Writer.

type Errors

type Errors []error

func NewErrors

func NewErrors(errors ...error) (errs Errors)

func (Errors) Err

func (e Errors) Err() error

func (Errors) Error

func (e Errors) Error() string

func (Errors) Errors

func (e Errors) Errors() (errors []string)

type EventNode

type EventNode struct {
	*SimpleNode
}

EventNode is a noteworthy happening related to an individual, a group, or an organization.

func NewEventNode

func NewEventNode(value string, children ...Node) *EventNode

EventNode creates a new EVEN node.

func (*EventNode) Dates

func (node *EventNode) Dates() DateNodes

Dates returns zero or more dates associated with the event.

When more than one date is returned you should not assume that the order has any significance for the importance of the dates.

If the node is nil the result will also be nil.

func (*EventNode) Equals

func (node *EventNode) Equals(node2 Node) bool

Equal tests if two events are the same.

Two events are considered equal if:

1. They both contain the same date. If either or both contain more than one date only a single date must match both sides.

2. They both do not have any dates, but all other attributes are the same.

If either node is nil (including both) or if the right side is not a EventNode then false is always returned.

func (*EventNode) Years

func (node *EventNode) Years() float64

Years returns the Years value of the minimum date node in the node.

type FamilyNode

type FamilyNode struct {
	// contains filtered or unexported fields
}

FamilyNode represents a family.

func (*FamilyNode) AddChild

func (node *FamilyNode) AddChild(individual *IndividualNode) *ChildNode

func (*FamilyNode) Children

func (node *FamilyNode) Children() ChildNodes

TODO: Needs tests

If the node is nil the result will also be nil.

func (FamilyNode) Document

func (node FamilyNode) Document() *Document

func (*FamilyNode) HasChild

func (node *FamilyNode) HasChild(individual *IndividualNode) bool

TODO: Needs tests

If the node is nil the result will also be nil.

func (*FamilyNode) Husband

func (node *FamilyNode) Husband() (husband *HusbandNode)

If the node is nil the result will also be nil.

func (*FamilyNode) SetHusband

func (node *FamilyNode) SetHusband(individual *IndividualNode) *FamilyNode

func (*FamilyNode) SetHusbandPointer

func (node *FamilyNode) SetHusbandPointer(pointer string) *FamilyNode

func (*FamilyNode) SetWife

func (node *FamilyNode) SetWife(individual *IndividualNode) *FamilyNode

func (*FamilyNode) SetWifePointer

func (node *FamilyNode) SetWifePointer(pointer string) *FamilyNode

func (FamilyNode) ShallowCopy

func (node FamilyNode) ShallowCopy() Node

func (*FamilyNode) Similarity

func (node *FamilyNode) Similarity(other *FamilyNode, depth int, options SimilarityOptions) float64

Similarity calculates the similarity between two families.

The depth controls how many generations should be compared. A depth of 0 will only compare the husband/wife and not take into account any children. At the moment only a depth of 0 is supported. Any other depth will raise panic.

The options.MaxYears allows the error margin on dates to be adjusted. See DefaultMaxYearsForSimilarity for more information.

func (*FamilyNode) String

func (node *FamilyNode) String() string

func (*FamilyNode) Warnings

func (node *FamilyNode) Warnings() (warnings Warnings)

func (*FamilyNode) Wife

func (node *FamilyNode) Wife() (wife *WifeNode)

If the node is nil the result will also be nil.

type FamilyNoder

type FamilyNoder interface {
	Family() *FamilyNode
}

type FamilyNodes

type FamilyNodes []*FamilyNode

func (FamilyNodes) ByPointer

func (nodes FamilyNodes) ByPointer(pointer string) *FamilyNode

type FamilySearchIDNode

type FamilySearchIDNode struct {
	*SimpleNode
}

FamilySearchIDNode is the unique identifier for the person on FamilySearch.org. A FamilySearch ID always takes the form of:

LZDP-V9V

There are several known tags that carry the FamilySearch ID:

_FID (UnofficialTagFamilySearchID1): Seen exported from MacFamilyFree.
_FSFTID (UnofficialTagFamilySearchID2): Some other applications.

func NewFamilySearchIDNode

func NewFamilySearchIDNode(tag Tag, value string, children ...Node) *FamilySearchIDNode

type FilterFlags

type FilterFlags struct {
	// Specific exclusions.
	NoEvents      bool
	NoResidences  bool
	NoPlaces      bool
	NoSources     bool
	NoMaps        bool
	NoChanges     bool
	NoObjects     bool
	NoLabels      bool
	NoCensuses    bool
	NoEmptyDeaths bool

	// Only vitals (name, birth, baptism, death and burial).
	OnlyVitals bool

	// Only official tags.
	OnlyOfficial bool

	// When comparing, hide lines that are equal on both sides.
	HideEqual bool

	// Condense NAME nodes to a simple string.
	NameFormat string
}

func (*FilterFlags) Filter

func (ff *FilterFlags) Filter(node Node) Node

func (*FilterFlags) FilterFunctions

func (ff *FilterFlags) FilterFunctions() []FilterFunction

func (*FilterFlags) SetupCLI

func (ff *FilterFlags) SetupCLI()

type FilterFunction

type FilterFunction func(node Node) (newNode Node, traverseChildren bool)

FilterFunction is used with the Filter function.

The node (as passed in through the parameter) will be replaced with newNode. You should return the same node argument if you do not want the node to be changed.

The traverseChildren argument decides if the traversal should continue through the children of node. If the traversal continues (traverseChildren is true) the FilterFunction will always receive the children of the node, and not the children (if any) of newNode.

If the newNode is nil then it will be removed and the children will not be traversed, regardless of the traverseChildren value.

func BlacklistTagFilter

func BlacklistTagFilter(tags ...Tag) FilterFunction

BlacklistTagFilter returns any node that is not one of the provided tags.

This is the opposite of WhitelistTagFilter.

See the Filter function.

func OfficialTagFilter

func OfficialTagFilter() FilterFunction

OfficialTagFilter returns any node that is official tag. See Tag.IsOfficial for more information.

See the Filter function.

func OnlyVitalsTagFilter

func OnlyVitalsTagFilter() FilterFunction

OnlyVitalsTagFilter removes all tags except for vital individual information.

The vital nodes are (or multiples in the same individual of): Name, birth, baptism, death and burial. Within these only the date and place is retained.

func RemoveEmptyDeathTagFilter

func RemoveEmptyDeathTagFilter() FilterFunction

RemoveEmptyDeathTagFilter removes any Death (DEAT) events that do not have any child nodes (which would otherwise be information like the date or place.

This is because some applications use the death tag as a marker without any further information which can cause problems when comparing individuals.

func SimpleNameFilter

func SimpleNameFilter(format NameFormat) FilterFunction

SimpleNameFilter flattens NAME nodes with the provided format.

This is useful for comparing names when the components of the name (title, suffix, etc) are less important than the name itself.

func WhitelistTagFilter

func WhitelistTagFilter(tags ...Tag) FilterFunction

WhitelistTagFilter returns any node that is one of the provided tags.

This is the opposite of BlacklistTagFilter.

See the Filter() function.

type FormatNode

type FormatNode struct {
	*SimpleNode
}

FormatNode represents an assigned name given to a consistent format in which information can be conveyed.

func NewFormatNode

func NewFormatNode(value string, children ...Node) *FormatNode

NewFormatNode creates a new FORM node.

type GEDCOMLiner

type GEDCOMLiner interface {
	// GEDCOMLine will return a single GEDCOM line, excluding children and with
	// an optional indent-level.
	//
	// The indent will only be included if it is at least 0. If you want to use
	// GEDCOMLine to compare the string values of nodes or exclude the indent
	// you should use the NoIndent constant.
	//
	// It is not safe to invoke GEDCOMLine on a nil value. Use GEDCOMLine() for
	// a safer alternative.
	GEDCOMLine(indent int) string
}

GEDCOMLiner allows an instance to return the single-line GEDCOM value as a string. This excludes any child nodes.

type GEDCOMStringer

type GEDCOMStringer interface {
	// GEDCOMString returns the multi-line GEDCOM that includes an optional
	// indent for each line.
	//
	// The indent will only be included if it is at least 0. If you want to use
	// GEDCOMString to compare the string values of nodes or exclude the indent
	// you should use the NoIndent constant.
	//
	// It is not safe to invoke GEDCOMString on a nil value. Use GEDCOMString()
	// for a safer alternative.
	GEDCOMString(indent int) string
}

GEDCOMStringer allows an instance to be rendered as multi-line GEDCOM.

GEDCOMStringer can be thought of as a superset of GEDCOMLiner, often sharing the same line. However, for some entities (such as a Document) it does not make sense to implement GEDCOMLiner as well.

type HusbandNode

type HusbandNode struct {
	*SimpleNode
	// contains filtered or unexported fields
}

HusbandNode is an individual in the family role of a married man or father.

func (*HusbandNode) Family

func (node *HusbandNode) Family() *FamilyNode

func (*HusbandNode) Individual

func (node *HusbandNode) Individual() *IndividualNode

func (*HusbandNode) IsIndividual

func (node *HusbandNode) IsIndividual(node2 *IndividualNode) bool

func (*HusbandNode) Similarity

func (node *HusbandNode) Similarity(other *HusbandNode, options SimilarityOptions) float64

func (*HusbandNode) String

func (node *HusbandNode) String() string

type IncorrectEventOrderWarning

type IncorrectEventOrderWarning struct {
	SimpleWarning
	FirstEvent, SecondEvent         Node
	FirstDateRange, SecondDateRange DateRange
}

IncorrectEventOrderWarning produces warnings where events for an individual are in an incorrect order. For example a burial before a death event, or a baptism before a birth.

func NewIncorrectEventOrderWarning

func NewIncorrectEventOrderWarning(firstEvent Node, firstDateRange DateRange, secondEvent Node, secondDateRange DateRange) *IncorrectEventOrderWarning

func (*IncorrectEventOrderWarning) Name

func (*IncorrectEventOrderWarning) String

func (w *IncorrectEventOrderWarning) String() string

type IndividualComparison

type IndividualComparison struct {
	// Left or Right may be nil, but never both.
	Left, Right *IndividualNode

	// Similarity will only contain a usable value if Left and Right are not
	// nil. Otherwise, Similarity may contain any unexpected value.
	Similarity *SurroundingSimilarity
	// contains filtered or unexported fields
}

IndividualComparison is the result of two compared individuals.

func NewIndividualComparison

func NewIndividualComparison(Left, Right *IndividualNode, Similarity *SurroundingSimilarity) *IndividualComparison

func (IndividualComparison) String

func (c IndividualComparison) String() string

String returns the comparison in a human-readable format, like one of:

John Smith <-> John H Smith (0.833333)
Jane Doe <-> (none) (?)
(none) <-> Joe Bloggs (?)

type IndividualComparisons

type IndividualComparisons []*IndividualComparison

IndividualComparisons is a slice of IndividualComparison instances.

func (IndividualComparisons) String

func (comparisons IndividualComparisons) String() string

String returns each comparison string on its own like, like:

John Smith <-> John H Smith (0.833333)
Jane Doe <-> (none) (?)
(none) <-> Joe Bloggs (?)

type IndividualNode

type IndividualNode struct {
	// contains filtered or unexported fields
}

IndividualNode represents a person.

func (*IndividualNode) AddBaptismDate

func (node *IndividualNode) AddBaptismDate(baptismDate string) *IndividualNode

func (*IndividualNode) AddBirthDate

func (node *IndividualNode) AddBirthDate(birthDate string) *IndividualNode

func (*IndividualNode) AddBurialDate

func (node *IndividualNode) AddBurialDate(burialDate string) *IndividualNode

func (*IndividualNode) AddDeathDate

func (node *IndividualNode) AddDeathDate(deathDate string) *IndividualNode

func (*IndividualNode) AddName

func (node *IndividualNode) AddName(name string) *IndividualNode

func (*IndividualNode) Age

func (node *IndividualNode) Age() (Age, Age)

Age returns the best estimate minimum and maximum age of the individual if they are still living or their approximate age range at the time of their death.

Age will use EstimatedBirthDate which will allow it to be more resilient if a birth date is strictly missing but this means that the value returned from Age may not always be exact. See IsEstimate and other fields returned in either Age return values.

If the birth or death date is a range, such as "Between 1945 and 1947" the minimum and maximum possible ages will be returned.

If the birth or death date is not an exact value then the ages will be estimates. See Age.IsEstimate.

If no estimated birth date can be determined then Age.IsKnown will be false.

IsLiving will be used to determine if the individual is still living which includes a maximum possible age when no death elements exist. However, in the case that the individual is not living then EstimatedDeathDate will be used to try and estimate the age at the time of death instead of simply using the maximum possible age (which is 100 by default).

func (*IndividualNode) AgeAt

func (node *IndividualNode) AgeAt(event Node) (Age, Age)

AgeAt follows the same logic as Age but uses an event as the comparison instead of the current time.

If there is more than one date associated with the event or a date contains a range the minimum and maximum values will be used to return the full range.

func (*IndividualNode) AllEvents

func (node *IndividualNode) AllEvents() (nodes Nodes)

AllEvents returns zero or more events of any kind for the individual.

This is not to be confused with the EventNode.

func (*IndividualNode) Baptism

func (node *IndividualNode) Baptism() (*DateNode, *PlaceNode)

Baptism returns the first values for the date and place of the baptism events.

func (*IndividualNode) Baptisms

func (node *IndividualNode) Baptisms() []*BaptismNode

Baptisms returns zero or more baptism events for the individual. The baptisms do not include LDS baptisms.

If the node is nil the result will also be nil.

func (*IndividualNode) Birth

func (node *IndividualNode) Birth() (*DateNode, *PlaceNode)

Birth returns the first values for the date and place of the birth events.

func (*IndividualNode) Births

func (node *IndividualNode) Births() (nodes []*BirthNode)

Births returns zero or more birth events for the individual.

If the node is nil the result will also be nil.

func (*IndividualNode) Burial

func (node *IndividualNode) Burial() (*DateNode, *PlaceNode)

Burial returns the first values for the date and place of the burial events.

func (*IndividualNode) Burials

func (node *IndividualNode) Burials() []*BurialNode

Burials returns zero or more burial events for the individual.

If the node is nil the result will also be nil.

func (*IndividualNode) Children

func (node *IndividualNode) Children() ChildNodes

TODO: Needs tests

If the node is nil the result will also be nil.

func (*IndividualNode) Death

func (node *IndividualNode) Death() (*DateNode, *PlaceNode)

Death returns the first values for the date and place of the death events.

func (*IndividualNode) Deaths

func (node *IndividualNode) Deaths() []*DeathNode

Deaths returns zero or more death events for the individual. It is common for individuals to not have a death event if the death date is not known. If you need to check if an individual is living you should use IsLiving().

If the node is nil the result will also be nil.

func (IndividualNode) Document

func (node IndividualNode) Document() *Document

func (*IndividualNode) EstimatedBirthDate

func (node *IndividualNode) EstimatedBirthDate() (date *DateNode, isBirthEvent bool)

EstimatedBirthDate attempts to find the exact or approximate birth date of an individual. It does this by looking at the births, baptisms and LDS baptisms. If any of them contain a date then the lowest date value is returned based on the Years() value which takes in account the full date range.

This logic is loosely based off the idea that if the birth date is not known that a baptism usually happens when the individual is quite young (and therefore close to the their birth date).

It is worth noting that since EstimatedBirthDate returns the lowest possible date that an exact birth date will be ignored if another event happens in a range before that. For example, if an individual has a birth date of "9 Feb 1983" but the Baptism was "9 Jan 1983" then the Baptism is returned. This data must be wrong in either case but EstimatedBirthDate cannot make a sensible decision in this case so it always returned the earliest date.

EstimatedBirthDate is useful when comparing individuals where the exact dates are less important that attempting to serve approximate information for comparison. You almost certainly do not want to use the EstimatedBirthDate value for anything meaningful aside from comparisons.

If the node is nil the result will also be nil.

func (*IndividualNode) EstimatedDeathDate

func (node *IndividualNode) EstimatedDeathDate() (date *DateNode, isDeathEvent bool)

EstimatedDeathDate attempts to find the exact or approximate death date of an individual. It does this by returning the earliest death date based on the value of Years(). If there are no death dates then it will attempt to return the minimum burial date.

This logic is loosely based off the idea that if the death date is not known that a burial usually happens a short time after the death of the individual.

It is worth noting that EstimatedDeathDate will always return a death date if one is present before falling back to a possibly more specific burial date. One example of this might be a death date that has a large range such as "1983 - 1993". The burial may be a much more specific date like "Apr 1985". This almost certainly indicates that the death date was around early 1985, however the larger death date range will still be returned.

EstimatedDeathDate is useful when comparing individuals where the exact dates are less important that attempting to serve approximate information for comparison. You almost certainly do not want to use the EstimatedDeathDate value for anything meaningful aside from comparisons.

If the node is nil the result will also be nil.

func (*IndividualNode) Families

func (node *IndividualNode) Families() (families FamilyNodes)

TODO: needs tests

If the node is nil the result will also be nil.

func (*IndividualNode) FamilySearchIDs

func (node *IndividualNode) FamilySearchIDs() (nodes []*FamilySearchIDNode)

func (*IndividualNode) FamilyWithSpouse

func (node *IndividualNode) FamilyWithSpouse(spouse *IndividualNode) *FamilyNode

TODO: needs tests

If the node is nil the result will also be nil.

func (*IndividualNode) FamilyWithUnknownSpouse

func (node *IndividualNode) FamilyWithUnknownSpouse() *FamilyNode

TODO: needs tests

If the node is nil the result will also be nil.

func (*IndividualNode) Is

func (node *IndividualNode) Is(individual *IndividualNode) bool

TODO: needs tests

func (*IndividualNode) IsLiving

func (node *IndividualNode) IsLiving() bool

IsLiving determines if the individual is living.

If no death node exists, but the estimated birth date is found to be older than Document.MaxLivingAge then the individual will not be considered living.

The default value for MaxLivingAge is 100 and can be modified on the document attached to this node. A MaxLivingAge of 0 means that it will only consider the individual to be not living if there is an explicit Death event.

If there is no document attached DefaultMaxLivingAge will be used.

If the node is nil the result will always be false.

func (*IndividualNode) LDSBaptisms

func (node *IndividualNode) LDSBaptisms() Nodes

LDSBaptisms returns zero or more LDS baptism events for the individual. These are not to be confused with Baptisms().

If the node is nil the result will also be nil.

func (*IndividualNode) Name

func (node *IndividualNode) Name() *NameNode

TODO: Needs tests

If the node is nil the result will also be nil.

func (*IndividualNode) Names

func (node *IndividualNode) Names() []*NameNode

If the node is nil the result will also be nil.

func (*IndividualNode) Parents

func (node *IndividualNode) Parents() FamilyNodes

Parents returns the families for which this individual is a child. There may be zero or more parents for an individual. The families returned will all reference this individual as child. However the father, mother or both may not exist.

It is also possible to have duplicate families. That is, families that have the same husband and wife combinations if these families are defined in the GEDCOM file.

If the node is nil the result will also be nil.

func (*IndividualNode) SetSex

func (node *IndividualNode) SetSex(sex string) *IndividualNode

SetSex adds or replaces tge gender of an individual. You should use one of the SexMale, SexFemale or SexUnknown constants.

func (*IndividualNode) Sex

func (node *IndividualNode) Sex() *SexNode

If the node is nil the result will be SexUnknown.

func (IndividualNode) ShallowCopy

func (node IndividualNode) ShallowCopy() Node

func (*IndividualNode) Similarity

func (node *IndividualNode) Similarity(other *IndividualNode, options SimilarityOptions) float64

Similarity calculates how similar two individuals are. The returned value will be between 0.0 and 1.0 where 1.0 means an exact match.

You should prefer SurroundingSimilarity, a more advanced checker that uses this function as part of it's ultimate analysis.

The similarity is based off three equally weighted components, the individuals name, estimated birth and estimated death date and is calculated as follows:

similarity = (nameSimilarity + birthSimilarity + deathSimilarity) / 3.0

Individual names are compared with the StringSimilarity function that does not consider the punctuation and extra spacing.

An individual may have more than one name, if this is the case then each name is checked and the highest matching combination is used.

The birth and death dates use the EstimatedBirthDate and EstimatedDeathDate functions respectively. These functions are allowed to make some estimates when critical information like the birth date does not exist so there is more data to include in the comparison.

Both dates are compared with the DateNode.Similarity function, which also returns a value of 0.0 to 1.0. To put simply the dates must existing within an error margin (for example, 10 years in either direction). Higher scores are awarded to dates that are more relatively closer to each other on a parabola. See DateNode.Similarity for a full explanation of how it deals with approximate dates and date ranges.

It is safe to use Similarity when one or both of the individuals are nil. This will always result in a 0.5. It is a 0.5 not because it is a partial match but that a positive or negative match cannot be determined. This is important when Similarity is used is more extensive similarity calculations as to not unnecessarily skew the results.

The options.MaxYears allows the error margin on dates to be adjusted. See DefaultMaxYearsForSimilarity for more information.

func (*IndividualNode) SpouseChildren

func (node *IndividualNode) SpouseChildren() SpouseChildren

SpouseChildren maps the known spouses to their children. The spouse will be nil if the other parent is not known for some or all of the children. Children can appear under multiple spouses.

If the node is nil the result will also be nil.

func (*IndividualNode) Spouses

func (node *IndividualNode) Spouses() (spouses IndividualNodes)

TODO: needs tests

If the node is nil the result will also be nil.

func (*IndividualNode) String

func (node *IndividualNode) String() string

String returns a human-readable representation of the individual like:

(no name) (b. Aft. 1983)
Bob Smith (b. 1943)
John Chance
Jane Doe (b. 3 Apr 1923, bur. Abt. 1943)

Ideally it will use birth (b.) and death (d.) if available. However, it will fall back to the baptism (bap.) or burial (bur.) respectively.

func (*IndividualNode) SurroundingSimilarity

func (node *IndividualNode) SurroundingSimilarity(other *IndividualNode, options SimilarityOptions, forceFullCalculation bool) (s *SurroundingSimilarity)

SurroundingSimilarity is a more advanced version of Similarity. SurroundingSimilarity also takes into account the immediate surrounding family. That is the parents, spouses and children have separate metrics calculated so they can be interpreted differently or together.

Checking for surrounding family is critical for calculating the similarity of individuals that would otherwise be considered the same because of similar names and dates in large family trees.

SurroundingSimilarity returns a structure of the same name, but really it calculates four discreet similarities:

1. IndividualSimilarity: This is the same as Individual.Similarity().

2. ParentsSimilarity: The similarity of the fathers and mothers of the individual. Each missing parent will be given 0.5. If both parents are missing the parent similarity will also be 0.5.

An individual can have zero or more pairs of parents, but only a single ParentsSimilarity is returned. The ParentsSimilarity is the highest value when each of the parents are compared with the other parents of the other individual.

3. SpousesSimilarity: The similarity of the spouses is compared with IndividualNodes.Similarity() which is designed to compare several individuals at once. It also handles comparing a different number of individuals on either side.

4. ChildrenSimilarity: Children are also compared with IndividualNodes.Similarity() but without respect to their parents (which in this case would be the current individual and likely one of their spouses). It is done this way as to not skew the results if any particular parent is unknown or the child is connected to a different spouse.

The options.MaxYears allows the error margin on dates to be adjusted. See DefaultMaxYearsForSimilarity for more information.

The options.MinimumSimilarity is used when comparing slices of individuals. In this case that means for the spouses and children. A higher value makes the matching more strict. See DefaultMinimumSimilarity for more information.

func (*IndividualNode) UniqueIDs

func (node *IndividualNode) UniqueIDs() (nodes []*UniqueIDNode)

func (*IndividualNode) UniqueIdentifiers

func (node *IndividualNode) UniqueIdentifiers() *StringSet

UniqueIdentifiers returns any strings that can be used to uniquely this individual in this document, but also between documents. For this reason the individual pointer is not included.

It's quite possible to receive an empty set, but it could also contain commonly unique identifiers such as the FamilySearch ID or UUID generated by some applications.

func (*IndividualNode) Warnings

func (node *IndividualNode) Warnings() (warnings Warnings)

type IndividualNodePair

type IndividualNodePair struct {
	Left, Right *IndividualNode
}

type IndividualNodePairs

type IndividualNodePairs []*IndividualNodePair

func (IndividualNodePairs) Has

func (pairs IndividualNodePairs) Has(findPair *IndividualNodePair) bool

type IndividualNodes

type IndividualNodes []*IndividualNode

IndividualNodes is a collection of individuals.

func (IndividualNodes) ByPointer

func (nodes IndividualNodes) ByPointer(pointer string) *IndividualNode

func (IndividualNodes) ByUniqueIdentifier

func (nodes IndividualNodes) ByUniqueIdentifier(identifier string) *IndividualNode

ByUniqueIdentifier returns the first individual that has a UniqueIdentifier of identifier. If no individual is found the nil is returned.

func (IndividualNodes) ByUniqueIdentifiers

func (nodes IndividualNodes) ByUniqueIdentifiers(identifiers *StringSet) (all IndividualNodes)

ByUniqueIdentifiers returns the any individuals that have a UniqueIdentifier of one of the provided identifiers.

func (IndividualNodes) Compare

Compare returns the matching individuals from two lists.

The length of the result slice will be no larger than the largest slice provided and no smaller than the smallest slice provided.

Individuals can only be matched once on their respective side so you can guarantee that all the Left's are unique and belong to the current nodes. Likewise all Right's will be unique and only belong to the other set.

See IndividualNodesCompareOptions for more options.

func (IndividualNodes) GEDCOMString

func (nodes IndividualNodes) GEDCOMString(indent int) string

GEDCOMString returns the GEDCOM for all individuals. See GEDCOMStringer for more details.

func (IndividualNodes) Merge

Merge uses the expensive but more accurate Compare algorithm to determine the best way to merge two slices of individuals.

Merge relies exclusively on the logic of Compare so there's no need to repeat those details here.

Any individuals that do not match on either side will be appended to the end.

func (IndividualNodes) Nodes

func (nodes IndividualNodes) Nodes() (ns Nodes)

Nodes returns a slice containing the same individuals.

Individuals that are manipulated will affect the original individuals.

func (IndividualNodes) Similarity

func (nodes IndividualNodes) Similarity(other IndividualNodes, options SimilarityOptions) float64

Similarity calculates how similar two collections of individuals are. The individuals could be children of the same parents, spouses that share the same partner or some other similar group of individuals.

Individuals that have a similarity below minimumSimilarity will not be considered a match. Making this a larger value will lead to less false-positives but also cause more true-negatives. You can use the DefaultMinimumSimilarity constant if you are unsure.

As a rule of thumb you should not trust a return value of 0.5 of less as any kind of match. 0.7 and above is getting in the range of what is likely to be considered the same.

Although there is no theoretical limit to the amount of individuals that can be compared, this function invokes a complex chain of comparisons that can be very CPU intensive. It is not a good idea to use it compare a large amount of individuals, like an entire file.

If both slices have zero elements then 1.0 is returned. However, if one slice is not empty then 0.5 is returned. 0.5 is actually the same value that would be returned in all cases if the logic were to fall through.

The algorithm works through several stages explained in more detail below but the basic principle is this:

1. Find an individual from both slices that have the highest similarity. There similarity is added to a total. These individuals are now excluded from the next pass.

2. Repeat the first step until one of the list runs out of individuals.

3. Increase the number of matched individuals to the length of the largest slice by using the score 0.5 for each individual.

4. Take the average. The total score (including the 0.5 for padding individuals) and divide it by the maximum slice size.

The easiest way to explain how the process works is by working through an example. Consider the two following slices of individuals:

[a, b, c]
[d, e]

There is 5 individuals in total, but the largest slice length is 3.

The first step is to calculate the individual similarity matrix between the inputs. This is the expensive part because it takes O(nm) time where n and m are the slice lengths respectively. The results may look like:

a.Similarity(d) = 0.234
a.Similarity(e) = 0.123
b.Similarity(d) = 0.546
b.Similarity(e) = 0.678
c.Similarity(d) = 0.235
c.Similarity(e) = 0.456

The results are sorted by their similarity score, highest first:

b.Similarity(e) = 0.678
b.Similarity(d) = 0.546
c.Similarity(e) = 0.456
c.Similarity(d) = 0.235
a.Similarity(d) = 0.234
a.Similarity(e) = 0.123

In reality the scores should be closer to 1.0 for many of the individuals, but I will use a wide range of values for this example.

The above list states that individual "b" is the most similar individual to "e". So we should consider these a match, and record the fact that "b" and "e" are matched.

Moving on to the second iteration, "b" has already been matched. Even though "d" has not we still skip this iteration. The same is true for the third iteration, since "e" has already been matched.

The forth iteration is the first time we see two new individuals, "c" and "d". For the second time we consider these two to be a match.

The process continues and can be visualised like this:

b.Similarity(e) = 0.678   b = e
b.Similarity(d) = 0.546   b already matched
c.Similarity(e) = 0.456   e already matched
c.Similarity(d) = 0.235   c = d
a.Similarity(d) = 0.234   d already matched
a.Similarity(e) = 0.123   e already matched

There should be the same amount of matches as the smallest slice size. As we can see the two matches is the same number as the smallest slice.

Finally, we pad out the remaining individuals with a score of 0.5 so that the total matches equals the longest slice. Using a middle-score (and not 0.0) is important because 0.0 would represent that individuals were a complete non-match and throw out the final score quite heavily. We must treat missing individuals as neither a perfect or non-match because we simply don't have the information to make the call either way, hence 0.5.

The returned score is now the average:

(0.678 + 0.234 + 0.5) / 3 = 0.4707

There are some known caveats to the algorithm:

When calculating the similarity of individuals where data is missing from both sides (such as both individuals having a missing birth date) then the result will be less than 1.0 even though the individuals are arguably the same.

This is designed this way on purpose as to not so eagerly match individuals with incomplete information. Otherwise these would take a higher score for matches of individuals that have a slightly different birth date.

The options.MaxYears allows the error margin on dates to be adjusted. See DefaultMaxYearsForSimilarity for more information.

func (IndividualNodes) String

func (nodes IndividualNodes) String() string

type IndividualNodesCompareOptions

type IndividualNodesCompareOptions struct {
	// SimilarityOptions controls the weights of the comparisons. See
	// SimilarityOptions for more information. Any matches below
	// MinimumSimilarity will not be used.
	//
	// Since this can take a long time to run with a lot of individuals there is
	// an optional notifier channel that can be listened to for progress
	// updates. Or pass nil to ignore this feature.
	SimilarityOptions SimilarityOptions

	// Notifier will be sent progress updates throughout the comparison if it is
	// not nil. If it is nil then this feature is ignored.
	//
	// You can control how precise this is with NotifierStep.
	//
	// You may close this Notifier to abort the comparison early.
	Notifier chan Progress

	// NotifierStep is the number of comparisons that must happen before the
	// Notifier be notified. The default is zero so all comparisons will cause a
	// notify. You should set this to a higher amount of reduce the frequency of
	// chatter.
	NotifierStep int64

	// Jobs controls the parallelism of the processing. The default value of 0
	// works the same as a value of 1 (no concurrency). Any number higher than 1
	// will create extra go routines to increase the CPU utilization of the
	// processing.
	//
	// It is important to note that the parallelism is still bound by
	// GOMAXPROCS.
	Jobs int
	// contains filtered or unexported fields
}

IndividualNodesCompareOptions provides more optional attributes for IndividualNodes.Compare.

You should use NewIndividualNodesCompareOptions to start with sensible defaults.

func NewIndividualNodesCompareOptions

func NewIndividualNodesCompareOptions() *IndividualNodesCompareOptions

NewIndividualNodesCompareOptions creates sensible defaults for IndividualNodesCompareOptions. In the majority of cases you will not need to change any further options.

Important: A single IndividualNodesCompareOptions must be created for each comparison.

func (*IndividualNodesCompareOptions) ConcurrentJobs

func (o *IndividualNodesCompareOptions) ConcurrentJobs() int

type IndividualTooOldWarning

type IndividualTooOldWarning struct {
	SimpleWarning
	Individual      *IndividualNode
	YearsOldAtDeath float64
}

func NewIndividualTooOldWarning

func NewIndividualTooOldWarning(individual *IndividualNode, yearsOldAtDeath float64) *IndividualTooOldWarning

func (*IndividualTooOldWarning) Name

func (w *IndividualTooOldWarning) Name() string

func (*IndividualTooOldWarning) String

func (w *IndividualTooOldWarning) String() string

type InverseSpousesWarning

type InverseSpousesWarning struct {
	SimpleWarning
	Family        *FamilyNode
	Husband, Wife *IndividualNode
}

func NewInverseSpousesWarning

func NewInverseSpousesWarning(family *FamilyNode, husband, wife *IndividualNode) *InverseSpousesWarning

func (*InverseSpousesWarning) Name

func (w *InverseSpousesWarning) Name() string

func (*InverseSpousesWarning) String

func (w *InverseSpousesWarning) String() string

type LatitudeNode

type LatitudeNode struct {
	*SimpleNode
}

LatitudeNode represents a value indicating a coordinate position on a line, plane, or space.

New in Gedcom 5.5.1.

func NewLatitudeNode

func NewLatitudeNode(value string, children ...Node) *LatitudeNode

NewLatitudeNode creates a new LATI node.

type LongitudeNode

type LongitudeNode struct {
	*SimpleNode
}

LongitudeNode represents a value indicating a coordinate position on a line, plane, or space.

New in Gedcom 5.5.1.

func NewLongitudeNode

func NewLongitudeNode(value string, children ...Node) *LongitudeNode

NewLongitudeNode creates a new LONG node.

type MapNode

type MapNode struct {
	*SimpleNode
}

MapNode pertains to a representation of measurements usually presented in a graphical form.

New in Gedcom 5.5.1.

func NewMapNode

func NewMapNode(value string, children ...Node) *MapNode

NewMapNode creates a new MAP node.

func (*MapNode) Latitude

func (node *MapNode) Latitude() *LatitudeNode

Latitude is the value specifying the latitudinal coordinate of the place name.

The latitude coordinate is the direction North or South from the equator in degrees and fraction of degrees carried out to give the desired accuracy.

For example: 18 degrees, 9 minutes, and 3.4 seconds North would be formatted as N18.150944.

Minutes and seconds are converted by dividing the minutes value by 60 and the seconds value by 3600 and adding the results together. This sum becomes the fractional part of the degree’s value.

func (*MapNode) Longitude

func (node *MapNode) Longitude() *LongitudeNode

Longitude is the value specifying the longitudinal coordinate of the place name.

The longitude coordinate is degrees and fraction of degrees east or west of the zero or base meridian coordinate.

For example: 168 degrees, 9 minutes, and 3.4 seconds East would be formatted as E168.150944.

type MarriedOutOfRangeWarning

type MarriedOutOfRangeWarning struct {
	SimpleWarning
	Family             *FamilyNode
	Spouse             *IndividualNode
	YearsOldAtMarriage float64

	// Either "young" or "old" to indicate which boundary was breached.
	Boundary string
}

MarriedOutOfRangeWarning is raised when the age of an individual at the time they were married is less than 16 (DefaultMinMarriageAge) or greater than 100 (DefaultMaxMarriageAge).

func NewMarriedOutOfRangeWarning

func NewMarriedOutOfRangeWarning(family *FamilyNode, spouse *IndividualNode, yearsOldAtMarriage float64, boundary string) *MarriedOutOfRangeWarning

func (*MarriedOutOfRangeWarning) Name

func (w *MarriedOutOfRangeWarning) Name() string

func (*MarriedOutOfRangeWarning) String

func (w *MarriedOutOfRangeWarning) String() string

type MergeFunction

type MergeFunction func(left, right Node) Node

MergeFunction will do one of two things:

1. If the nodes should be merged, it must return a new new node.

2. If the nodes should not or could not be merged, then nil is returned.

A MergeFunction can be used with MergeNodeSlices.

func IndividualBySurroundingSimilarityMergeFunction

func IndividualBySurroundingSimilarityMergeFunction(minimumSimilarity float64, options SimilarityOptions) MergeFunction

IndividualBySurroundingSimilarityMergeFunction creates a MergeFunction that will merge individuals if their surrounding similarity is at least minimumSimilarity.

If either of the nodes are not IndividualNode instances then it will always return nil so they will not be merged.

The minimumSimilarity should be value between 0.0 and 1.0. The options must not be nil, you should use NewSimilarityOptions() for sensible defaults.

type MultipleSexesWarning

type MultipleSexesWarning struct {
	SimpleWarning
	Individual *IndividualNode

	// Sexes should contain at least two elements. The elements may have the
	// same values.
	Sexes []*SexNode
}

func NewMultipleSexesWarning

func NewMultipleSexesWarning(individual *IndividualNode, sexes []*SexNode) *MultipleSexesWarning

func (*MultipleSexesWarning) Name

func (w *MultipleSexesWarning) Name() string

func (*MultipleSexesWarning) String

func (w *MultipleSexesWarning) String() string

type NameFormat

type NameFormat string

NameFormat describes how an individuals name should be formatted.

The format is a string that contains placeholders and works similar to fmt.Printf where placeholders represent different components of the name:

%% "%"
%f GivenName
%l Surname
%m SurnamePrefix
%p Prefix
%s Suffix
%t Title

Each of the letters may be in upper case to convert the name part to upper case also. Whitespace before, after and between name components will be removed:

name.Format("%l, %f")     // "Smith, Bob"
name.Format("%f %L")      // "Bob SMITH"
name.Format("%f %m (%l)") // "Bob (Smith)"
const (
	// This is the written format, also used by String().
	NameFormatWritten NameFormat = "%t %p %f %m %l %s"

	// This is the style used in GEDCOM NAME nodes. It is used in GedcomName().
	//
	// It should be noted that while the formatted name is valid GEDCOM, it
	// cannot be reverse back into its individual name parts.
	NameFormatGEDCOM NameFormat = "%t %p %f %m /%l/ %s"

	// NameFormatIndex is appropriate for showing names that are indexed by
	// their surname, such as "Smith, Bob"
	NameFormatIndex NameFormat = "%m %l, %t %p %f %s"
)

NameFormat constants can be used with NameNode.Format.

func NewNameFormatByName

func NewNameFormatByName(name string) (NameFormat, bool)

NewNameFormatByName returns one of the NameFormat constants.

The name is the lowercase name of the constant without the prefix. For example, "NameFormatWritten" would have the name "written".

It will return the original name and false if the name is not known. This allows custom formats to be passed through like:

NewNameFormatByName("gedcom") // "%t %p %f %m /%l/ %s", true
NewNameFormatByName("%L %f")  // "%L %f", false

type NameNode

type NameNode struct {
	*SimpleNode
}

NameNode represents all the parts that make up a single name. An individual may have more than one name, each one would be represented by a NameNode.

func NewNameNode

func NewNameNode(value string, children ...Node) *NameNode

func (*NameNode) Format

func (node *NameNode) Format(format NameFormat) string

Format returns a formatted name.

There are some common formats described with the NameFormat constants. See NameFormat for a full description.

func (*NameNode) GedcomName

func (node *NameNode) GedcomName() (name string)

GedcomName returns the simplified GEDCOM name often used also as the value for the NAME node.

The only difference between this as String() is that the surname is encapsulated inside forward slashes like:

Sir Elliot Rupert /Chance/ Sr

Even this uses the NameFormatGEDCOM it may return a different value from Format(NameFormatGEDCOM) because any empty surnames will be removed.

func (*NameNode) GivenName

func (node *NameNode) GivenName() string

GivenName is the given or earned name used for official identification of a person. It is also commonly known as the "first name".

func (*NameNode) Prefix

func (node *NameNode) Prefix() string

func (*NameNode) String

func (node *NameNode) String() string

String returns all name components in the format that would be written like "Grand Duke Bob Smith Esq.". It specifically uses NameFormatWritten.

func (*NameNode) Suffix

func (node *NameNode) Suffix() string

func (*NameNode) Surname

func (node *NameNode) Surname() string

Surname is a family name passed on or used by members of a family.

func (*NameNode) SurnamePrefix

func (node *NameNode) SurnamePrefix() string

func (*NameNode) Title

func (node *NameNode) Title() string

func (*NameNode) Type

func (node *NameNode) Type() NameType

type NameType

type NameType string

func (NameType) String

func (t NameType) String() string

Is usually blank for the primary name

type NicknameNode

type NicknameNode struct {
	*SimpleNode
}

NicknameNode is a descriptive or familiar that is used instead of, or in addition to, one's proper name.

func NewNicknameNode

func NewNicknameNode(value string, children ...Node) *NicknameNode

NewNicknameNode creates a new NICK node.

type Node

type Node interface {
	fmt.Stringer
	NodeCopier
	Noder
	GEDCOMLiner
	GEDCOMStringer

	// The node itself.
	RawSimpleNode() *SimpleNode
	Tag() Tag
	Value() string
	Pointer() string

	// Equals performs a shallow comparison between two nodes.
	//
	// The implementation is different depending on the types of nodes being
	// compared. You should see the specific documentation for the Node.
	//
	// That being said, as a general rule is fair to assume that in most cases
	// the following things take place:
	//
	// 1. The default logic, if not overridden by the node is to consider nodes
	// equal if they have the all of the same; tag, value and pointer.
	//
	// 2. If either side is nil (or both) the nodes are never considered equal.
	//
	// 3. If both nodes are different types they are not considered equal.
	//
	// 4. Despite being a shallow equality test some nodes need to check the
	// equality some children to make a determination. For example, a BirthNode
	// is always equal to another BirthNode, even if they contain different
	// children or dates. Whereas a ResidenceNode is only considered equal if
	// they both contain at least one DateNode with exactly the same value.
	//
	// The rules above play heavily into the logic of other things, such as
	// CompareNodes.
	Equals(node2 Node) bool
}

func DeepCopy

func DeepCopy(node Node) Node

DeepCopy returns a new node with all recursive children also duplicated.

func EqualityMergeFunction

func EqualityMergeFunction(left, right Node) Node

EqualityMergeFunction is a MergeFunction that will return a merged node if the node are considered equal (with Equals). This is probably the most generic case when doing general merges.

func Filter

func Filter(root Node, fn FilterFunction) Node

Filter returns a new nest node structure by recursively filtering all children based on a callback FilterFunction.

See FilterFunction for the implementation details of fn.

There are several other functions that can be used as filters including; WhitelistTagFilter, BlacklistTagFilter and OfficialTagFilter.

Some nodes, such as an IndividualNode or FamilyNode cannot be created without being attached to a document. Filter will attach these to a new document which can be accessed through their respective Document() method.

func First

func First(nodes interface{}) Node

First returns the first non-nil node of nodes. If the length of nodes is zero or a non-nil value is not found then nil is returned.

First is useful in combination with other functions like:

birth := First(individual.Births())

func Last

func Last(nodes interface{}) Node

Last returns the last non-nil node of nodes. If the length of nodes is zero or a non-nil value is not found then nil is returned.

Last is useful in combination with other functions like:

death := Last(individual.Deaths())

func MergeNodes

func MergeNodes(left, right Node) (Node, error)

MergeNodes returns a new node that merges children from both nodes.

If either of the nodes are nil, or they are not the same tag an error will be returned and the result node will be nil.

The node returned and all of the merged children will be created as new nodes as to not interfere with the original input.

func NewNode

func NewNode(tag Tag, value, pointer string, children ...Node) Node

NewNode creates a node with no children. It is also the correct way to create a shallow copy of a node.

If the node tag is recognised as a more specific type, such as *DateNode then that will be returned. Otherwise a *SimpleNode will be used.

func NodeCondition

func NodeCondition(condition bool, node1, node2 Node) Node

NodeCondition is a convenience method for inline conditionals.

type NodeCopier

type NodeCopier interface {
	// ShallowCopy returns a new node with all the same properties, but no
	// children.
	//
	// You should assume that it is not safe to use ShallowCopy() on a nil
	// value.
	//
	// See DeepCopy() for copying nodes recursively.
	ShallowCopy() Node
}

type NodeDiff

type NodeDiff struct {
	// Left or Right may be nil, but never both.
	//
	// Since nodes may be compared from different documents and have different
	// raw values it's important to retain the left and right nodes. Make sure
	// when displaying or traversing your data you are showing the correct side.
	//
	// The Left and Right retain their original children as well so you an still
	// perform all the same operations on the nodes inside a NodeDiff.
	Left, Right Node

	// Children represents each of the compared child nodes from both sides. See
	// CompareNodes for a full explanation.
	Children []*NodeDiff
}

NodeDiff is used to describe the difference when two nodes are compared.

It is important to understand the semantics of what a "difference" (and therefore "equality") means for GEDCOM data as this heavily factors into influencing the way the algorithms and returned values represent.

GEDCOM files are quite unbounded when it comes to events and facts. For example, it's common to have multiple birth events (BIRT tag) for the same individual. This is not necessarily a bug in the data but rather a way to describe two possible known birth dates or locations.

The order of nodes in the GEDCOM file is also insignificant. That is to say that a birth event that appears before another birth event is no more important than any other tag, including other birth events.

Child nodes belonging to two parent nodes that are considered equal (by using Equals) can be merged. For example, all of the following examples are considered to be equal because the BirthNode.Equals regards all BirthNodes as equal (see specific documentation for a complete explanation):

BIRT               |  BIRT               |  BIRT
  DATE 3 SEP 1943  |    DATE 3 SEP 1943  |    PLAC England
BIRT               |    PLAC England     |    DATE 3 SEP 1943
  PLAC England     |                     |  BIRT

However, the semantics of Equals is quite different for other types of nodes. For example ResidenceNodes are considered equal only if they have the same date, as it wouldn't make sense (or just be plain wrong) to merge children from separate Residence events.

func CompareNodes

func CompareNodes(left, right Node) *NodeDiff

CompareNodes returns the recursive comparison of two root nodes. To properly understand the motivations and expected result you should first understand NodeDiff before you continue reading.

The returned NodeDiff will have root node assigned to the Left and Right, even if they are non-equal values. This is the only case where this is possible. It was decided to do it this way to allow comparing of nodes that often have a different root node value (like individuals with different pointers), and also keep the output from CompareNodes consistent.

If you need to be sure the root node are the equal after the comparison, you can use (this is also nil safe):

d.Left.Equals(d.Right)

The algorithm to perform the diff is actually very simple:

1. It creates an empty NodeDiff instance.

2. It traverses down the left creating all the respective child nodes as it goes. Before it adds a child node at any level it will always check previously created nodes at the same level for equality. If it finds a match it will redirect the traversal through this parent rather than creating a new child.

3. It traverses the right side with the same rules. The only real difference is that it will assign the node to the right side on a match/new child instead of the left.

Here are two individuals that have slightly different data:

0 INDI @P3@           |  0 INDI @P4@
1 NAME John /Smith/   |  1 NAME J. /Smith/
1 BIRT                |  1 BIRT
2 DATE 3 SEP 1943     |  2 DATE Abt. Sep 1943
1 DEAT                |  1 BIRT
2 PLAC England        |  2 DATE 3 SEP 1943
1 BIRT                |  1 DEAT
2 DATE Abt. Oct 1943  |  2 DATE Aft. 2001
                      |  2 PLAC Surry, England

In this case both of the root nodes are different (because of the different pointer values). The returned left and right will have the respective root nodes.

Here is the output, rendered with NodeDiff.String():

LR 0 INDI @P3@
L  1 NAME John /Smith/
LR 1 BIRT
L  2 DATE Abt. Oct 1943
LR 2 DATE 3 SEP 1943
 R 2 DATE Abt. Sep 1943
LR 1 DEAT
L  2 PLAC England
 R 2 DATE Aft. 2001
 R 2 PLAC Surry, England
 R 1 NAME J. /Smith/

func (*NodeDiff) IsDeepEqual

func (nd *NodeDiff) IsDeepEqual() bool

IsDeepEqual returns true if the current NodeDiff and all of its children have been assigned to the left and right.

The following diff (rendered with String) shows each NodeDiff and if it would be considered DeepEqual:

LR 0 INDI @P3@           | false
LR 1 NAME John /Smith/   | true
LR 1 BIRT                | false
L  2 DATE Abt. Oct 1943  | false
LR 2 DATE 3 SEP 1943     | true
 R 2 DATE Abt. Sep 1943  | false
LR 1 DEAT                | true
LR 2 PLAC England        | true
 R 1 NAME J. /Smith/     | false

func (*NodeDiff) LeftNode

func (nd *NodeDiff) LeftNode() Node

LeftNode returns the flattening Node value that favors the left side.

To favor means to return the Left value when both the Left and Right are set.

func (*NodeDiff) RightNode

func (nd *NodeDiff) RightNode() Node

RightNode returns the flattening Node value that favors the right side.

To favor means to return the Left value when both the Left and Right are set.

func (*NodeDiff) Sort

func (nd *NodeDiff) Sort()

Sort mutates the existing NodeDiff to order the nodes recursively.

Nodes are first sorted by their tag group. The tag group places some tags are specific points, such as the name as the top, and the burial after the death event.

For nodes in the same tag group they are then ordered by date based on the Yearer interface.

If nodes do not implement Yearer, or the values are equal it will then use the third level of ordering which is the node Value itself.

Sort uses SliceStable to make the results more predicable and also ensures that nodes remain in the same order if all three levels are the same.

func (*NodeDiff) String

func (nd *NodeDiff) String() string

String returns a readable comparison of nodes, like:

LR 0 INDI @P3@
L  1 NAME John /Smith/
LR 1 BIRT
L  2 DATE Abt. Oct 1943
LR 2 DATE 3 SEP 1943
 R 2 DATE Abt. Sep 1943
LR 1 DEAT
L  2 PLAC England
 R 2 DATE Aft. 2001
 R 2 PLAC Surry, England
 R 1 NAME J. /Smith/

The L/R/LR represent which side has the node, followed by the GEDCOM indent and node line.

There is a special case if both root nodes are different. They will be displayed as two separate lines even though they both belong to the same NodeDiff:

LR 0 INDI @P3@
LR 0 INDI @P4@

You should not rely on this format to be machine readable as it may change in the future.

func (*NodeDiff) Tag

func (nd *NodeDiff) Tag() Tag

type NodeSet

type NodeSet map[Node]bool

NodeSet is a collection of unique nodes.

The nodes are considered unique only by their address, not by any other measure of equality.

func (NodeSet) Add

func (ns NodeSet) Add(node Node)

Add a node to the set.

The nodes are considered unique only by their address, not by any other measure of equality.

Attempting to add a node that already exists will have no effect.

func (NodeSet) Has

func (ns NodeSet) Has(node Node) bool

Has returns true if a node exists in the set.

type Noder

type Noder interface {
	// Nodes returns any child nodes.
	Nodes() Nodes

	// AddNode will add a child to this node.
	//
	// There is no restriction on whether a node is not allow to have children
	// so you can expect that no error can occur.
	//
	// AddNode will always append the child at the end, even if there is is an
	// exact child that already exists. However, the order of node in a GEDCOM
	// file is almost always irrelevant.
	AddNode(node Node)

	// SetNodes replaces all of the child nodes.
	SetNodes(nodes Nodes)

	DeleteNode(node Node) bool
}

Noder allows an instance to have child nodes.

type Nodes

type Nodes []Node

func Compound

func Compound(nodes ...interface{}) Nodes

Compound is a easier way to join a collection of nodes. The input type is flexible to allow the following types:

nil
Node
Nodes

If any of the inputs are not one of the above types then a panic is raised.

Using nil as a Node or including nil as one of the elements for Nodes will be ignored, so you should not receive any nil values in the output.

func Flatten

func Flatten(node Node) Nodes

Flatten returns a slice of nodes from a tree structure.

The original nodes will not be modified, but they will also not be copied. Any changes to the result nodes will directly affect the original tree structure. This also means that the nodes returned will have the references to their children as before.

Flatten makes no guarantees about the same node appearing more than once if it also appears more then once in the original structure. Be careful not to pass in structures that have circular references between nodes.

If the input is nil then the result will also be nil.

If you would like a completely new copy of the data you can use:

Flatten(DeepCopy(node))

func MergeNodeSlices

func MergeNodeSlices(left, right Nodes, mergeFn MergeFunction) Nodes

MergeNodeSlices merges two slices based on the mergeFn.

The MergeFunction must not be nil, but may return nil. See MergeFunction for usage.

The left and right may contain zero elements or be nil, these mean the same thing.

MergeNodeSlices makes some guarantees about the result:

1. The result slice will contain at least the length of the greatest length of left and right. So if len(left) = 3 and len(right) = 5 then the result slice will have a minimum of 5 items. If both slices are empty or nil the minimum length will also be zero.

2. The result slice will not contain more elements than the sum of the lengths of the left and right. So if len(left) = 3 and len(right) = 5 then the largest possible slice returned is 8.

3. All of the nodes returned will be deep copies of the original nodes so it is safe to manipulate the result in any way without affecting the original input slices.

4. Any element from the left or right may only be merged once. That is to say that if a merge happens between a left and right node that the result node cannot be merged again.

5. Merges can only happen between a node on the left with a node on the right. Even if two nodes in the left could be merged they will not be. The same goes for all of the elements in the right slice.

func NewNodes

func NewNodes(ns interface{}) (nodes Nodes)

func NodesWithTag

func NodesWithTag(node Node, tag Tag) (result Nodes)

NodesWithTag returns the zero or more nodes that have a specific GEDCOM tag. If the provided node is nil then an empty slice will always be returned.

If the node is nil the result will also be nil.

func NodesWithTagPath

func NodesWithTagPath(node Node, tagPath ...Tag) Nodes

NodesWithTagPath return all of the nodes that have an exact tag path. The number of nodes returned can be zero and tag must match the tag path completely and exactly.

birthPlaces := NodesWithTagPath(individual, TagBirth, TagPlace)

If the node is nil the result will also be nil.

func (Nodes) CastTo

func (nodes Nodes) CastTo(t interface{}) interface{}

CastTo creates a slice of a more specific node type.

All Nodes must be the same type and the same as the provided t.

func (Nodes) FlattenAll

func (nodes Nodes) FlattenAll(result Nodes)

FlattenAll works as Flatten with multiple inputs that are returned as a single slice.

If any of the nodes are nil they will be ignored.

type NoteNode

type NoteNode struct {
	*SimpleNode
}

NoteNode represents additional information provided by the submitter for understanding the enclosing data.

func NewNoteNode

func NewNoteNode(value string, children ...Node) *NoteNode

NewNoteNode creates a new NOTE node.

type Number

type Number int

Number can be used to transform a number into another representation.

Even though a Number is an alias for int you should use the provided function Int() to get its value in case the underlying type changes in the future.

It should also be noted that Number only supports integer values and many of the conversions or representations will only work with positive values. Some functions may also have more specific ranges.

func NewNumberWithInt

func NewNumberWithInt(n int) Number

NewNumberWithInt is the preferred way to create a new Number.

While it is possible to cast the value directly to a Number, using this constructor is safer if the underlying type of Number changes.

func (Number) Int

func (n Number) Int() int

Int returns the true value of the number with no loss of precision.

func (Number) LowerRoman

func (n Number) LowerRoman() (string, error)

LowerRoman returns the lowercase Roman numerals, like "vii".

LowerRoman works with exactly the same rules and constraints as UpperRoman.

func (Number) UpperRoman

func (n Number) UpperRoman() (string, error)

UpperRoman returns uppercase Roman numerals, like "VII".

The acceptable range is between 0 and 10000. Zero is a special case that will return "N", an abbreviation for "nulla". While it is possible to represent numbers number larger than 10000 it would get very cumbersome since each thousand would need an extra "M".

If the number is outside of the acceptable range then an empty string is returned with an error.

Also see LowerRoman.

type ObjectMapper

type ObjectMapper interface {
	ObjectMap() map[string]interface{}
}

ObjectMapper allows objects to be represented a map. This is important when serializing and examining objects.

type PhoneticVariationNode

type PhoneticVariationNode struct {
	*SimpleNode
}

PhoneticVariationNode represents a phonetic variation of a superior text string.

New in Gedcom 5.5.1.

func NewPhoneticVariationNode

func NewPhoneticVariationNode(value string, children ...Node) *PhoneticVariationNode

NewPhoneticVariationNode creates a new FONE node.

func (*PhoneticVariationNode) Type

func (node *PhoneticVariationNode) Type() *TypeNode

type PlaceNode

type PlaceNode struct {
	*SimpleNode
}

PlaceNode represents a jurisdictional name to identify the place or location of an event.

The original specification was derived from http://wiki-en.genealogy.net/GEDCOM/PLAC-Tag

func NewPlaceNode

func NewPlaceNode(value string, children ...Node) *PlaceNode

NewPlaceNode creates a new PLAC node.

The original specification was derived from http://wiki-en.genealogy.net/GEDCOM/PLAC-Tag

func Places

func Places(nodes ...Node) (result []*PlaceNode)

Places returns the shallow PlaceNodes for each of the input nodes.

Dates is safe to use with nil nodes.

func (*PlaceNode) Country

func (node *PlaceNode) Country() string

Country is the forth part of the JurisdictionalName().

Country will only return a non-empty response if the JurisdictionalName is exactly in the form of "Name,County,State,Country" or the country can be identified from the list of Countries.

func (*PlaceNode) County

func (node *PlaceNode) County() string

County is the second part of the JurisdictionalName().

County will only return a non-empty response if the JurisdictionalName is exactly in the form of "Name,County,State,Country".

func (*PlaceNode) Format

func (node *PlaceNode) Format() *FormatNode

Format shows the jurisdictional entities that are named in a sequence from the lowest to the highest jurisdiction.

The jurisdictions are separated by commas, and any jurisdiction's name that is missing is still accounted for by a comma.

When a PLAC.FORM structure is included in the HEADER of a GEDCOM transmission, it implies that all place names follow this jurisdictional format and each jurisdiction is accounted for by a comma, whether the name is known or not.

When the PLAC.FORM is subordinate to an event, it temporarily overrides the implications made by the PLAC.FORM structure stated in the HEADER. This usage is not common and, therefore, not encouraged. It should only be used when a system has over-structured its place-names.

See JurisdictionalName() for a more reliable way to determine the Format.

func (*PlaceNode) JurisdictionalEntities

func (node *PlaceNode) JurisdictionalEntities() (string, string, string, string)

JurisdictionalEntities returns the name, county, state and country.

See JurisdictionalName() for a full explanation.

func (*PlaceNode) JurisdictionalName

func (node *PlaceNode) JurisdictionalName() string

JurisdictionalName determines the best name to use to identify the jurisdiction entities.

If Format() is not empty then this is the best jurisdictional name to use because it should be in the form of "Name,County,State,Country". Otherwise it will have to fallback to using the PlaceNode value.

The PlaceNode value does not have to follow any standards but it's common for it to have the same value as the Format would have had.

If the jurisdictional name is not exactly in the form of "Name,County,State,Country" (including more or less components) then it cannot be split. In this case the Name component is the entire name and the County, State and Country will be empty.

func (*PlaceNode) Map

func (node *PlaceNode) Map() *MapNode

func (*PlaceNode) Name

func (node *PlaceNode) Name() string

Name is the first part of the JurisdictionalName().

If the JurisdictionalName is not in the exact form of "Name,County,State,Country" then Name will return the entire jurisdictional name.

func (*PlaceNode) Notes

func (node *PlaceNode) Notes() []*NoteNode

func (*PlaceNode) PhoneticVariations

func (node *PlaceNode) PhoneticVariations() []*PhoneticVariationNode

PhoneticVariations of the place name are written in the same form as was the place name used in the superior PlaceNode value, but phonetically written using the method indicated by the subordinate Type.

For example if hiragana was used to provide a reading of a name written in kanji, then the Type value would indicate kana.

See PhoneticVariationTypeHangul and PhoneticVariationTypeKana.

func (*PlaceNode) RomanizedVariations

func (node *PlaceNode) RomanizedVariations() []*RomanizedVariationNode

RomanizedVariations of the place name are written in the same form prescribed for the place name used in the superior PlaceNode context.

The method used to romanize the name is indicated by the Value of the subordinate Type().

For example if romaji was used to provide a reading of a place name written in kanji, then the Type subordinate to the RomanizedVariationNode would indicate "romaji".

func (*PlaceNode) State

func (node *PlaceNode) State() string

State is the third part of the JurisdictionalName().

State will only return a non-empty response if the JurisdictionalName is exactly in the form of "Name,County,State,Country".

type Placer

type Placer interface {
	Places() []*PlaceNode
}

type Progress

type Progress struct {
	// Done is how many operations have been completed so far. If Done is zero
	// you should add the value of Add instead.
	Done int64

	// Add represents how many operations were performed since the last
	// operation. It is possible for both the Done and Add to be zero. This
	// means the progress did not change. Add may also be a negative value.
	Add int64

	// Total is the expected number of total operations. Total may change
	// throughout the processing to be larger to smaller that any previous
	// value.
	//
	// If total is zero, you should not change the existing total value.
	Total int64
}

Progress contains information about the progress of an operation.

Progress will consist of a value for Add or Done. It will also optionally contain a value for Total.

type ResidenceNode

type ResidenceNode struct {
	*SimpleNode
}

ResidenceNode is the act of dwelling at an address for a period of time.

func NewResidenceNode

func NewResidenceNode(value string, children ...Node) *ResidenceNode

NewResidenceNode creates a new RESI node.

func (*ResidenceNode) Dates

func (node *ResidenceNode) Dates() DateNodes

Dates returns zero or more dates associated with the residence.

When more than one date is returned you should not assume that the order has any significance for the importance of the dates.

If the node is nil the result will also be nil.

func (*ResidenceNode) Equals

func (node *ResidenceNode) Equals(node2 Node) bool

Equal tests if two residence events are the same.

Two residence events are considered equal if they both contain the same date. If either or both contain more than one date only a single date must match both sides.

If either node is nil (including both) or if the right side is not a ResidenceNode then false is always returned.

func (*ResidenceNode) Years

func (node *ResidenceNode) Years() float64

Years returns the Years value of the minimum date node in the node.

type RomanizedVariationNode

type RomanizedVariationNode struct {
	*SimpleNode
}

RomanizedVariationNode represents a romanized variation of a superior text string.

New in Gedcom 5.5.1.

func NewRomanizedVariationNode

func NewRomanizedVariationNode(value string, children ...Node) *RomanizedVariationNode

NewRomanizedVariationNode creates a new ROMN node.

func (*RomanizedVariationNode) Type

func (node *RomanizedVariationNode) Type() *TypeNode

type SexNode

type SexNode struct {
	*SimpleNode
}

Indicates the sex of an individual--male or female.

func NewSexNode

func NewSexNode(value string) *SexNode

NewSexNode returns a node that represents a known or unknown gender. You should use one of the constants; SexMale, SexFemale or SexUnknown.

func (*SexNode) IsFemale

func (node *SexNode) IsFemale() bool

func (*SexNode) IsMale

func (node *SexNode) IsMale() bool

func (*SexNode) IsUnknown

func (node *SexNode) IsUnknown() bool

func (*SexNode) OwnershipWord

func (node *SexNode) OwnershipWord() string

func (*SexNode) String

func (node *SexNode) String() string

type SiblingsBornTooCloseWarning

type SiblingsBornTooCloseWarning struct {
	SimpleWarning
	Sibling1, Sibling2 *ChildNode
}

func NewSiblingsBornTooCloseWarning

func NewSiblingsBornTooCloseWarning(sibling1, sibling2 *ChildNode) *SiblingsBornTooCloseWarning

func (*SiblingsBornTooCloseWarning) Name

func (*SiblingsBornTooCloseWarning) String

func (w *SiblingsBornTooCloseWarning) String() string

type SimilarityOptions

type SimilarityOptions struct {
	// MinimumSimilarity is the threshold for matching individuals as the same
	// person. This is used to compare only the individual (not surrounding
	// family) like spouses and children. See DefaultMinimumSimilarity.
	MinimumSimilarity float64

	// MinimumWeightedSimilarity is the threshold for whether two individuals
	// should be the seen as the same person when the surrounding immediate
	// family is taken into consideration. See WeightedSimilarity().
	MinimumWeightedSimilarity float64

	// MaxYears is the maximum error margin (in years) that two dates can be
	// different before they are assume to not be the same. See
	// DefaultMaxYearsForSimilarity.
	MaxYears float64

	// All four of these must sum up to 1.0.
	IndividualWeight, ParentsWeight, SpousesWeight, ChildrenWeight float64

	// NameToDateRatio describes the ratio between the weight of the individuals
	// name to their combined estimated birth and death dates. A value of 0.0
	// would not take into account the individuals name at all, whereas 1.0
	// would not take into account any dates. A sensible default is 0.5.
	NameToDateRatio float64

	// JaroBoostThreshold and JaroPrefixSize are used by the JaroWinkler
	// function. They affect the properties of names are compared. The default
	// values for each of these can be found in the constants
	// DefaultJaroWinklerBoostThreshold and DefaultJaroWinklerPrefixSize. Their
	// values have been chosen with gedcomtune.
	JaroBoostThreshold float64
	JaroPrefixSize     int

	// PreferPointerAbove controls if two individuals should be considered a
	// match by their pointer value.
	//
	// The default value is DefaultMinimumSimilarity which means that the
	// individuals will be considered a match if they share the same pointer and
	// hit the same default minimum similarity.
	//
	// A value of 1.0 would have to be a perfect match to be considered equal on
	// their pointer, this is the same as disabling the feature.
	//
	// A value of 0.0 would mean that it always trusts the pointer match, even
	// if the individuals are nothing alike.
	//
	// PreferPointerAbove makes sense when you are comparing documents that have
	// come from the same base and retained the pointers between individuals of
	// the existing data.
	PreferPointerAbove float64
}

SimilarityOptions is used by all of the functions that calculate the similarity or otherwise compare entities. This struct allows many things to be tweaked. However, not all of the values are used by all of the functions.

Use NewSimilarityOptions() to choose sensible defaults that are best for most general cases.

func NewSimilarityOptions

func NewSimilarityOptions() SimilarityOptions

NewSimilarityOptions returns sensible defaults that are used around many of the similarity functions.

func (SimilarityOptions) String

func (options SimilarityOptions) String() string

String renders the options as a comma-separated string.

type SimpleNode

type SimpleNode struct {
	// contains filtered or unexported fields
}

SimpleNode is used as the default node type when there is no more appropriate or specific type to use.

func (*SimpleNode) AddNode

func (node *SimpleNode) AddNode(n Node)

func (*SimpleNode) DeleteNode

func (node *SimpleNode) DeleteNode(n Node) (didDelete bool)

func (*SimpleNode) Equals

func (node *SimpleNode) Equals(node2 Node) bool

Equals compares two nodes for value equality.

1. If either or both nodes are nil then false is always returned. 2. Nodes are compared only by their root value (shallow) meaning any value for the child nodes is ignored. 3. The document the node belongs to is not taken into consideration to be able to compare nodes by value across different documents. 4. A node is considered to have the same value (and therefore be equal) is both nodes share the all of the same tag, value and pointer.

func (*SimpleNode) GEDCOMLine

func (node *SimpleNode) GEDCOMLine(indent int) string

GEDCOMLine converts a node into its single line GEDCOM value. It is used several places including the actual Encoder.

GEDCOMLine, as the name would suggest, does not handle children. You can use GEDCOMString if you need the child nodes as well.

GEDCOMLine will not work with a nil value. You can use the package GEDCOMLine function to gracefully handle nils.

The indent will only be included if it is at least 0. If you want to use GEDCOMLine to compare the string values of nodes or exclude the indent you should use the NoIndent constant.

func (*SimpleNode) GEDCOMString

func (node *SimpleNode) GEDCOMString(indent int) string

GEDCOMString is the recursive version of GEDCOMLine. It will render a node and all of its children (if any) as a multi-line GEDCOM string.

GEDCOMString will not work with a nil value. You can use the package GEDCOMString function to gracefully handle nils.

The indent will only be included if it is at least 0. If you want to use GEDCOMString to compare the string values of nodes or exclude the indent you should use the NoIndent constant.

func (*SimpleNode) MarshalJSON

func (node *SimpleNode) MarshalJSON() ([]byte, error)

func (*SimpleNode) Nodes

func (node *SimpleNode) Nodes() Nodes

If the node is nil the result will also be nil.

func (*SimpleNode) ObjectMap

func (node *SimpleNode) ObjectMap() map[string]interface{}

func (*SimpleNode) Pointer

func (node *SimpleNode) Pointer() string

If the node is nil the result will be an empty string.

func (*SimpleNode) RawSimpleNode

func (node *SimpleNode) RawSimpleNode() *SimpleNode

func (*SimpleNode) SetNodes

func (node *SimpleNode) SetNodes(nodes Nodes)

SetNodes replaces all of the child nodes.

You can use SetNodes(nil) to remove all child nodes.

func (*SimpleNode) ShallowCopy

func (node *SimpleNode) ShallowCopy() Node

ShallowCopy returns a new node that has the same properties as the input node without any children.

If the input node is nil then nil is also returned.

func (*SimpleNode) String

func (node *SimpleNode) String() string

If the node is nil the result be an empty string.

func (*SimpleNode) Tag

func (node *SimpleNode) Tag() Tag

If the node is nil the result will be an empty tag.

func (*SimpleNode) Value

func (node *SimpleNode) Value() string

If the node is nil the result will be an empty string.

type SimpleWarning

type SimpleWarning struct {
	// contains filtered or unexported fields
}

func (*SimpleWarning) Context

func (w *SimpleWarning) Context() WarningContext

func (*SimpleWarning) SetContext

func (w *SimpleWarning) SetContext(context WarningContext)

type SourceNode

type SourceNode struct {
	*SimpleNode
}

SourceNode represents a source.

func NewSourceNode

func NewSourceNode(value, pointer string, children ...Node) *SourceNode

func (*SourceNode) Title

func (node *SourceNode) Title() string

If the node is nil the result will be an empty string.

type SpouseChildren

type SpouseChildren map[*IndividualNode]ChildNodes

SpouseChildren connects a single spouse to a set of children. The children may appear under multiple spouses. This is only useful when in combination with an individual (that would be the other spouse).

The spouse can be nil, indicating that the spouse it not known for the assigned children. You should not assume that you can also recover the other spouse from one of the keys in this map as the map is valid to be empty or to only contain a nil key.

type StringSet

type StringSet struct {
	// contains filtered or unexported fields
}

StringSet represents a slice of strings where all elements are unique (a set).

func NewStringSet

func NewStringSet(elements ...string) *StringSet

NewStringSet creates a new StringSet that is initialized with zero or more elements.

See Add() for semantics.

func (*StringSet) Add

func (ss *StringSet) Add(elements ...string) *StringSet

Add will append zero more strings to the set. If any of the elements already exist in the set they will be ignored.

func (*StringSet) Has

func (ss *StringSet) Has(element string) bool

Has returns true if the string exists in the set.

func (*StringSet) Intersects

func (ss *StringSet) Intersects(ss2 *StringSet) bool

Intersects returns true if the two sets contain at least one value that is the same.

func (*StringSet) Iterate

func (ss *StringSet) Iterate(fn func(string) bool)

Iterate will iterate all items, similar to a "for range".

The order of the elements will change between successive iterations.

The iteration will stop if the fn returns false.

func (*StringSet) Len

func (ss *StringSet) Len() (len int)

Len returns the number of elements in the set.

func (*StringSet) String

func (ss *StringSet) String() string

String returns all of the items sorted, in the form of:

(bar,foo)

func (*StringSet) Strings

func (ss *StringSet) Strings() (elements []string)

Strings returns all the values as a slice of strings. The result is always sorted.

type SurroundingSimilarity

type SurroundingSimilarity struct {
	// ParentsSimilarity is the similarity of the fathers and mothers of the
	// individual. Each missing parent will be given 0.5. If both parents are
	// missing the parent similarity will also be 0.5.
	//
	// An individual can have zero or more pairs of parents, but only a single
	// ParentsSimilarity is provided. The ParentsSimilarity is the highest value
	// when each of the parents are compared with the other parents of the other
	// individual.
	ParentsSimilarity float64

	// IndividualSimilarity is the same as Individual.Similarity().
	IndividualSimilarity float64

	// SpousesSimilarity is the similarity of the spouses is compared with
	// IndividualNodes.Similarity() which is designed to compare several
	// individuals at once. It also handles comparing a different number of
	// individuals on either side.
	SpousesSimilarity float64

	// ChildrenSimilarity also uses IndividualNodes.Similarity() but without
	// respect to their parents (which in this case would be the current
	// individual and likely one of their spouses).
	//
	// It is done this way as to not skew the results if any particular parent
	// is unknown or the child is connected to a different spouse.
	ChildrenSimilarity float64

	// Options affects the weights and other aspects of the normalised
	// similarity metrics.
	Options SimilarityOptions
}

SurroundingSimilarity describes different aspects of the similarity of an individual by its immediate relationships; parents, spouses and children.

func NewSurroundingSimilarity

func NewSurroundingSimilarity(parentsSimilarity, individualSimilarity, spousesSimilarity, childrenSimilarity float64) *SurroundingSimilarity

NewSurroundingSimilarity creates a surrounding similarity using default similarity options. You can modify or replace the Options after instantiation.

func (SurroundingSimilarity) String

func (s SurroundingSimilarity) String() string

String returns the WeightedSimilarity -- a number between 0.0 and 1.0.

The WeightedSimilarity is affected by Options.

func (SurroundingSimilarity) WeightedSimilarity

func (s SurroundingSimilarity) WeightedSimilarity() float64

WeightedSimilarity calculates a single similarity from all of the similarity metrics with following weights:

IndividualSimilarity: 80%
ParentsSimilarity: ~6.7%
SpousesSimilarity: ~6.7%
ChildrenSimilarity: ~6.7%

type Tag

type Tag struct {
	// contains filtered or unexported fields
}

Tag is the type of node. You should not initialise a Tag instance manually, but rather use TagFromString.

func FamilySearchIDNodeTags

func FamilySearchIDNodeTags() []Tag

FamilySearchIDNodeTags returns all of the known GEDCOM tags that can be represented by a FamilySearchIDNode.

func TagFromString

func TagFromString(tag string) Tag

TagFromString returns known tag constant like TagHeader from it's raw string representation, like "HEAD". It will also return unofficial tags as well.

If the tag is not found a Tag will still be returned (and is find to use) but it will not include extra information like if it is a type of event (IsEvent).

You can check the Valid property to test if the returned Tag is known.

func Tags

func Tags() []Tag

Tags returns all of the known GEDCOM tags. This includes official and unofficial tags.

If a tag exists as a constant but is not registered here then it will not covered by tests and the conversion from a string to a tag with TagFromString will not work correctly.

func (Tag) Is

func (tag Tag) Is(tag2 Tag) bool

Is test if two tags are the same. Tags are deemed to be the same solely on their Tag attribute (the GEDCOM representation). All other properties will be ignored. This makes it safe to compare real/registered tags with ones manually created or provided from TagFromString.

func (Tag) IsEvent

func (tag Tag) IsEvent() bool

IsEvent return true if the tag is a type of event. Events can be attached to individuals or families and generally include a date and/or place in the child nodes.

It is important to note that tags thar are not seen as events can still have dates and place attached to them.

func (Tag) IsKnown

func (tag Tag) IsKnown() bool

IsKnown returns true if the tag can provide extra information like IsEvent, IsOfficial, etc. If you are using the Tag or UnofficialTag variables provided by this will always return true.

func (Tag) IsOfficial

func (tag Tag) IsOfficial() bool

IsOfficial returns true if the tag is part of the GEDCOM 5.5 standard.

func (Tag) SortValue

func (tag Tag) SortValue() int

SortValue is used when sorting tags.

The lowest SortValue should appear first.

func (Tag) String

func (tag Tag) String() string

String returned the descriptive name of the tag, like "Bar Mitzvah".

func (Tag) Tag

func (tag Tag) Tag() string

Tag returns the raw GEDCOM name for the tag, like "MARR".

type TypeNode

type TypeNode struct {
	*SimpleNode
}

TypeNode represents a further qualification to the meaning of the associated superior tag.

The value does not have any computer processing reliability. It is more in the form of a short one or two word note that should be displayed any time the associated data is displayed.

func NewTypeNode

func NewTypeNode(value string, children ...Node) *TypeNode

NewTypeNode creates a new TYPE node.

type UUID

type UUID string

func NewUUIDFromString

func NewUUIDFromString(s string) (UUID, error)

NewUUIDFromString returns a valid UUID in one of the forms:

EE13561DDB204985BFFDEEBF82A5226C
e0d4d387-618a-4713-ab3b-5fa3500b7a75

An error is returned if there is more than 32 hexadecimal characters.

func (UUID) Equals

func (uuid UUID) Equals(uuid2 UUID) bool

Equals is true only if both UUIDs represent the same value.

func (UUID) String

func (uuid UUID) String() string

String returns a lowercase, hyphenated UUID in the form of:

e0d4d387-618a-4713-ab3b-5fa3500b7a75

type UniqueIDNode

type UniqueIDNode struct {
	*SimpleNode
}

UniqueIDNode represents a _UID.

The _UID tag is what I call a Common GEDCOM Extension; a GEDCOM extension that's common to many different applications. The _UID tag is a legal GEDCOM extension; it starts with an underscore, like any vendor-defined extension should. However, it would be wrong to think of the _UID tag as a vendor- or product-specific tag. The _UID tag is not specific to any particular product or vendor. It is a common GEDCOM extension, supported by quite a few different products from different vendors.

Applications that support the _UID tag include:

  • Daub Ages!
  • Ancestral Quest (AQ)
  • Family Historian (FH)
  • Family Origins for Windows (FOW)
  • MyHeritage Family Tree Builder (FTB)
  • Family Tree Heritage
  • Family Tree Legends (FTL)
  • Genbox Family History
  • GenoPro
  • Legacy Family Tree
  • ohmiGene
  • Personal Ancestral File (PAF)
  • Reunion
  • RootsMagic (RM)

The above list was created by googling for GEDCOM files that contain the _UID tag. It probably isn't complete, but it does show that support for the _UID tag is not merely common, but also that it is supported by some of the best-known and most popular applications, such as PAF, RootsMagic and Legacy.

https://www.tamurajones.net/The_UIDTag.xhtml

func NewUniqueIDNode

func NewUniqueIDNode(value string, children ...Node) *UniqueIDNode

func (*UniqueIDNode) Checksum

func (node *UniqueIDNode) Checksum() string

Checksum returns the optional last 4 digits after the UUID.

This is what a UUID looks like in a PAF GEDCOM:

92FF8B766F327F48A256C3AE6DAE50D3A114

Notice that the _UID value is not divided into groups separated by hyphens, but represented as one long hexadecimal number. What is not immediately obvious because of its length is that the number shown is not a UUID. It cannot be an UUID, because an UUID is 32 hexadecimal digits long, and the _UID value is 36 hexadecimal digits long. When we hyphenate the number for readability, we find that there are four extra digits:

92FF8B76-6F32-7F48-A256-C3AE6DAE50D3-A114

The _UID value is a UUID followed by a checksum.

That little fact, essential to making sense of the _UID value, used to be undocumented. I once figured that out myself, but you don't have to do so, nor take my word for it. Nowadays, FamilySearch documents it, if you know where to look. The FamilySearch document GEDCOM Unique Identifiers states that it provides guidelines for the use of UUIDs, but it actually documents the format of the PAF _UID value; a 32-hexadigit UUID value followed by a 4-hexadigit checksum. That brief document includes some Windows C code, possibly the actual PAF source code. That code shows how to calculate the checksum.

PAF is a fork of Ancestral Quest, so it is no wonder that Ancestral Quest uses the same format. But it is not just Ancestral Quest that uses this format. This UUID format is the most popular one. Other applications that use the same UUID format for their _UID tag are Family Origins for Windows, Family Tree Heritage, Family Tree Legends, Genbox Family History, Legacy Family Tree, Reunion and RootsMagic.

https://www.tamurajones.net/The_UIDTag.xhtml

func (*UniqueIDNode) Equals

func (node *UniqueIDNode) Equals(node2 Node) bool

Equals returns true if both nodes have the same UUID value. The checksum (if any) is ignored.

If either nodes are nil (or both) the result will always be false.

func (*UniqueIDNode) UUID

func (node *UniqueIDNode) UUID() (UUID, error)

UUID returns the UUID component of the UniqueID.

The cross-reference identifiers are unique with a single GEDCOM file, but different GEDCOM files, are very likely to use the same identifiers for different records.

For some purposes it would be nice to have truly unique identifiers. That requires two things; some way to create globally unique identifiers, and a GEDCOM tag to carry that identifier. The Universally Unique ID (UUID) is that globally unique identifier, and _UID is the tag that carries it.

Microsoft developers known UUID as Globally Unique Identifier (GUID). What makes UUIDs so suitable is that they were developed so precisely so that everyone can generate UUIDs, without coordinating with anyone else, and still be practically sure that the generated identifier is unique.

A UUID is an 128-bit (16-byte) number, generally represented by 32 hexadecimal digits, divided into five groups, separated by hyphens, like this: 12345678-1234-1234-1234-123456789ABC.

https://www.tamurajones.net/The_UIDTag.xhtml

type UnparsableDateWarning

type UnparsableDateWarning struct {
	SimpleWarning
	Date *DateNode
}

func NewUnparsableDateWarning

func NewUnparsableDateWarning(date *DateNode) *UnparsableDateWarning

func (*UnparsableDateWarning) Name

func (w *UnparsableDateWarning) Name() string

func (*UnparsableDateWarning) String

func (w *UnparsableDateWarning) String() string

type Warner

type Warner interface {
	Warnings() Warnings
}

type Warning

type Warning interface {
	fmt.Stringer

	Name() string
	SetContext(context WarningContext)
	Context() WarningContext
}

type WarningContext

type WarningContext struct {
	Individual *IndividualNode
	Family     *FamilyNode
}

A WarningContext describes the entity the warning is attached to.

For example if the warning was an unparsable date for the birth of an individual then the Individual would be set, but not the Family.

func (WarningContext) String

func (context WarningContext) String() string

type Warnings

type Warnings []Warning

func (Warnings) Strings

func (ws Warnings) Strings() (ss []string)

func (Warnings) WriteHTMLTo

func (ws Warnings) WriteHTMLTo(w io.Writer) (int64, error)

type WifeNode

type WifeNode struct {
	*SimpleNode
	// contains filtered or unexported fields
}

WifeNode is an individual in the role as a mother and/or married woman.

func (*WifeNode) Family

func (node *WifeNode) Family() *FamilyNode

func (*WifeNode) Individual

func (node *WifeNode) Individual() *IndividualNode

func (*WifeNode) IsIndividual

func (node *WifeNode) IsIndividual(node2 *IndividualNode) bool

func (*WifeNode) Similarity

func (node *WifeNode) Similarity(other *WifeNode, options SimilarityOptions) float64

func (*WifeNode) String

func (node *WifeNode) String() string

type Yearer

type Yearer interface {
	Years() float64
}

Yearer allows some kind of date node or value to return its date representation in a number of years. This is implemented in several ways, you should read the docs for each implementation for more details.

Source Files

Directories

Path Synopsis
Gedcom2html renders a GEDCOM file into HTML pages that can be shared and published easily.
Gedcom2html renders a GEDCOM file into HTML pages that can be shared and published easily.
Gedcomdiff is a tool for comparing GEDCOM files and producing a HTML report.
Gedcomdiff is a tool for comparing GEDCOM files and producing a HTML report.
Gedcomq is a command line tool and query language for GEDCOM files heavily inspired by jq, in name and syntax.
Gedcomq is a command line tool and query language for GEDCOM files heavily inspired by jq, in name and syntax.
Gedcomtune is used to calculate the ideal weights and similarities for the main gedcom package.
Gedcomtune is used to calculate the ideal weights and similarities for the main gedcom package.
Package html is shared HTML rendering components that are shared by the other packages.
Package html is shared HTML rendering components that are shared by the other packages.
q
Package q is the gedcomq parser and engine.
Package q is the gedcomq parser and engine.
Package util contains shared functions used by several packages.
Package util contains shared functions used by several packages.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL