Getting Started with EDIFACTWriter

Requirements:
IPWorks EDI or IPWorks EDI Translator

Introduction

IPWorks EDI and IPWorks EDI Translator include components for reading, and writing EDIFACT documents. This article will focus on using the EDIFACTWriter component to create EDI (EDIFACT) documents.

Contents

  1. Loading a Schema
  2. Writing an EDI Document
  3. Code Example for DESADV

Loading a Schema

The EDIFACTWriter component is designed to work with multiple schema formats. A schema allows the component to validate the EDI document while writing and provides additional details about the structure of the document, such as loops. Using a schema is not required, but is recommended. The free JSON schemas offered by CData Arc may be used, but multiple formats are supported:

LoadSchema should be called before writing the document. For instance:

//Load the EDIFACT DESADV schema string schemaFile = @"C:\Schemas\edifact_schemas\D97A\RSSBus_D97A_DESADV.json"; Edifactwriter writer = new Edifactwriter(); writer.SchemaFormat = EdifactwriterSchemaFormats.schemaJSON; writer.LoadSchema(schemaFile);

Once a schema is loaded the document can be created. In some cases the document structure is known ahead of time. However, in other cases it's useful to see the schema structure of the document. To display schema information from the component call the DisplaySchemaInfo method. For instance:

edireader.LoadSchema(schemaFile); Console.WriteLine(edireader.DisplaySchemaInfo());

This will output a schema structure like:

