Search by

korin / gedcom

sergey-timtsunyk

Lossless GEDCOM 5.5–7.0 reader, validator, converter and writer for PHP

v0.2.0 2026-11-15 17:28 UTC

This package is auto-updated.

Last update: 2026-11-15 19:14:28 UTC


README

Read, validate, convert and write GEDCOM 5.5, 5.5.1, 5.5.5 and 7.0 — without losing a single tag. Every unavoidable loss is reported.

Status: 0.2 — early development. Reading, lossless writing, editing and validation against the profiles of 5.5, 5.5.1, 5.5.5 and 7.0 work today; conversion, the typed model, GEDZIP and streaming are planned — see the specification for the roadmap and CHANGELOG.md for releases. Until 1.0 a minor release may break the API.

use Korin\Gedcom\Gedcom;

$doc = Gedcom::read('family.ged');          // version and encoding detected automatically
echo $doc->version()->value;                // "5.5.1"
echo $doc->encoding()->value;               // "Windows-1251"

$name = $doc->find('@I1@/NAME');
echo $name?->value();                       // "Анна /Коваль/"
$name?->setValue('Анна /Ковальова/');

Gedcom::write($doc, 'family.ged');          // only the changed line is rewritten

Why Korin

  • Lossless. Unknown and vendor tags (_UID, _FSFTID, …) are kept. Writing an unmodified document reproduces the input byte for byte: BOM, line endings, spacing.
  • Encodings that real files use. UTF-8, UTF-16 LE/BE, ANSEL with combining diacritics, ASCII, Windows-1250/1251/1252, CP437, CP850, MacRoman — including files that declare CHAR ANSI or contradict their own CHAR.
  • No runtime dependencies. ext-intl and ext-mbstring are used when present.
  • Tested against a shared corpus — gedcom-corpus, including the gedcom7code test files.

Requirements

PHP 8.2–8.6, 64-bit.

Installation

composer require korin/gedcom

Diagnostics

Reading reports syntax problems, validation checks the document against its version's rules. Problems are reported, not thrown, unless you ask for strict mode:

use Korin\Gedcom\ReadOptions;
use Korin\Gedcom\Validation\ValidationOptions;

foreach ($doc->diagnostics() as $d) {
    echo $d, PHP_EOL;   // KV1101 warning line 6 (HEAD/CHAR): Non-standard CHAR value; …
}

Gedcom::read('family.ged', (new ReadOptions())->withStrict());   // throws ParseException on errors

$report = Gedcom::validate($doc);   // structure, values and references of every version
$report->isValid();                  // false if there are errors
Gedcom::validate($doc, (new ValidationOptions())->withPlausibility());   // also births after deaths, cycles
echo json_encode($report);           // code, severity, message, line, path, reference

All codes are listed in docs/diagnostics.md.

Performance

Measured with PHPBench on generated, fictional 5.5.1 files (PHP 8.5, Apple M-series, no opcache):

Scenario Peak memory Time
Full read, 10 MB UTF-8 70 MB 0.32 s
Full read, 10 MB Windows-1251 105 MB 0.49 s
Full read, 50 MB UTF-8 (2.4 million lines) 426 MB 1.6 s
Preserve-mode write of 10 MB, unchanged / 10% of surnames edited 76 MB 104 ms / 121 ms

The 1.0 target for a full read of 50 MB is ≤ 512 MB and ≤ 20 s. Streaming and indexed modes for large files are planned. Run the benchmarks with composer bench. A baseline comparison with liberu-genealogy/php-gedcom is in docs/comparison.

License and trademarks

Apache-2.0. GEDCOM is a trademark of Intellectual Reserve, Inc. Korin is not affiliated with or endorsed by FamilySearch.