Skip to content

The version-independent model

Linea Codex understands GEDCOM 5.5, 5.5.1, and 7.0, but it does not keep three separate notions of what your file is. Every file you open is parsed into one internal model — a plain tree of nodes that looks the same no matter which version produced it. Editing, validation, and conversion all operate on that one model. This page explains what the model is, how parse → model → serialize works, and why routing every conversion through a single shared model is what makes results faithful and predictable.

If you have never read a raw GEDCOM line, start with How GEDCOM works — this page assumes you know what a level, tag, value, and cross-reference are.

A GEDCOM file on disk is a flat list of lines. The first thing Linea Codex does is turn that flat list into a tree — and the tree it builds is deliberately version-neutral. The same node shape represents a 5.5 birth event, a 5.5.1 birth event, and a 7.0 birth event; nothing about the node remembers which version’s text it came from.

Each node carries exactly the four pieces of information a GEDCOM line can hold, plus its children:

Part of a nodeWhat it isExample
tagthe short code naming the lineINDI, NAME, BIRT, DATE
xref (optional)a cross-reference id, present only on the lines that start a record@I1@ on 0 @I1@ INDI
value (optional)literal text, or a pointer to another record12 MAR 1832, or @F1@
childrenthe nodes nested beneath this oneGIVN and SURN under a NAME

The level number you see in the raw text isn’t stored on the node at all — it is implicit in how deep the node sits in the tree. A child is one level below its parent by definition, so the structure that the level numbers describe becomes the structure of the tree itself. (See Levels make the hierarchy for the same idea from the text side.)

The whole document is three of these trees in a container — the header, the list of records, and the trailer — together with one piece of metadata: which version the document is in. That version label is the only place the document records its GEDCOM flavour. The node trees themselves are identical in shape across all three versions; what differs between versions is which tags are valid where, not how a tag is represented. That separation is the whole point: it lets one set of code edit, search, and traverse the tree without caring about the version, while the version-specific rules live in one place and are consulted only when needed.

Three operations move data between the file on disk and the model in memory.

StepDirectionWhat happens
Parsetext → modelThe file’s encoding is decoded, the lines are tokenised, and the flat lines are assembled into the node tree.
Edit / validatemodel → modelEverything you do in the app — typing, transforms, conversion — produces a new model from the old one.
Serializemodel → textThe node tree is written back out as GEDCOM lines, in the encoding the target version requires.

Parsing is lossless by design: a node is built for every line, including lines whose tag the version doesn’t define. Custom tags, unfamiliar tags, the whole subtree beneath them — all of it lands in the tree exactly as written. Serializing walks the tree and emits one line per node. Because parse and serialize are mirror images over the same model, importing a file and exporting it again gives you back the same data — a faithful round-trip — rather than a normalised approximation of it.

This is also why Linea Codex is permissive: it does not refuse a file merely because it is non-compliant. A file with unfamiliar tags, a missing version line, or data that doesn’t fit its declared version still becomes a model; those problems are recorded as diagnostics and surfaced in the validation panel, not used as a reason to reject your data. The app warns; it does not gate. (A file that is structurally broken — lines the reader cannot tokenise, a missing header or trailer, an encoding it can’t decode — is a different case: there is no well-formed tree to build, so parsing reports a hard error instead of a partial model.)

Converting between GEDCOM versions is not a separate translator bolted onto the side. It is a transform that runs over the model — it takes the node tree, reshapes the nodes that need reshaping for the target version, and produces a new node tree, which is then serialized in the target version’s form. (For the user-facing walkthrough — the preview, the warnings, what each version supports — see Converting GEDCOM versions.)

The reshaping is expressed as a list of small, declarative steps: each step matches a place in the tree and applies an action there — rename a tag, rewrite a value, move an inline structure out into its own record, drop a construct the target can’t carry, and so on. There is one such set of steps per version hop, and the steps are the data the conversion engine runs; they aren’t opaque code.

Through a common model — never directly between two versions

Section titled “Through a common model — never directly between two versions”

The architectural rule is simple and absolute: conversion always goes through the common model, never directly from one specific version to another. Concretely, Linea Codex only knows how to take a single step between neighbouring versions:

5.5 ◄──► 5.5.1 ◄──► 7.0

5.5.1 sits in the middle as a hub. So a conversion is routed as a chain of these neighbour-steps:

ConvertRoute taken
5.5 → 5.5.1one step
5.5.1 → 7.0one step
7.0 → 5.5.1one step
5.5 → 7.0two steps, through 5.5.1 (5.5 → 5.5.1 → 7.0)
7.0 → 5.5two steps, through 5.5.1 (7.0 → 5.5.1 → 5.5)

There is deliberately no “5.5 → 7.0” translator. A distant conversion is performed by chaining the adjacent steps through the hub, each step a transform over the same model. Converting a file to the version it’s already in is the identity — nothing is reshaped — though Linea Codex still validates it on the way through.

Funnelling every conversion through a single shared model, rather than writing a direct translator for each pair of versions, is what buys the qualities the app promises.

Fewer mappings, fewer places to be wrong. With three versions there are six directed version-to-version conversions you could write by hand. Routing through the neighbour hub means only the four adjacent steps exist; the distant conversions are compositions of those. Less conversion logic means fewer corners for a bug to hide in and one consistent path whichever direction you convert.

Faithful round-trips. Because parse and serialize are inverses over the same model, and conversion is just a transform that produces a new model, the data that can be preserved is preserved structurally rather than by re-derivation. A clean, compliant file converted to another version and back comes through intact.

Custom tags survive. A tag the standard doesn’t define is parsed into the same tree as any standard tag — the model has no separate “unknown” category to strand it in. Conversion carries those nodes through unchanged: the converter never drops a tag merely because it doesn’t recognise it, because no version “owns” a custom tag in the first place. (Standard tags that exist in one version but not another are a different matter — see below.) The full story, including how 7.0 lets you document custom tags, is in When GEDCOM has no tag for it.

Best-effort, with explicit warnings — never a silent lossy downgrade. The guarantee is one-directional and honest: compliant in yields compliant out. When a construct in the source genuinely has no representation in the target — a 7.0-only standard tag converted down to 5.5, say — the conversion is best-effort: it does the most faithful thing it can and records what it had to drop or leave behind, which surfaces as a warning you see before you commit. Nothing is quietly discarded, and no downgrade is presented as lossless. This best-effort posture is the same permissiveness as the rest of the app: conversion is never blocked on your file being valid; it proceeds and tells you the truth about the result.

For which constructs each version supports — and therefore what a given conversion can and cannot carry — see the versions & conversion matrix. For why GEDCOM, and its versions, are worth caring about at all, see Why GEDCOM.


In short: one tree model is the source of truth, parsing and serializing are faithful inverses over it, and conversion is a transform that chains neighbour-steps through that model — which is exactly why your data round-trips cleanly, your custom tags survive, and every conversion tells you honestly what it could and couldn’t carry.