Closed sarnobat closed 3 years ago
Hi @sarnobat, from your previous issue #317 you should know that converting the entire document to CSV and back again isn't possible because the structure of a gendom doesn't flatten in that way. However, there is a solution for this with a modified workflow:
This is all untested and just from memory, but since your learning go it should be a good enough starting point.
// Usage:
// testdata tocsv # Export originalGedcomFile to csvFile
// testdata update # Apply csvFile to originalGedcomFile, save as updatedGedcomFile
//
// IMPORTANT: The process relies on the order of the individuals remaining the
// same (so no adding/removing individuals either). This can be improved by
// using a unique ID instead of a position.
package main
import (
"fmt"
"github.com/elliotchance/gedcom"
"os"
"encoding/csv"
)
const originalGedcomFile = "rohidekar.ged"
const csvFile = "rohidekar.csv"
// We don't want to override the original in case something goes wrong.
const updatedGedcomFile = "rohidekar-2.ged"
func main() {
// In any case we need to read the original gedcom.
document, err := gedcom.NewDocumentFromGEDCOMFile(originalGedcomFile)
if err != nil {
panic(err)
}
switch os.Args[1] {
case "tocsv":
toCSV(document)
case "update":
updateGedcom(document)
default:
panic(os.Args[1])
}
}
func check(err error) {
if err != nil {
panic(err)
}
}
func toCSV(document *gedcom.Document) {
file, err := os.Create(csvFile)
check(err)
defer file.Close()
writer := csv.NewWriter(file)
defer writer.Flush()
for _, individual := range document.Individuals() {
// Note: There can be multiple dates. This just uses the first.
// https://pkg.go.dev/github.com/elliotchance/gedcom#IndividualNode.Births
birthDate, birthPlace := individual.Birth()
err := writer.Write([]string{
// Note: There are more name parts and individuals can have multiple
// names. This just uses the first.
// https://pkg.go.dev/github.com/elliotchance/gedcom#NameNode
// https://pkg.go.dev/github.com/elliotchance/gedcom#IndividualNode.Names
individual.Name().GivenName(),
individual.Name().Surname(),
birthDate.String(),
birthPlace.String(),
})
check(err)
}
}
func updateGedcom(originalDocument *gedcom.Document) {
file, err := os.Open(csvFile)
check(err)
defer f.Close()
lines, err := csv.NewReader(f).ReadAll()
check(err)
individuals := originalDocument.Individuals()
for index, line := range lines {
givenName, surname, birthDate, birthPlace := line[0], line[1], line[2], line[3]
// Note: Not all of these will have data so you will need to use Add
// functions in these cases:
// https://pkg.go.dev/github.com/elliotchance/gedcom#IndividualNode
// Note: This destroys all the existing name parts when creating a new name.
individuals[i].Names[0] = gedcom.NewNameNode(
gedcom.NewNode(gedcom.TagGivenName, givenName),
gedcom.NewNode(gedcom.TagSurname, surname),
)
individuals[i].Births[0] = gedcom.NewBirthNode(
gedcom.NewDateNode(birthDate),
gedcom.NewPlaceNode(birthPlace),
)
}
// Save into a new gedcom file so the original isn't modified.
err := ioutil.WriteFile(updatedGedcomFile, []byte(originalDocument.String()), 0644)
check(err)
}
Thanks for the detailed info, I will come back to this.
Do you have any info on the UniqueIdentifier
fetching? I'd like to attempt a smaller program first.
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.
https://pkg.go.dev/github.com/elliotchance/gedcom#IndividualNode.UniqueIdentifiers
Example:
for _, individual := range document.Individuals() {
fmt.Println(individual.Name(), individual.UniqueIdentifiers())
}
I'm not sure that answers my question, let me try to explain: I'm able to get the identifier given the individual
object. But I'm not able to get the individual
object given the UniqueIdentifier - it returns 0
when I call Individuals().ByUniqueIdentifier("XYZ123")
. That's what my code sample is intended to demonstrate.
Is there a way to get an individual's object if you know the UniqueIdentifier (apart from iterating over the entire set)?
Yes, that should work. If you are not getting an individual back it's because:
ByPointer
instead.If either of those do not solve your issue, then show me the value you are using and the gedcom file line that its supposed to be matching.
I'm struggling to find time to play with this a bit more. I'll close it and reopen when I have further info so that it doesn't take attention away from other issues in your list. Thanks for the help so far.
I'm new to Golang and I must be doing something wrong. I'm not able to find sample code or documentation to help. Some assistance would be great.
Test Case
Full code
rohidekar.ged testcase.go testcase (native binary)
source
run instructions
(after removing the
.txt
suffixes):or run the native binary (if you are using Mac OS X)
error output:
i
isnil
so this gets printed: