I learned a little bit of nHAPI during my last post on HL7 over HTTP and wanted to use it for a utility that I am working on. But some more research on nHAPI influenced me to develop my own small library in C#.
nHAPI is a great library and I do not want to compete with it. One of the reasons I decided to write a small library is I needed very basic features like read any HL7 message, evaluate some fields, update some fields, get updated HL7 message, generate ACKs. At this time I have decided to overlook message type or trigger event specific features/validations. However it performs basic validations to ckeck message header, format of segment names, delimiters etc.
This library treats every message in same manner while parsing HL7 messages. After successfull parsing it provides all the components of HL7 message like segments, fields (with repetitions), components, subcomponents in easily accessible way.
I do not want to claim it as HL7 Parsing Library. But it provides some basic features and simple ways to access those features.
Now let’s see how to use this library:
Create a Message object and pass raw HL7 message in text format
Message message = new Message(strMsg);
Parse this message
bool isParsed = false;
try
{
isParsed = message.ParseMessage();
}
catch(Exception ex)
{
//handle the exception
}
Now let’s see some of the functions, Please note indexes are zero based, so if you access FieldList[3], it’s actually a fourth field.
Accessing Segments
Get list of all segments
List<Segment> segList = message.Segments();
Get List of list of repeated segments by name For example if you have multiple IN1 segments
List<Segment> IN1List = message.Segments("IN1");
access a particular occurrence from multiple IN1s you can provide the index, please note index 1 will give you 2nd element from list
Segment IN1_2 = message.Segments("IN1")[1];
Get count of IN1s
int countIN1 = message.Segments("IN1").Count;
Access first occurrence of any segment
Segment IN1 = message.DefaultSegment("IN1");
//OR
Segment IN1 = message.Segments("IN1")[0];
Accessing Fields
Access field values
String SendingFacility = message.getValue("MSH.4");
//OR
String SendingFacility = message.DefaultSegment("MSH").Fields(4).Value;
//OR
String SendingFacility = message.Segments("MSH")[0].Fields(4).Value;
Check if field is componentized
bool isComponentized = message.Segments("PID")[0].Fields(5).IsComponentized;
//OR
bool isComponentized = message.IsComponentized("PID.5");
Check if field has repetitions
bool isRepeated = message.Segments("PID")[0].Fields(3).HasRepetitions;
//OR
bool isRepeated = message.HasRepeatitions("PID.3");
Get list of repeated fields
List<Field> repList = message.Segments("PID")[0].Fields(3).Repetitions();
Get particular repetition i.e 2nd repetition of PID.3
List<Field> repList = message.Segments("PID")[0].Fields(3).Repetitions();
Update value of any field i.e. to update PV1.2 – patient class
message.setValue("PV1.2", "I");
//OR
message.Segments("PV1"[0];).Fields(2).Value = "I";
You can access some of the required MSH fields with properties
String version = message.Version;
String msgControlID = message.MessageControlID;
String messageStructure = message.MessageStructure;
Accessing Components
Access particular component i.e. PID.5.1 – Patient Family Name
String PatName1 = message.getValue("PID.5.1");
//OR
String PatName1 = message.Segments("PID")[0].Fields(5).Components(1).Value;
Check if component is sub componentized
bool isSubComponentized = message.Segments("PV1")[0].Fields(7).Components(1).IsSubComponentized;
//OR
bool isSubComponentized = message.IsSubComponentized("PV1.7.1");
Update value of any component
message.Segments("PID")[0].Fields(5).Components(1).Value = "Jayant";
//OR
message.setValue("PID.5.1", "Jayant");
Adding new Segment
//Create a Segment with name ZIB
Segment newSeg = new Segment("ZIB");
//Create Field ZIB_1
Field ZIB_1 = new Field("ZIB1");
//Create Field ZIB_5
Field ZIB_5 = new Field("ZIB5");
//Create Component ZIB.5.2
Component com1 = new Component("ZIB.5.2");
//Add Component ZIB.5.2 to Field ZIB_5
//2nd parameter here specifies the component position, if you want to insert segment on particular position
//If we don’t provide 2nd parameter, component will be inserted to next position (if field has 2 components this will be 3rd, if field is empty this will be 1st component
ZIB_5.AddNewComponent(com1, 2);
//Add Field ZIB_1 to segment ZIB, this will add a new filed to next field location, in this case first field
newSeg.AddNewField(ZIB_1);
//Add Field ZIB_5 to segment ZIB, this will add a new filed as 5th field of segment
newSeg.AddNewField(ZIB_5, 5);
//add segment ZIB to message
message.AddNewSegment(newSeg);
New Segment would look like this
ZIB|ZIB1||||^ZIB.5.2
After you have evaluated and modified required values you can again get the message in text format
String strUpdatedMsg = message.SerializeMessage();
Generate ACKs
AA ACK
String ackMsg = message.getACK();
To generate negative ACK message with error message
String ackMsg = message.getNACK("AR", "Invalid Processing ID");
This is my small library to parse HL7 messages.
I welcome any comments/criticism to help improve this.