UNH[0,1] BGM[0,1] DTM[0,35] PAI[0,1] ALI[0,5] IMD[0,1] FTX[0,10] LOC[0,10] GIS[0,10] DGS[0,1] RFFLoop1[0,99] RFF[0,1] DTM_2[0,5] GIR[0,5] LOC_2[0,2] MEA[0,5] QTY[0,2] FTX_2[0,5] MOA[0,2] NADLoop1[0,99] NAD[0,1] LOC_3[0,25] FII[0,5] RFFLoop2[0,9999] RFF_2[0,1] DTM_3[0,5] DOCLoop1[0,5] DOC[0,1] DTM_4[0,5] CTALoop1[0,5] CTA[0,1] COM[0,5] TAXLoop1[0,5] TAX[0,1] MOA_2[0,1] LOC_4[0,5] CUXLoop1[0,5] CUX[0,1] DTM_5[0,5] PATLoop1[0,10] PAT[0,1] DTM_6[0,5] PCD[0,1] MOA_3[0,1] PAI_2[0,1] FII_2[0,1] TDTLoop1[0,10] TDT[0,1] TSR[0,1] LOCLoop1[0,10] LOC_5[0,1] DTM_7[0,5] RFFLoop3[0,9999] RFF_3[0,1] DTM_8[0,5] TODLoop1[0,5] TOD[0,1] LOC_6[0,2] PACLoop1[0,1000] PAC[0,1] MEA_2[0,5] EQD[0,1] PCILoop1[0,5] PCI[0,1] RFF_4[0,1] DTM_9[0,5] GIN[0,5] ALCLoop1[0,9999] ALC[0,1] ALI_2[0,5] FTX_3[0,1] RFFLoop4[0,5] RFF_5[0,1] DTM_10[0,5] QTYLoop1[0,1] QTY_2[0,1] RNG[0,1] PCDLoop1[0,1] PCD_2[0,1] RNG_2[0,1] MOALoop1[0,2] MOA_4[0,1] RNG_3[0,1] CUX_2[0,1] DTM_11[0,1] RTELoop1[0,1] RTE[0,1] RNG_4[0,1] TAXLoop2[0,5] TAX_2[0,1] MOA_5[0,1] RCSLoop1[0,100] RCS[0,1] RFF_6[0,5] DTM_12[0,5] FTX_4[0,5] AJTLoop1[0,1] AJT[0,1] FTX_5[0,5] INPLoop1[0,1] INP[0,1] FTX_6[0,5] LINLoop1[0,9999999] LIN[0,1] PIA[0,25] IMD_2[0,10] MEA_3[0,5] QTY_3[0,5] PCD_3[0,1] ALI_3[0,5] DTM_13[0,35] GIN_2[0,1000] GIR_2[0,1000] QVR[0,1] EQD_2[0,1] FTX_7[0,5] DGS_2[0,1] MOALoop2[0,10] MOA_6[0,1] CUX_3[0,1] PATLoop2[0,10] PAT_2[0,1] DTM_14[0,5] PCD_4[0,1] MOA_7[0,1] PRILoop1[0,25] PRI[0,1] CUX_4[0,1] APR[0,1] RNG_5[0,1] DTM_15[0,5] RFFLoop5[0,10] RFF_7[0,1] DTM_16[0,5] PACLoop2[0,10] PAC_2[0,1] MEA_4[0,10] EQD_3[0,1] PCILoop2[0,10] PCI_2[0,1] RFF_8[0,1] DTM_17[0,5] GIN_3[0,10] LOCLoop2[0,9999] LOC_7[0,1] QTY_4[0,100] DTM_18[0,5] TAXLoop3[0,99] TAX_3[0,1] MOA_8[0,1] LOC_8[0,5] NADLoop2[0,99] NAD_2[0,1] LOC_9[0,5] RFFLoop6[0,5] RFF_9[0,1] DTM_19[0,5] DOCLoop2[0,5] DOC_2[0,1] DTM_20[0,5] CTALoop2[0,5] CTA_2[0,1] COM_2[0,5] ALCLoop2[0,30] ALC_2[0,1] ALI_4[0,5] DTM_21[0,5] FTX_8[0,1] QTYLoop2[0,1] QTY_5[0,1] RNG_6[0,1] PCDLoop2[0,1] PCD_5[0,1] RNG_7[0,1] MOALoop3[0,2] MOA_9[0,1] RNG_8[0,1] CUX_5[0,1] DTM_22[0,1] RTELoop2[0,1] RTE_2[0,1] RNG_9[0,1] TAXLoop4[0,5] TAX_4[0,1] MOA_10[0,1] TDTLoop2[0,10] TDT_2[0,1] LOCLoop3[0,10] LOC_10[0,1] DTM_23[0,5] TODLoop2[0,5] TOD_2[0,1] LOC_11[0,2] RCSLoop2[0,100] RCS_2[0,1] RFF_10[0,5] DTM_24[0,5] FTX_9[0,5] GISLoop1[0,10] GIS_2[0,1] RFF_11[0,1] DTM_25[0,5] GIR_3[0,5] LOC_12[0,2] MEA_5[0,5] QTY_6[0,2] FTX_10[0,5] MOA_11[0,2] UNS[0,1] CNT[0,10] MOALoop4[0,100] MOA_12[0,1] RFFLoop7[0,1] RFF_12[0,1] DTM_26[0,5] TAXLoop5[0,10] TAX_5[0,1] MOA_13[0,2] ALCLoop3[0,15] ALC_3[0,1] ALI_5[0,1] MOA_14[0,2] FTX_11[0,1] UNT[0,1]

This information provides a starting place if there is no prior knowledge about the document structure.

Writing an EDI Document

After loading the schema, determine the destination of the file being written. The EDI file may be written to disk by setting OutputFile. In Java and .NET editions streams are supported by calling SetOutputStream. If neither are set, the data will be held in memory and accessible via OutputData.

The suffix used to separate segments may be specified in the Suffix property. For readability CrLf may be used. For instance:

writer.Suffix = EdifactwriterSuffixes.suffixCRLF;

Starting a Document

When creating the document the StartInterchangeHeader, StartFunctionalGroupHeader, and StartTransactionHeader methods are used to create the initial segments within the document.

Interchange Header

To begin creating the document call StartInterchangeHeader. This method takes the document version as a parameter. The elements of the interchange segment may be written with WriteElementString and WriteComponentString. For instance:

