This is a fork from Jayant Singh's HL7 parser. Since then, it has been modified fundamentally, with respect to features, code quality, bugs and typos. For more information about the original implementation read:
The field encoding and decoding methods have been based on https://github.com/elomagic/hl7inspector
Since version 2.9, the MSH segment will have an extra field at the beginning of the segment list, containing the field separator. This is according to the HL7 standard, as mentioned in Issue #26. Every field index in that segment should be increased by one.
Since version 2.9, some previously deprecated methods starting with lowercase have been removed. The replacement methods starting with uppercase shall be used instead.
Message message = new Message(strMsg);
// Parse this message
bool isParsed = false;
try
{
isParsed = message.ParseMessage();
}
catch(Exception ex)
{
// Handle the exception
}
For adding a header segment to a new message object, use the AddSegmentMSH()
method, after constructing an empty message:
message.AddSegmentMSH(sendingApplication, sendingFacility,
receivingApplication, receivingFacility,
security, messageType,
messageControlId, processingId, version);
If the HL7 message is coming from a MLLP connection (see the official documentation), the message needs to be cleared from the MLLP prefixes and suffixes. Also, consider there can be more than one message in a single MLLP frame.
For this purpose, there is an ExtractMessages()
method, to be used as follows:
// extract the messages from a buffer containing a MLLP frame
var messages = MessageHelper.ExtractMessages(buffer);
// construct and process each message
foreach (var strMsg in messages)
{
Message message = new Message(strMsg);
// do something with the message object
}
List<Segment> segList = message.Segments();
For example if there are multiple IN1 segments
List<Segment> IN1List = message.Segments("IN1");
Note index 1 will return the 2nd element from list
Segment IN1_2 = message.Segments("IN1")[1];
int countIN1 = message.Segments("IN1").Count;
Segment IN1 = message.DefaultSegment("IN1");
// OR
Segment IN1 = message.Segments("IN1")[0];
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;
bool isComponentized = message.Segments("PID")[0].Fields(5).IsComponentized;
// OR
bool isComponentized = message.IsComponentized("PID.5");
bool isRepeated = message.Segments("PID")[0].Fields(3).HasRepetitions;
// OR
bool isRepeated = message.HasRepetitions("PID.3");
List<Field> repList = message.Segments("PID")[0].Fields(3).Repetitions();
Field PID3_R2 = message.Segments("PID")[0].Fields(3).Repetitions(2);
message.SetValue("PV1.2", "I");
// OR
message.Segments("PV1")[0].Fields(2).Value = "I";
string version = message.Version;
string msgControlID = message.MessageControlID;
string messageStructure = message.MessageStructure;
string PatName1 = message.GetValue("PID.5.1");
// OR
string PatName1 = message.Segments("PID")[0].Fields(5).Components(1).Value;
bool isSubComponentized = message.Segments("PV1")[0].Fields(7).Components(1).IsSubComponentized;
// OR
bool isSubComponentized = message.IsSubComponentized("PV1.7.1");
message.Segments("PID")[0].Fields(5).Components(1).Value = "Jayant";
// OR
message.SetValue("PID.5.1", "Jayant");
//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, for inserting 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||||ZIB5^ZIB.5.2
After evaluated and modified required values, the message can be obtained again in text format
string strUpdatedMsg = message.SerializeMessage();
Some contents may contain forbidden characters like pipes and ampersands. Whenever there is a possibility of having those characters, the content shall be encoded before calling the 'AddNew' methods, like in the following code:
var obx = new Segment("OBX", new HL7Encoding());
// Not encoded. Will be split into parts.
obx.AddNewField("70030^Radiologic Exam, Eye, Detection, FB^CDIRadCodes");
// Encoded. Won't be parsed nor split.
obx.AddNewField(obx.Encoding.Encode("domain.com/resource.html?Action=1&ID=2"));
The DeepCopy method allows to perform a clone of a segment when building new messages. Countersense, if a segment is referenced directly when adding segments to a message, a change in the segment will affect both the origin and new messages.
Segment pid = ormMessage.DefaultSegment("PID").DeepCopy();
oru.AddNewSegment(pid);
To generate an ACK message
Message ack = message.GetACK();
To generate negative ACK (NACK) message with error message
Message nack = message.GetNACK("AR", "Invalid Processing ID");
It may be required to change the application and facility fields
Message ack = message.GetACK();
ack.SetValue("MSH.3", appName);
ack.SetValue("MSH.4", facility);