HL7 Fundamentals


This article contains an overview of using HL7 with Iguana Translator. We suggest you read the full article for a basic understanding of how Iguana works with databases, or atleast skim the the article – you can always come back later and read relevant sections in more depth.

For more specific database techniques and best practices read Working with HL7.

Creating HL7 interfaces in Iguana follows a simple repeatable pattern:

  • Parse the incoming HL7 messages into a read-only data structure
  • Create a writable outgoing message structure
  • Translate/map your messages into the outgoing message
  • Filter out any unwanted messages
  • Deal with unknown message types

The following pages in this article give a brief description of these stages. We also discuss what to expect in a VMD file structure.

Parse messages with hl7.parse{} [top]

This function if successful will return an HL7 ‘node tree’. The function takes the vmd file which defines the schema to parse the HL7 data with and the HL7 message to be parsed.

The function returns two values. The first is the ‘node tree’ representing the data and the second is the name of the message rule that was used to parse the data. How the message is parsed is highly dependent on the configuration of the vmd file used. The message rules are defined within the demo.vmd file.

This dialog is displayed for this example message:

This page shows what to expect when you open the demo.vmd within Chameleon and see the message rules.

This is the API Reference for hl7.parse{}

Generate messages with hl7.message{} [top]

To generate an empty HL7 message which we can populate with data the API to use is hl7.message{}.

This is an example of it’s usage:

  • The arguments are a vmd file and a name of a message defined in the vmd file
  • This returns an empty node tree which can then be populated with data

This is the API Reference for hl7.message{}

Translating HL7 [top]

Translating HL7 messages using the Iguana Translator is easy.

It’s best to begin with a simple example:

This code would typically go into a Translator filter, so the channel configuration would look something like this:

Where the Source and Destination components would be a LLP Listener and a LLP Client component. Here’s the source code to the module:

function main(Data)
   local MsgIn = hl7.parse{vmd='example/demo.vmd', data=Data}
   local Out = hl7.message{vmd='example/demo.vmd', 

   Out:mapRange(MsgIn, 1)

   Out.MSH[4][1] = 'Acme'


See Also

How to filter messages [top]

Ignoring specific messages can be done very easily. Simply omit running the queue.push{data=Data} in a Translator Filter instance for all the HL7 messages you wish to filter out.

You can apply any arbitrary logic you like to exclude messages from being processed.

For example:

Here’s the code in a format you can copy.

function main(Data)
   local Msg = hl7.parse{data=Data, vmd='demo.vmd'}

   if Msg.PID[5][1][1][1]:nodeValue() == 'Adams' then
      iguana.logInfo('Adams family not welcome here!  Filtering message!')

See Also

Strategies for dealing with unknown messages [top]

It’s common in HL7 interfaces to set up a default message in the VMD file which will be invoked when an unrecognized message is found. See what to expect in the vmd file.

If you do have messages encountered that are picked up by the default message matching rule it’s easy to choose what to do with them. You can raise an error, log a warning or do whatever you want to do to make it easy to reprocess these messages at a later stage.

Handling different versions of HL7 [top]

Iguana supports all the standard versions of HL7. The main thing to keep in mind with HL7 however is that there is very little standardization in the protocol.

Typically real world HL7 interfaces are thin wrappers around the structure of the databases that populate them. All the flaws and limitations of the data as expressed in the database will be mirrored in the HL7 interfaces.

i.e. if a system doesn’t have separate fields for last name and first name then you can expect its HL7 interface will just have the name in one field. All this good fun is why you need to have an interface engine in the first place.

See the article on Technological and Social Change to get more of a feel for the issue.

Understanding the Structure of the demo.vmd file [top]

This screen shot shows the workspace in Chameleon of the demo.vmd file used in the hl7.parse{} example:

You can see there are three ‘message rules’ defined:

  • ADT – matches all messages with MSH.9.1 set to ‘ADT’
  • ORU – matches all messages with MSH.9.1 set to ‘ORU’
  • Catchall – matches everything else.

To see the matching rules you can double click to see the Identity window for each message rule:


This matches all messages that have ‘ADT’ in MSH.9.1


This matches all messages that have ‘ORU’ in MSH.9.1.


The Catchall message is the ‘wildcard’ message in that it matches everything not matches by the other rules. It’s defined that way by clicking on the second Change… button, this brings up the Message Definition Matching Order screen:

This should make it more clear what the relationship between the ‘Name’ return value from the hl7.parse{} function and the associated vmd file.

Leave a Reply