ediwriter1.StartInterchangeHeader("D97A"); ediwriter1.StartElement(); ediwriter1.WriteComponentString("UNOB"); ediwriter1.WriteComponentString("1"); ediwriter1.EndElement(); ediwriter1.StartElement(); ediwriter1.WriteComponentString("WAYNE_TECH"); ediwriter1.EndElement(); ediwriter1.StartElement(); ediwriter1.WriteComponentString("ACME"); ediwriter1.EndElement(); ediwriter1.StartElement(); ediwriter1.WriteComponentString("160707"); ediwriter1.WriteComponentString("1547"); ediwriter1.EndElement(); ediwriter1.WriteElementString("000000001"); ediwriter1.StartElement(); ediwriter1.WriteComponentString(""); ediwriter1.EndElement(); ediwriter1.WriteElementString("1234"); ediwriter1.SkipElement(); ediwriter1.SkipElement(); ediwriter1.SkipElement(); ediwriter1.WriteElementString("1"); ediwriter1.EndElement(); Will create the UNA and UNB segments: UNA:+.?*' UNB+UNOB:1+WAYNE_TECH+ACME+160707:1547+000000001++1234++++1'

Transaction Header

Next create the transaction header by calling StartTransactionHeader. This method takes the document code (for example "DESADV"). The component will use the document code specified and the document version provided when StartInterchangeHeader was called to locate a matching transaction set schema from the loaded schema file(s).

For instance:

writer.StartTransactionHeader("DESADV"); writer.WriteElementString("1"); writer.StartElement(); writer.WriteComponentString("DESADV"); writer.WriteComponentString("D"); writer.WriteComponentString("97A"); writer.WriteComponentString("UN"); writer.EndElement();

Creates the UNH segment:

UNH+1+DESADV:D:97A:UN'

Segments and Elements

Segments are created within the document by calling StartSegment. When called a new data segment is created in the current transaction and set at the current segment. Creating a new data segment automatically writes the previous current segment to the output stream.

The SegmentType argument specifies the type of data segment to create, using an XPath-like syntax, based on the transaction set schema. See Creating Loops for details on using StartSegment with loops.

After creating the segment to write an element call WriteElementString. To write an element without providing a value call SkipElement. For instance:

//Write the TDT segment writer.StartSegment("TDTLoop1/TDT"); writer.WriteElementString("12"); writer.SkipElement(); writer.StartElement(); writer.WriteComponentString("M"); writer.EndElement(); writer.SkipElement(); writer.StartElement(); writer.WriteComponentString("CARRIER"); writer.SkipComponent(); writer.WriteComponentString("86"); writer.EndElement();

Creates the segment:

TDT+12++M++CARRIER::86'

The EndSegment method may be called to explicitly end the segment. In many cases calling EndSegment is not necessary if the next call is StartSegement since StartSegment will automatically close any open segment before starting the new segment.

Creating Loops

Loops are also created using the StartSegment method. When passing the segmentType parameter to the method include the XPath notation of the loop and the segment within the loop, for instance NADLoop1/NAD. For instance:

//Create a NADLoop1 with NAD segment writer.StartSegment("NADLoop1/NAD"); writer.WriteElementString("ST"); writer.StartElement(); writer.WriteComponentString("0018"); writer.SkipComponent(); writer.WriteComponentString("92"); writer.EndElement();

Creates the following segment:

NAD+ST+0018::92'

Composite Elements

Composite Elements can be created by calling StartElement followed by one or more calls to WriteComponentString. When all the components of the composite element are written call EndElement. For instance:

writer.StartSegment("TST"); writer.StartElement(); writer.WriteComponentString("VAL1"); writer.WriteComponentString("VAL2"); writer.WriteComponentString("VAL3"); writer.EndElement(); writer.WriteElementString("OTHER");

Will create a segment with the elements:

TST+VAL1:VAL2:VAL3+OTHER'

Repeat Elements

Repeating elements may be written by calling the RepeatElement method in conjunction with WriteElementString or WriteComponentString. The following code will repeat a simple data element:

writer.StartSegment("TST"); writer.WriteElementString("VAL1_1"); writer.RepeatElement(); writer.WriteElementString("VAL1_2"); writer.RepeatElement(); writer.WriteElementString("VAL1_3");

Which outputs:

TST+VAL1_1*VAL1_2*VAL1_3'

The following code will repeat a composite data element:

