Getting Started with X12Writer

Requirements:
IPWorks EDI or IPWorks EDI Translator

Introduction

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

Contents

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

Loading a Schema

The X12Writer 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 X12 810 schema string schemaFile = @"C:\Schemas\x12_schemas\00401\RSSBus_00401_810.json"; X12writer writer = new X12writer(); writer.SchemaFormat = X12writerSchemaFormats.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:

ST[0,1] BIG[0,1] NTE[0,100] CUR[0,1] REF[0,12] YNQ[0,10] PER[0,3] N1Loop1[0,200] N1[0,1] N2[0,2] N3[0,2] N4[0,1] REF_2[0,12] PER_2[0,3] DMG[0,1] ITD[0,999999] DTM[0,10] FOB[0,1] PID[0,200] MEA[0,40] PWK[0,25] PKG[0,25] L7[0,1] BAL[0,999999] INC[0,1] PAM[0,999999] LMLoop1[0,10] LM[0,1] LQ[0,100] N9Loop1[0,1] N9[0,1] MSG[0,10] V1Loop1[0,999999] V1[0,1] R4[0,999999] DTM_2[0,999999] FA1Loop1[0,999999] FA1[0,1] FA2[0,999999] IT1Loop1[0,200000] IT1[0,1] CRC[0,1] QTY[0,5] CUR_2[0,1] IT3[0,5] TXI[0,10] CTP[0,25] PAM_2[0,10] MEA_2[0,40] PIDLoop1[0,1000] PID_2[0,1] MEA_3[0,10] PWK_2[0,25] PKG_2[0,25] PO4[0,1] ITD_2[0,2] REF_3[0,999999] YNQ_2[0,10] PER_3[0,5] SDQ[0,500] DTM_3[0,10] CAD[0,999999] L7_2[0,999999] SR[0,1] SACLoop1[0,25] SAC[0,1] TXI_2[0,10] SLNLoop1[0,1000] SLN[0,1] DTM_4[0,1] REF_4[0,999999] PID_3[0,1000] SAC_2[0,25] TC2[0,2] TXI_3[0,10] N1Loop2[0,200] N1_2[0,1] N2_2[0,2] N3_2[0,2] N4_2[0,1] REF_5[0,12] PER_4[0,3] DMG_2[0,1] LMLoop2[0,10] LM_2[0,1] LQ_2[0,100] V1Loop2[0,999999] V1_2[0,1] R4_2[0,999999] DTM_5[0,999999] FA1Loop2[0,999999] FA1_2[0,1] FA2_2[0,999999] TDS[0,1] TXI_4[0,10] CAD_2[0,1] AMT[0,999999] SACLoop2[0,25] SAC_3[0,1] TXI_5[0,10] ISSLoop1[0,999999] ISS[0,1] PID_4[0,1] CTT[0,1] SE[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 = X12writerSuffixes.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:

writer.StartInterchangeHeader("004010"); writer.WriteElementString("00"); writer.SkipElement(); writer.WriteElementString("00"); writer.SkipElement(); writer.WriteElementString("ZZ"); writer.WriteElementString("ACME "); writer.WriteElementString("ZZ"); writer.WriteElementString("WAYNE_TECH "); writer.WriteElementString("160707"); writer.WriteElementString("1544"); writer.WriteElementString("U"); writer.WriteElementString("00401"); writer.WriteElementString("000000006"); writer.WriteElementString("0"); writer.WriteElementString("T"); writer.WriteElementString(">"); Will create the ISA segment: ISA*00* *00* *ZZ*ACME *ZZ*WAYNE_TECH *160707*1544*U*00401*000000006*0*T*>~

Functional Group Header

After creating the interchange header, the functional group header must be created by calling StartFunctionalGroupHeader. Again WriteElementString and WriteComponentString may be used to create the header values. For instance:

writer.StartFunctionalGroupHeader(); writer.WriteElementString("IN"); writer.WriteElementString("ACME"); writer.WriteElementString("WAYNE_TECH"); writer.WriteElementString("20160707"); writer.WriteElementString("1544"); writer.WriteElementString("6"); writer.WriteElementString("T"); writer.WriteElementString("004010");

Creates the GS segment:

GS*IN*ACME*WAYNE_TECH*20160707*1544*6*T*004010~

Transaction Header

Next, create the transaction header by calling StartTransactionHeader. This method takes the document code (for example "810"). 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("810"); writer.WriteElementString("810"); writer.WriteElementString("0001");

Creates the ST segment:

ST*810*0001~

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 BIG segment writer.StartSegment("BIG"); writer.WriteElementString("20150708"); writer.WriteElementString("3003014445"); writer.SkipElement(); writer.WriteElementString("0476553272"); writer.SkipElement(); writer.SkipElement(); writer.WriteElementString("DR"); writer.EndElement();

Creates the segment:

BIG*20150708*3003014445**0476553272***DR~

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, like N1Loop1/N1. For instance:

//Create a N1Loop1 with N1, N3, and N4 segments writer.StartSegment("N1Loop1/N1"); writer.WriteElementString("BY"); writer.WriteElementString("Company"); writer.WriteElementString("92"); writer.WriteElementString("544380"); writer.StartSegment("N1Loop1/N3"); writer.WriteElementString("Address"); writer.StartSegment("N1Loop1/N4"); writer.WriteElementString("City"); writer.SkipElement(); writer.WriteElementString("200131"); writer.WriteElementString("US");

Creates the following segments:

N1*BY*Company*92*544380~ N3*Address~ N4*City**200131*US~

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 810 document example, calling:

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

Outputs:

SE*19*0001~ GE*1*6~ IEA*1*000000006~

Code Example for 810

The following code creates an example X12 810 document.

//Initial Setup X12writer writer = new X12writer(); writer.SchemaFormat = X12writerSchemaFormats.schemaJSON; writer.LoadSchema(schemaFile); writer.Suffix = X12writerSuffixes.suffixCRLF; //Start Interchange Header writer.StartInterchangeHeader("004010"); writer.WriteElementString("00"); writer.SkipElement(); writer.WriteElementString("00"); writer.SkipElement(); writer.WriteElementString("ZZ"); writer.WriteElementString("ACME "); writer.WriteElementString("ZZ"); writer.WriteElementString("WAYNE_TECH "); writer.WriteElementString("160707"); writer.WriteElementString("1544"); writer.WriteElementString("U"); writer.WriteElementString("00401"); writer.WriteElementString("000000006"); writer.WriteElementString("0"); writer.WriteElementString("T"); writer.WriteElementString(">"); //Start Functional Group writer.StartFunctionalGroupHeader(); writer.WriteElementString("IN"); writer.WriteElementString("ACME"); writer.WriteElementString("WAYNE_TECH"); writer.WriteElementString("20160707"); writer.WriteElementString("1544"); writer.WriteElementString("6"); writer.WriteElementString("T"); writer.WriteElementString("004010"); //Start Transaction Header writer.StartTransactionHeader("810"); writer.WriteElementString("810"); writer.WriteElementString("0001"); //Write the BIG segment writer.StartSegment("BIG"); writer.WriteElementString("20150708"); writer.WriteElementString("3003014445"); writer.SkipElement(); writer.WriteElementString("0476553272"); writer.SkipElement(); writer.SkipElement(); writer.WriteElementString("DR"); writer.EndElement(); //Write the CUR segment writer.StartSegment("CUR"); writer.WriteElementString("SE"); writer.WriteElementString("USD"); //Write the REF segment writer.StartSegment("REF"); writer.WriteElementString("8M"); writer.WriteElementString("0056"); //Write N1Loop1 with N1, N3, and N4 segments writer.StartSegment("N1Loop1/N1"); writer.WriteElementString("BY"); writer.WriteElementString("Company"); writer.WriteElementString("92"); writer.WriteElementString("544380"); writer.StartSegment("N1Loop1/N3"); writer.WriteElementString("Address"); writer.StartSegment("N1Loop1/N4"); writer.WriteElementString("City"); writer.WriteElementString("CA"); writer.WriteElementString("Postal Code"); //Write N1Loop1 with N1, N3, and N4 segments writer.StartSegment("N1Loop1/N1"); writer.WriteElementString("ST"); writer.WriteElementString("Name"); writer.WriteElementString("92"); writer.WriteElementString("0607047800010"); writer.StartSegment("N1Loop1/N3"); writer.WriteElementString("Address"); writer.StartSegment("N1Loop1/N4"); writer.WriteElementString("City"); writer.SkipElement(); writer.WriteElementString("200131"); writer.WriteElementString("US"); //Write N1Loop1 with N1, N3, and N4 segments writer.StartSegment("N1Loop1/N1"); writer.WriteElementString("RE"); writer.WriteElementString("Name"); writer.WriteElementString("92"); writer.WriteElementString("5095956"); writer.StartSegment("N1Loop1/N3"); writer.WriteElementString("Address"); writer.StartSegment("N1Loop1/N4"); writer.WriteElementString("City"); writer.WriteElementString("IL"); writer.WriteElementString("Postal Code"); //Write IT1Loop1 with IT1 segment writer.StartSegment("IT1Loop1/IT1"); writer.WriteElementString("20"); writer.WriteElementString("2500"); writer.WriteElementString("EA"); writer.WriteElementString("36.96"); writer.SkipElement(); writer.WriteElementString("BP"); writer.WriteElementString("335S0594"); //Write IT1Loop1 with REF segments writer.StartSegment("IT1Loop1/REF"); writer.WriteElementString("KK"); writer.WriteElementString("0099778154"); writer.StartSegment("IT1Loop1/REF"); writer.WriteElementString("PO"); writer.WriteElementString("0476553272"); writer.WriteElementString("20"); //Write TDS segment writer.StartSegment("TDS"); writer.WriteElementString("9240000"); //Write CTT segment writer.StartSegment("CTT"); writer.WriteElementString("1"); //Create footers writer.CreateTransactionFooter(); writer.CreateFunctionalGroupFooter(); writer.CreateInterchangeFooter(); writer.Flush(); Console.WriteLine(writer.OutputData);

Creates the document:

ISA*00* *00* *ZZ*ACME *ZZ*WAYNE_TECH *160707*1544*U*00401*000000006*0*T*>~ GS*IN*ACME*WAYNE_TECH*20160707*1544*6*T*004010~ ST*810*0001~ BIG*20150708*3003014445**0476553272***DR~ CUR*SE*USD~ REF*8M*0056~ N1*BY*Company*92*544380~ N3*Address~ N4*City*CA*Postal Code~ N1*ST*Name*92*0607047800010~ N3*Address~ N4*City**200131*US~ N1*RE*Name*92*5095956~ N3*Address~ N4*City*IL*Postal Code~ IT1*20*2500*EA*36.96**BP*335S0594~ REF*KK*0099778154~ REF*PO*0476553272*20~ TDS*9240000~ CTT*1~ SE*19*0001~ GE*1*6~ IEA*1*000000006~

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