EDI DOM Document Object Model

EDI Document Object Model (EDI DOM) is a revolutionary new approach for handling EDI files or documents programmatically. In the EDI world each business transaction is defined with a standard EDI specification (also known as EDI spec, or EDI schema, or EDI rule). Each EDI rule describes a particular business document, e.g. an invoice or a purchase order and is tied up to a version. The governing bodies of X12, EDIFACT and EANCOM are ASC, UNECE and GS1 respectively, and they release new versions of the rules once or twice per year.

Unfortunately the versions are not backward compatible, mainly due to the EDI codes which can change significantly in every subsequent version. An excerpt from a sample rule is shown below:

EDI rules rules

The EDI rules are usually distributed in the form of PDF or text files accompanied by machine readable XML schemas (XSDs). There is no unified way in supporting the EDI rules and businesses have taken into building and maintaining their own representations of the EDI rules. This adds to the complexity of EDI due to the abundant EDI formats and their partner specific variations but also of the various methods to describe and represent their corresponding EDI rules. We've witnessed the birth of SEF, custom XSD/XML based formats and proprietary scripts, all attempting to resolve the dilemma of how to best represent the EDI rules.

Some of the disadvantages of all existing approaches are:

  • 1. Mapping - the need to support both the EDI rules and the mapping to other targets such as data base structures or domain entities.
  • 2. Complexity - SEF format for example is notoriously complex and custom scripting formats require extra resources and knowledge to maintain them and introduce new versions or changes.
  • 3. Tight coupling - having multiple moving parts such as the EDI rules, a separate editor program to manipulate them, mapping software and maps, custom parser\solutions to transpose EDI according to the rules, etc. have limitations on how easy a simple change to one of the parts can be safely propagated to the others and the sufficient time to re-test it.
  • 4. Performance - the parsing of EDI files usually flows through multiple hops and the data from the original file needs to be converted to internal memory representation, matched against a grammar, loaded into XML or other key-value table structures, then serialized or queried using Xpath or custom scripts. All these steps consume valuable resources, take longer to complete and provide a cumbersome interface to access the data from EDI files.

EDI Document Object Model (EDI DOM) resolves all the implications described above. It does not reinvent the wheel, but rather extend the existing efforts with the same idea that made XML so popular amongst the developer community - the document object model. The same way as XML provides access to its data via a unified set of attributes, elements and interfaces, EDI DOM introduced a set of annotations which can turn plain C# classes and class hierarchies into fully compliant EDI rules. The benefits of this approach are obvious but let's mention some of them:

  • 1. No mapping - the data from EDI files is transposed directly to the annotated classes thus eliminating the need for any mapping.
  • 2. Simplicity - all EDI rules are simple C# classes which can be edited with any text editor by any programmer with no EDI experience.
  • 3. Loose coupling - changes are trivial, either amend a class or create a new one from scratch or from template. There are no internal dependencies or moving parts.
  • 4. Performance - the contents of EDI files are streamed directly into instances of the C# EDI rules. There are no internal hops and no serialization - all data is transposed ultra fast directly to the instances of the specified classes.

EdiFabric uses plain C# classes to represent EDI documents. Each of the main EDI elements, such as transaction set, segment, data element and composite element are simply classes annotated with our custom attributes. Every class hierarchy can be turned into EDI rule by applying the following attributes:

Transaction set classes are annotated with MessageAttribute and inherit from EdiMessage

[Message("X12", "002040", "810")]
public class TS810 : EdiMessage

EdiMessage is the base class for all transaction sets.

The first parameter is the format (X12 or EDIFACT).

The second parameter is the version (edition + release).

The last parameter is the transaction set identifier.

EdiFabric uses these attribute values to load the correct transaction set class. Classes with the same values for all three attributes are not allowed in the same assembly and are regarded as duplicates.

Classes can contain only ordered public properties

[Pos(1)]
public ST ST { get; set; }
[Pos(2)]
public BIG BIG { get; set; }
[Pos(3)]
public List<NTE> NTE { get; set; }

To order the properties they must be annotated with PosAttribute, which denotes the position of the property within the class.

Repetitions or multiple occurrences are represented as Lists

public List<NTE> NTE { get; set; }

Simple data elements are represented as strings

public string TransactionTypeCode_07 { get; set; }

Segment classes are annotated with SegmentAttribute

[Segment("BHT", typeof(X12_ID_1005), typeof(X12_ID_353))]
public class BHT

The first parameter is the EDI identifier of the segment.

(Optional) The second parameter is a reference to the class defining the allowed EDI codes for the first data element in the segment.

(Optional)The last parameter is a reference to the class defining the allowed EDI codes for the second data element in the segment.

The allowed EDI codes are represented as classes annotated with EdiCodesAttribute

[EdiCodes(",00,18,")]
public class X12_ID_353

The only parameter is a string containing all of the allowed EDI codes, delimited with a comma.

Loop (Group) classes are annotated with GroupAttribute

[Group(typeof(N1))]
public class TS810_N1Loop1

The only parameter is the type of the first (trigger) segment in the group.

HIPAA specific non-sequence groupings are annotated with AllAttribute

[All()]
public class All_NM1_2

Composite element classes are annotated with CompositeAttribute

[Composite("C108")]
public class C108

(Optional) The first parameter is the EDI identifier of the composite element.

Each namespace, class or property name can be renamed.

Conform to every naming convention by the ability to rename anything outside the custom attributes without affecting the framework.