This is part of my HL7 article series in which we will look at important aspect of HL7 messaging processing which is message parsing. Before we get started on this tutorial, have a quick look at my earlier article titled “A Very Short Introduction to the HL7 2.x Standard”. One of my earlier tutorials in this series titled "HL7 Programming using .NET - A Short Tutorial" gave you a foundational understanding of HL7 2.x message transmission, reception and message acknowledgement. I then introduced you to a .NET library called "NHAPI" (a port of the original Java-based HAPI HL7 framework which I covered in my previous tutorials) and showed you an example of how a HL7 message can be easily created using the library in my tutorial titled "HL7 Programming using NHAPI and .NET - Creating HL7 Messages". We also looked at how to send HL7 messages in a subsequent tutorial titled "HL7 Programming using NHAPI and .NET - Sending HL7 Messages". In this tutorial, we will explore the many ways in which you can extract HL7 message structures such as segment, fields, components, sub-components, etc using the NHAPI framework.
Tools and Resources Needed
- .NET Framework 4.5 or higher
- A .NET IDE or Editor such as Visual Studio IDE or Visual Studio Code (even a text editor should suffice)
- NHAPI GitHub page is located here
- Install NHAPI Nuget Package using NuGet Package Manager
- NHAPI Tools GitHub page is located here
- Install NHAPI Tools Nuget Package using NuGet Package Manager
- (Optional) Download HAPI Test Panel from here
- (Optional) JDK 1.4 SDK or higher (this may be required to run HAPI Test Panel)
- You can also find all the code demonstrated in this tutorial on GitHub here
“Wonder is the beginning of wisdom.” ~ Greek Proverb
NHAPI Parsers - An Overview
NHAPI provides two mechanisms for accessing message information, and these are Parsers and Tersers. They both work quite differently from each other, and in this tutorial, we will look at the parser classes and their capabilities, and what you can use them for in your HL7-enabled applications. In a subsequent tutorial in this series, we will look at tersers as well.
In the field of computer science, the word "parser" often refers to the act of breaking down a piece of text such as a sentence, a string of words or any other linguistic construct into its smaller constituent parts to aid in either the structural or the semantic understanding of that material. This deconstructed information is often displayed in the form of a "parse tree" which refers to the act of displaying this information in a tree like structure. This enables us to see the big picture as to how the various parts are related to one another. The parser classes provided by HAPI contain many useful features including being able to convert from a message string to a message object (this is referred to as "parsing"), and also convert a HL7 message object back to a string format (referred to as "encoding" a message). With these parsers, you can translate the HL7 2.x information from as well as to various formats such as ER7 (sometimes also referred to as "normal encoding") and XML when serialization to a file, a database or transmission across the network is needed.
When you are dealing with message parsing, something you will begin to really appreciate about the NHAPI library is the many strongly typed classes that it provides for dealing with nearly every HL7 message definition laid out in the various HL7 2.x standards. Since there are many versions of the HL7 2.x standard each of which consist of hundreds of message types and trigger events, hand coding parser classes can become extremely time consuming. NHAPI authors overcame this problem through a rather ingenious way by auto-generating C# class definitions based on HL7 standard's official HL7 Microsoft Access Tables containing the HL7 2.x message definitions*. The .NET classes generated by this approach help provide convenient binding interfaces that enable application programmers using the HAPI library to access as well as update message data pretty much along the same HL7 abstract message syntax model defined by the HL7 group. So, if you are looking to write code that follows the "HL7 2.x Information Model" more closely, then NHAPI parsers can assist you with that. Let us look at some examples of using NHAPI parsers now.
Basic Parser Operations
The code below demonstrates a few different operations you can perform using the parser classes. It shows how we can take a HL7 message string (in our case an ACK message response) and parse it into a HL7 message object using the PipeParser. It also shows you how when we have the information in a strongly typed HL7 message object, we can then easily access as well as update any data on the message such as a segment, field, etc. It then shows you how to use the DefaultXmlParser to encode the message object into XML format for display purposes.
Running the code above should result in the output similar to what is shown below. We are able to successfully parse the message string into a message object and able to access the message data easily. Here, I am displaying the message type, the message control id, the timestamp of when the message was origination as well as the sending facility for the message. We are also able to encode the message object into XML format for display.
Parsing of Custom Message Models
An interesting and very useful feature that parsers in NHAPI (and tools built on top of NHAPI such as "NHAPI Tools") provide is in the area of HL7 message customization. Something you will run into occasionally when dealing with HL7 2.x messaging systems is what is known as a "Z-segment". Occasionally, a requirement emerges where communication of some special type of information is required which is not easily supported by the standard message definitions that are specified in the HL7 standard. In those situations, we can create a custom segment to help transmit this custom data. The standard convention is that all these custom segments begin with the letter Z. For instance, a "ZPV" segment may be used when customized patient visit information needs to be transmitted because there is some specialization information that needs to be recorded as part of the patient visit information. Because custom segments almost always start with the letter Z, they are also referred to as Z-segments. This feature helps provide quite a bit of flexibility to HL7 message communications. However, you need to be able to handle the extraction of the data from Z-segment when this is the case. Writing this parsing logic can be quite tricky as you need to handle the parsing of the entire message and the other message structures contained in it as well. I will show two different approaches for extracting Z-segment data from HL7 messages. The first approach will be by using the extensibility offered by the NHAPI library and the second approach will be by using another third-party library built on top of NHAPI called NHAPI Tools).
Approach 1 - Parsing of Custom Message Models using NHAPI
Step 1 of 3 - Create a Z-segment Class
First, we need to create an new HL7 segment definition that we will store our custom fields. We do this by extending the Abstract Segment class that comes with NHAPI that provides a lot of pre-built functionality to manage segment data. This abstract class assists in providing useful methods to help initialize the various fields contained in the messages. We utilize the add method that is already implemented in the abstract this class to define as well as initialize the fields in this segment. In the example below, I am defining two custom fields named "custom notes" and "custom description" that are both of ST data type, but you can implement fields using whatever data type that is supported in the HL7 standard. For the two custom fields, I am also specifying other characteristics such as whether the field is mandatory, the number of repetitions of this field as well as the field length.
“The clearest way into the Universe is through a forest wilderness.” ~ John Muir
Step 2 of 3 - Create a Specialized Class by Extending the ADT A01 Message Class
We need to define a new message type to carry the z-segment we just defined earlier as we need to inform the receiving system that this message is not a normal ADT A01 message. Here we are simply extending the ADT A01 message class provided by the NHAPI library and are adding additional behavior to support the new message segment. This approach enables us to build on the behavior already provided by the ADT A01 message class and the other classes and interfaces that it extends or implements already. As you can see in the code below, we are specifying some additional behavior in the constructor of this new message type class by invoking the Init method and are asking it to include new z-segment to its normal payload using the new z-segment class that we previously created and are marking it is a mandatory.
Step 3 of 3 - Stitch The Behavior Together
In this last step, we bring all these specialized behaviors together to help parse the new message type successfully. The NHAPI pipe parser helps load as well as parse the HL7 message string into the custom ADT_A01 message. We can then extract the custom ZPV message segment including the custom message data from this message as shown in the code illustration below. Please note that some additional configuration is needed for the parser class to load the necessary classes during the parse operation. Please have a look at the Readme.txt file included with the sample project in GitHub for additional instructions.
The results of running the main program above are shown below. By using an approach such as this, we reduce the amount of code we otherwise need to write and support in our custom HL7 applications. If you are interested in exploring this area further, you should look up the official NHAPI source code and/or documentation for more information. While on the topic of Z-segments, I would ask you to be careful around the amount of customization you generally do as this tends to decrease the interoperability and supportability of the overall system especially if the remote systems are upgraded or when new systems come onboard. Besides, the standard already provides support for most scenarios anyway, and so you should always look at the HL7 official documentation before deciding to use Z-segments as there may be ways to do what you are looking for already.
Approach 2 - Parsing of Custom Message Models using NHAPI Tools
Yet another way of extracting Z-segment data from customized HL7 messages is by using a facility in NHAPI Tools called the GenericMessageWrapper class. In this approach, we still define the custom Z-segment and the custom HL7 message class as we did in the previous approach (see steps 1 and 2). However, the third step of message extraction works slightly differently. Here, we simply parse the HL7 message data into a generic HL7 message structure using the GenericMessageWrapper class which works in conjunction with the EnhancedModelClassFactory class under the covers and provides a convenient method to get at all the segments that are contained in a generic message object using the Unwrap method. We then check to see if this generic HL7 message object contains the custom segment that we are interested in and extract it if it exists. Some additional configuration is required in the App.Config file to help the class loader of NHAPI parser to look for the custom HL7 message definition that we previously defined in a separate .NET project that is referenced by the main project. Please have a look at the Readme.txt file included with the sample project in GitHub for additional instructions.
The results of running the main program above are shown below. As you can see, both approaches outlined here can get the job done for us. I will leave it to you to decide which approach you like and want to employ in your custom application.
That brings us to the end of yet another tutorial on using the NHAPI HL7 library. We looked at some basic message parsing capabilities provided in the NHAPI library. The various parser classes provided by this library help us to convert messages from and to various formats such as ER7, XML, etc. We also looked at how the parser classes in the NHAPI library enable us to process special Z-segments when site-specific customizations are in place. I showed you two different approaches that you can use during custom message parsing (one using the core NHAPI library and another approach using the NHAPI Tools library). By using the various classes provided by the NHAPI library and by the NHAPI Tools framework, application programmers can reduce the time required to create and/or extend HL7 2.x message-enabled applications especially when we need to process many different message types or trigger events. In the next tutorial in my HL7 article series, we will look at tersers quickly before moving on to review the more advanced features provided by the parser classes such as message validation and message reception. See you then!
* - Always consult the official HAPI and HL7 documentation for latest information as this may change or may have changed already.