Edifact.Structure
1.0.0-preview.3
See the version list below for details.
dotnet add package Edifact.Structure --version 1.0.0-preview.3
NuGet\Install-Package Edifact.Structure -Version 1.0.0-preview.3
<PackageReference Include="Edifact.Structure" Version="1.0.0-preview.3" />
<PackageVersion Include="Edifact.Structure" Version="1.0.0-preview.3" />
<PackageReference Include="Edifact.Structure" />
paket add Edifact.Structure --version 1.0.0-preview.3
#r "nuget: Edifact.Structure, 1.0.0-preview.3"
#:package Edifact.Structure@1.0.0-preview.3
#addin nuget:?package=Edifact.Structure&version=1.0.0-preview.3&prerelease
#tool nuget:?package=Edifact.Structure&version=1.0.0-preview.3&prerelease
Edifact.Structure
Matches a segment stream against a message's segment table, resolving segment group nesting and repetition into a message tree with every position accounted for.
This is the layer that turns a flat list of segments into a shape: which NAD is the buyer's,
which PRI belongs to which line item, and which segment nothing in the definition could place.
It does not check element contents, code values or the envelope — that is
Edifact.Validation, which uses this. Reach for
this package directly when you want the tree and not the verdict: a viewer, a mapper, an extractor
walking to SG26[2]/SG30[1]/PRI.
Install
dotnet add package Edifact.Structure --prerelease
net8.0 and net10.0, no external dependencies.
You supply the directory
No directory data ships in this package. A compiled pack is a derivative of the UN Directory, and shipping one would make every consumer a redistributor of it. Download a release from UNECE and ingest it once:
dotnet tool install --global Edifact.Cli --prerelease
edifact ingest ~/Downloads/D96A --out ~/edifact/packs/compiled
That writes the pack to ~/edifact/packs/compiled/untdid-d96a, and puts the four ISO 9735 syntax
definitions in ~/edifact/packs/syntax beside it. Those four are the one input no ingestion can
produce — the UNTDID omits the service definitions — so they reach a machine only because the tool
ships them. Files already in that directory are left alone.
Use it
using Edifact.Core.Syntax;
using Edifact.Schema.Model;
using Edifact.Schema.Serialization;
using Edifact.Structure;
var syntax = new SyntaxPackSet("/home/me/edifact/packs/syntax");
var pack = PackReader.Read("/home/me/edifact/packs/compiled/untdid-d96a", syntax.For);
// Compiling a segment table is the expensive half — about 4 µs per segment to match afterwards —
// so a compiled message is worth keeping for as long as the pack is.
var spec = pack.TryGetMessage(new MessageKey("INVOIC", "D", "96A"))!;
var compiled = MessageCompiler.Compile(spec);
// One message: UNH through UNT, in interchange order. Edifact.Validation's EnvelopeReader is what
// splits a whole interchange into messages.
var segments = EdifactTokenizer.Tokenize(File.ReadAllText("message.edi")).Segments;
var match = StructureMatcher.Match(compiled, segments);
Console.WriteLine(match.Outcome); // Complete, Repaired or Abandoned
Console.WriteLine(match.Tree.Describe()); // the tree, indented, as the CLI's --tree prints it
foreach (var finding in match.Findings) Console.WriteLine(finding);
Walk(match.Tree.Children);
static void Walk(IEnumerable<MessageNode> nodes, int depth = 0)
{
foreach (var node in nodes)
{
Console.WriteLine($"{new string(' ', depth * 2)}{node.Label} {node.Path}");
switch (node)
{
case GroupNode group:
Walk(group.Children, depth + 1);
break;
case SegmentNode segment:
// segment.Item is the segment table entry it satisfies; segment.Segment is the
// characters it was read from.
break;
case OrphanNode orphan:
Console.WriteLine($" nothing could place this: {orphan.Reason}");
break;
}
}
}
Two contracts worth knowing
A tree always exists. Even for input that could not be matched at all, and even for a message
type the directory does not define — MessageTree.OfOrphans covers that case. Every consumer
downstream needs something to walk, and returning null on bad input would push the same conditional
into all of them. What varies is ParseOutcome and how much of the tree is orphans.
Nothing is dropped. A segment nothing could account for stays in the tree as an OrphanNode, in
the order it arrived, which is what lets the message be written back out character for character
after a round trip through
Edifact.Projection.
MessageCompiler.Compile takes an AmbiguityPolicy — which reading of an ambiguous segment table
to prefer — and an optional StructureOverrides, three facts about a position (excluded, required,
how often) as plain data. That last one is the seam
Edifact.Overlays uses to apply a trading
partner's guide without this package knowing what a guide is.
Where this sits
Edifact.Core → nothing the tokenizer, usable with no directory at all
Edifact.Schema → Core what a release says
Edifact.Structure → Core, Schema matching a segment table ← you are here
Edifact.Overlays → Structure what a guide says on top of a release
Edifact.Validation → Structure, Overlays the usual entry point
Full documentation: https://github.com/WimSuenens/EDIFACT.
Licence
Apache-2.0. See the NOTICE in this package for what the wider project is derived from and under
what terms.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Edifact.Core (>= 1.0.0-preview.3)
- Edifact.Schema (>= 1.0.0-preview.3)
-
net8.0
- Edifact.Core (>= 1.0.0-preview.3)
- Edifact.Schema (>= 1.0.0-preview.3)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Edifact.Structure:
| Package | Downloads |
|---|---|
|
Edifact.Overlays
Trading partner and subset rules layered over a base directory — tightened cardinalities, restricted code values and conditional requirements — compiled into an effective message and evaluated with a ledger saying which overlay decided what. |
|
|
Edifact.Validation
Validates an interchange against a directory and any overlays: envelope structure, segment and element cardinality, representation and code values, each finding carrying the rule that produced it and where in the source it applies. |
|
|
Edifact.Projection
Projects a matched message into JSON or XML, either as the document it describes or as a linked form in which every value still points at the directory definition it was read against. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0-preview.6 | 76 | 10/11/2026 |
| 1.0.0-preview.5 | 102 | 9/19/2026 |
| 1.0.0-preview.4 | 89 | 9/17/2026 |
| 1.0.0-preview.3 | 141 | 9/7/2026 |
| 1.0.0-preview.2 | 119 | 9/6/2026 |
| 1.0.0-preview.1 | 103 | 9/6/2026 |