X12 parsing


This code is a template for X12 parsing

Source Code
-- use the path to where you saved the file "270BlueCrossEdited.edi"
local MY_FILE = '/Users/<some-user>/downloads/temp/270BlueCrossEdited.edi'

--[[ Prior to parsing, create a 'copy' of X12 Library VMD file.

Remove from 'copy' all Transactions you aren't going to use 
with this specific interface.

Add to 'copy' Segment Grammar the Functional Groups and the
Interchange Envelope segments.

See example in 270v3.vmd file, where hierarchy is defined as 


In shorthand notation it could be expressed as 
ISA [{GS [{ST ... SE}]  GE}] IEA 

The v3 in vmd file name has nothing to do with versions of 
X12 or HL7. Simply two earlier versions of this file were 

function main()  
   local function readMyFile(fn)
      local f = assert(io.open(fn, 'rb'))
      local d = f:read('*a')
      return d
   local Data = readMyFile(MY_FILE)
   --[[ Optionally, Interchange delimiters can be normalized
   here, e.g. Data = Data:gsub('\r','~')
   Above example replaces <CR> Segments Terminator with tilde.
   In your specific data, the character to replace will be the 
   one on 106th place in ISA segment. So that example can be 
   enhanced to be Data = Data:gsub(Data:sub(106,106),'~').
   Translator's X12 module expects to find standard Interchange  
   delimiters in a message. If needed, delimiters can be reversed
   to original values after processing by Translator got completed.
   local In,Name,Warnings = x12.parse{
      vmd = 'example/270v3.vmd', 
      data = Data}
   --[[ Optionally, some sanity tests for validation of data can 
   take place here. Please see TA1 acknowledgement example in Wiki
   at http://wiki.interfaceware.com/388.html
   This example shows TA1 for 270/271 "HealthCare Eligibility 
   Benefit Inquiry and Response" scenario, as per 004010X092
   local TS  
   --[[ Now substract every single Transaction Set to be processed as 
   single Transaction Set.
   for i=1,In.InterchangeEnvelope.IEA[1]:nodeValue() do
      for j=1,In.InterchangeEnvelope.FunctionalGroup[i].GE[1]:nodeValue() do
         TS = In.InterchangeEnvelope.FunctionalGroup[i].TransactionSet[j]
         --[[ To push it into Iguana's queue, to be processed by next
         channels component, call function queue.push{}, e.g.
         queue.push{data = tostring(TS):gsub('\r','~')}
         Note the tilde placed back as Segment Terminator.
         --[[ To process otherwise, call some other function, 
         e.g. function foo()
         or another example
         local Success, s = pcall(foo2,TS)
         --[[ The X12 Interchange Envelope may contain huge number of 
         Transacion Sets, thus it only makes sense to push individual 
         Transaction Sets into Iguana's queue one by one to be processed by 
         next channels component. 
         This, instead of processing them by local function in this channels 
         This recommended approach will speed up over all 
         processing speed of given interface.
         --[[ JSON to the resque
         Whenever next Transaction Set is processed by next channels component,
         we often wish to know which Functional Group it comes from, and which 
         Interchange Envelope, etc...
         To pass this information along with Transaction Set content, we can 
         combine variable TS with values from GS/GE ans ISA/IEA segments
         into JSON object. 
         This JSON object get pushed into Iguana's queue. Then next channels 
         component will decompose the object as shown in example
         on page http://wiki.interfaceware.com/1337.html and process content.
         Hypothetical next component can do, for example, 271 construction (see 
         function x12.message{} at http://wiki.interfaceware.com/425.html#message)
         as Transaction Sets get processed, or to write parsed data to database
         (see selected database related parts of example on page 
         http://wiki.interfaceware.com/1456.html), or so...
         For example:
         local Messages = {}
         Messages[1] = tostring(TS):gsub('\r','~')
         Messages[2] = In.InterchangeEnvelope.FunctionalGroup[i].GE[2]:nodeValue()
         Messages[3] = In.InterchangeEnvelope.IEA[2]:nodeValue()

function foo(n)   
   return n["Position 010"].Grp010ABCD[1].Loop2000A.Loop2100A.NM1[3]:nodeValue()

function foo2(TS)
   --[[ Please see selected database related parts from example of writing to 
   database on page http://wiki.interfaceware.com/1456.html
   return true
This code is a template for X12 parsing
Usage Details

This example helps to begin with writing an X12 parsing interface. The comments in the code explain how it works. Please pay attention to use Library VMD file respective to version of X12 you are using in real life, i.e., 4010 or 5010.

Note: The sample code is very similar to one of Lev’s tips: How to approach X12 parsing.

How to use the code:

  • Download the 270BlueCrossEdited.edi file
    Note: You will need to remove the “.txt” extension
  • Modify the MY_FILE variable (at the start of the code) to point to where you saved 270BlueCrossEdited.edi
  • Load the project zip or paste the code into a Filter or To Translator script
  • Examine the code and annotations to see how it works