Validate🔗
Validation is always explicit — loading and saving never validate implicitly.
import sil_lift
# Exhaustive: a lazy stream of Problems (schema + semantic layers).
for problem in sil_lift.iter_problems("dictionary.lift"):
print(problem)
# error [dangling-ref] dictionary.lift:88 (entry apu): ref 'nope' matches ...
# Fail-fast: raises LiftValidationError on the first error-level problem.
sil_lift.validate_file("dictionary.lift")
# In-memory state (serializes first — a documented cost on large lexicons):
lex = sil_lift.load("dictionary.lift")
problems = list(lex.iter_problems())
Each Problem carries level ("error"/"warning"), a stable code, message, and an address: file, entry_id, guid, line.
The layers🔗
- RELAX NG against the LIFT 0.13 grammar (vendored from lift-standard — a byte-identical copy committed into this package).
- Ranges schema — this project's
lift-ranges-0.13.rng— over every tracked.lift-rangescompanion. - Semantic checks the grammar cannot express:
duplicate-guid,dangling-ref,range-parent,undefined-range-value,duplicate-form-lang,missing-media.
Real-world FieldWorks (FLEx) output🔗
FieldWorks systematically writes some content that strict tooling rejects. Here is sil-lift's policy, so that real lexicons validate usefully:
file://C:/...hrefs (invalid URIs) are reported as warnings (uri-not-rfc), not schema errors — the C# validator never rejected them.- Legally interleaved children (e.g.
field, note, field, notein a sense) are not flagged, working around a false positive in libxml2. - Range values are compared under Unicode NFC normalization — FLEx writes the
.liftin NFC but the.lift-rangesin NFD within the same export. - FLEx's
trait/fieldextensions insiderange-elementare reported (schema errors against the ranges schema): they are genuine spec deviations.