writer.StartSegment("TST"); writer.StartElement(); writer.WriteComponentString("COMP1_1"); writer.WriteComponentString("COMP2_1"); writer.RepeatElement(); writer.WriteComponentString("COMP1_2"); writer.WriteComponentString("COMP2_2"); writer.RepeatElement(); writer.WriteComponentString("COMP1_3"); writer.WriteComponentString("COMP2_3"); writer.EndElement();

Which outputs:

TST+COMP1_1:COMP2_1:COMP1_2:COMP2_2:COMP1_3:COMP2_3'

Creating Footers and Ending the Document

When all segments of the document have been written the component can optionally create the transaction, functional group, and interchange footers. To do this call the CreateTransactionFooter, CreateFunctionalGroupFooter, and CreateInterchangeFooter methods. For instance in the DESADV document example in the following section calling:

writer.CreateTransactionFooter(); writer.CreateInterchangeFooter();

Outputs:

UNT+19+1' UNZ+1+000000001'

Code Example for DESADV

The following code creates an example EDIFACT DESADV document.

//Initial setup Edifactwriter writer = new Edifactwriter(); writer.SchemaFormat = EdifactwriterSchemaFormats.schemaJSON; writer.LoadSchema(schemaFile); writer.Suffix = EdifactwriterSuffixes.suffixCRLF; //Start Interchange Header writer.StartInterchangeHeader("D97A"); writer.StartElement(); writer.WriteComponentString("UNOB"); writer.WriteComponentString("1"); writer.EndElement(); writer.StartElement(); writer.WriteComponentString("WAYNE_TECH"); writer.EndElement(); writer.StartElement(); writer.WriteComponentString("ACME"); writer.EndElement(); writer.StartElement(); writer.WriteComponentString("160707"); writer.WriteComponentString("1547"); writer.EndElement(); writer.WriteElementString("000000001"); writer.StartElement(); writer.WriteComponentString(""); writer.EndElement(); writer.WriteElementString("1234"); writer.SkipElement(); writer.SkipElement(); writer.SkipElement(); writer.WriteElementString("1"); writer.EndElement(); //Start Transaction Header writer.StartTransactionHeader("DESADV"); writer.WriteElementString("1"); writer.StartElement(); writer.WriteComponentString("DESADV"); writer.WriteComponentString("D"); writer.WriteComponentString("97A"); writer.WriteComponentString("UN"); writer.EndElement(); //Write the BGM segment writer.StartSegment("BGM"); writer.StartElement(); writer.WriteComponentString("351"); writer.EndElement(); writer.StartElement(); writer.WriteComponentString("2014/10093"); writer.EndElement(); writer.WriteElementString("9"); writer.EndElement(); //Write the DTM segment writer.StartSegment("DTM"); writer.StartElement(); writer.WriteComponentString("137"); writer.WriteComponentString("201404192036"); writer.WriteComponentString("203"); writer.EndElement(); //Write the DTM segment writer.StartSegment("DTM"); writer.StartElement(); writer.WriteComponentString("11"); writer.WriteComponentString("201404192036"); writer.WriteComponentString("203"); writer.EndElement(); //Write the MEA segment writer.StartSegment("MEA"); writer.WriteElementString("AAX"); writer.StartElement(); writer.WriteComponentString("SQ"); writer.EndElement(); writer.StartElement(); writer.WriteComponentString("C62"); writer.WriteComponentString("17"); writer.EndElement(); //Write NADLoop1 with NAD segment writer.StartSegment("NADLoop1/NAD"); writer.WriteElementString("ST"); writer.StartElement(); writer.WriteComponentString("0018"); writer.SkipComponent(); writer.WriteComponentString("92"); writer.EndElement(); //Write NADLoop1 with NAD segment writer.StartSegment("NADLoop1/NAD"); writer.WriteElementString("SU"); writer.StartElement(); writer.WriteComponentString("2019813"); writer.SkipComponent(); writer.WriteComponentString("92"); writer.EndElement(); //Write TDTLoop1 with TDT segment writer.StartSegment("TDTLoop1/TDT"); writer.WriteElementString("12"); writer.SkipElement(); writer.StartElement(); writer.WriteComponentString("M"); writer.EndElement(); writer.SkipElement(); writer.StartElement(); writer.WriteComponentString("CARRIER"); writer.SkipComponent(); writer.WriteComponentString("86"); writer.EndElement(); //Write EQDLoop1 with EQD segment writer.StartSegment("EQDLoop1/EQD"); writer.WriteElementString("TE"); writer.StartElement(); writer.WriteComponentString("X"); writer.EndElement(); writer.EndElement(); //Write CPSLoop1 with CPS segment writer.StartSegment("CPSLoop1/CPS"); writer.WriteElementString("1"); writer.SkipElement(); writer.WriteElementString("1"); writer.EndElement(); //Write PACLoop1 with PAC segment (nested inside CPSLoop1) writer.StartSegment("CPSLoop1/PACLoop1/PAC"); writer.WriteElementString("4"); writer.StartElement(); writer.WriteComponentString("1"); writer.EndElement(); writer.StartElement(); writer.WriteComponentString("BOX-001"); writer.EndElement(); //Write the QTY segment (nested inside PACLoop1, nested inside CPSLoop1) writer.StartSegment("CPSLoop1/PACLoop1/QTY"); writer.StartElement(); writer.WriteComponentString("52"); writer.WriteComponentString("50"); writer.WriteComponentString("C62"); writer.EndElement(); //Write the CPS segment (nested inside CPSLoop1) writer.StartSegment("CPSLoop1/CPS"); writer.WriteElementString("2"); writer.SkipElement(); writer.WriteElementString("1"); writer.EndElement(); //Write PACLoop1 with PAC segment (nested inside CPSLoop1) writer.StartSegment("CPSLoop1/PACLoop1/PAC"); writer.WriteElementString("2"); writer.StartElement(); writer.WriteComponentString("1"); writer.EndElement(); writer.StartElement(); writer.WriteComponentString("BOX-002"); writer.EndElement(); //Write the QTY segment (nested inside PACLoop1, nested inside CPSLoop1) writer.StartSegment("CPSLoop1/PACLoop1/QTY"); writer.StartElement(); writer.WriteComponentString("52"); writer.WriteComponentString("100"); writer.WriteComponentString("C62"); writer.EndElement(); //Write LINLoop1 with LIN segment (nested inside CPSLoop1) writer.StartSegment("CPSLoop1/LINLoop1/LIN"); writer.WriteElementString("1"); writer.SkipElement(); writer.StartElement(); writer.WriteComponentString("9001"); writer.WriteComponentString("IN"); writer.EndElement(); //Write the QTY segment (nested inside PACLoop1, nested inside LINLoop1) writer.StartSegment("CPSLoop1/LINLoop1/QTY"); writer.StartElement(); writer.WriteComponentString("12"); writer.WriteComponentString("400"); writer.WriteComponentString("C62"); writer.EndElement(); //Write RFFLoop1 with RFF segment writer.StartSegment("RFFLoop1/RFF"); writer.StartElement(); writer.WriteComponentString("ON"); writer.WriteComponentString("N55109001"); writer.EndElement(); //Create footers writer.CreateTransactionFooter(); writer.CreateInterchangeFooter(); writer.Flush(); Console.WriteLine(writer.OutputData);

Creates the document:

UNA:+.?*' UNB+UNOB:1+WAYNE_TECH+ACME+160707:1547+000000001++1234++++1' UNH+1+DESADV:D:97A:UN' BGM+351+2014/10093+9' DTM+137:201404192036:203' DTM+11:201404192036:203' MEA+AAX+SQ+C62:17' NAD+ST+0018::92' NAD+SU+2019813::92' TDT+12++M++CARRIER::86' EQD+TE+X' CPS+1++1' PAC+4+1+BOX-001' QTY+52:50:C62' CPS+2++1' PAC+2+1+BOX-002' QTY+52:100:C62' LIN+1++9001:IN' QTY+12:400:C62' RFF+ON:N55109001' UNT+19+1' UNZ+1+000000001'

We appreciate your feedback.  If you have any questions, comments, or suggestions about this article please contact our support team at kb@nsoftware.com.