web stats
Extracting individual fields from pipe-delimited HL7 as raw HL7? - Mirth Community

Go Back   Mirth Community > Mirth Connect > Support

Reply
 
Thread Tools Display Modes
  #1  
Old 04-18-2018, 11:06 AM
jridderhoff jridderhoff is offline
OBX.1 Kenobi
 
Join Date: Jan 2015
Posts: 42
jridderhoff is on a distinguished road
Default Extracting individual fields from pipe-delimited HL7 as raw HL7?

I'm trying to fulfill a bit of an odd request. At first blush, I thought I'd be able to do this in Mirth, but actually trying to implement it, I'm starting to think I'm going to have to go a different route.

I've got a need to take raw, pipe-delimited HL7 messages, pull out selected fields from various segments (as they appear in the raw HL7 messages), and stick them in an output file. Problem is, no matter what I seem to try to do, once I've got the message to a point I can actually get the individual fields, they're in E4X, and there's no way to re-serialize XML fragments to their pipe-delimited format.

To put it another way, for instance, I have a message where I want to get back the entire MSH.4 field out, along with all the carets & other delimiters within it (e.g. "ARUP LABORATORIES^46D0523979^CLIA", and stick it in an output file. But, if I do anything in the transformers to let me get the MSH.4 field, it's an E4X object, and all I get out is the E4X representation of it (e.g. <MSH.4><MSH.4.1>ARUP LABORATORIES</MSH.4.1><MSH.4.2>46D0523979</MSH.4.2><MSH.4.3>CLIA</MSH.4.3></MSH.4>).

Am I missing a trick for doing what I need, or am I just stuck and need to get to the brute force way of string splitting & counting?
Reply With Quote
  #2  
Old 04-18-2018, 10:43 PM
aTom aTom is offline
OBX.3 Kenobi
 
Join Date: Feb 2016
Location: Lake Geneva Area
Posts: 115
aTom is on a distinguished road
Default

Hi,

Tricky but will work :

Code:
var myField = <HL7Message/>;
myField.appendChild(msg['MSH']['MSH.4']);
var delimited = SerializerFactory.getSerializer('HL7V2').fromXML(myField); // will contain "|||ARUP LABORATORIES^46D0523979^CLIA|"
delimited = delimited.replace("|", '');
__________________
Tom

Last edited by aTom; 04-18-2018 at 10:51 PM.
Reply With Quote
  #3  
Old 04-19-2018, 12:37 AM
AlexNeiva AlexNeiva is offline
Mirth Guru
 
Join Date: Oct 2013
Location: Portugal
Posts: 282
AlexNeiva is on a distinguished road
Default

Hello,

you can also set the inbound messages as Delimited Text where the delimiter is '|' and just get the complete MSH.4 field using:

Code:
msg['row'][0]['column4'].toString();
Best Regards
__________________
Best Regards,
Alex Neiva
Reply With Quote
  #4  
Old 04-19-2018, 07:59 AM
agermano agermano is offline
Mirth Guru
 
Join Date: Apr 2017
Location: Indiana, USA
Posts: 1,176
agermano is on a distinguished road
Default

You can also join the components yourself

Code:
var msh_4 = [];
for each (component in msg['MSH']['MSH.4'].children()) {
  msh_4.push(component.toString());
}
msh_4 = msh_4.join('^');
Reply With Quote
  #5  
Old 04-19-2018, 04:12 PM
jridderhoff jridderhoff is offline
OBX.1 Kenobi
 
Join Date: Jan 2015
Posts: 42
jridderhoff is on a distinguished road
Default

Quote:
Originally Posted by agermano View Post
You can also join the components yourself

Code:
var msh_4 = [];
for each (component in msg['MSH']['MSH.4'].children()) {
  msh_4.push(component.toString());
}
msh_4 = msh_4.join('^');
Thanks, guys!

agermano, I ended up going down the road you suggested, even taking it a bit further to the point of making a recursive function that'll rebuild the field, even including repeating fields. I've still got one pesky problem, but here's what I did in case it helps anyone else:

Code:
function xmlToPipes(nodeList, joinStrArray, joinStrIdx) {
	var elementList = [];

	for each (node in nodeList) {
		var nodeChildren = node.elements();
		if (nodeChildren.length() > 0) {
			elementList.push(xmlToPipes(nodeChildren, joinStrArray, joinStrIdx+1));
		} else {
			elementList.push(node.toString());
		}
	}

	return elementList.join(joinStrArray[joinStrIdx]);
}
...and then later, you can call...

Code:
var msh4 = xmlToPipes(msg['MSH']['MSH.4'], ["~", "^", "&"], 0);
Running that, an input XML of "<MSH.4><MSH.4.1>ARUP LABORATORIES</MSH.4.1><MSH.4.2>46D0523979</MSH.4.2><MSH.4.3>CLIA</MSH.4.3></MSH.4>" comes back out properly as "ARUP LABORATORIES^46D0523979^CLIA".

Where it gets icky still, and I haven't yet figured out what to do about it, is if you have blank components/sub-components. For example, if the reporter only sent MSH.4.1 and MSH.4.3, the serializer omits the <MSH.4.2/> tag altogether, and you end up getting back something like "ARUP LABORATORIES^CLIA" instead of the "ARUP LABORATORIES^^CLIA" value you had originally.

Somehow, I've got to make it aware enough to insert blanks where there are missing tags... maybe after more coffee.

Thanks again for the suggestions, hope my update helps somebody else down the road.
Reply With Quote
  #6  
Old 04-20-2018, 10:04 AM
jridderhoff jridderhoff is offline
OBX.1 Kenobi
 
Join Date: Jan 2015
Posts: 42
jridderhoff is on a distinguished road
Default Final updated function

After a little bit of logic headbashing, I was able to update the function to handle re-inserting the empty fields and completely replicate the original HL7 text delimited representation of the field. I realize this is probably beyond niche, but hey, in case it helps anybody else out, here it is in full.

This should handle repeating fields as well, as long as you make sure to pass in the proper delimiters in the joinStrArray as documented.

The function:
Code:
/**
 * Function to convert an E4X XML fragment representing an HL7 field into its original HL7 text representation
 * 
 * @param XMLList nodeList         XML representing the field to translate.
 * @param array   joinStrArray     Array containing your HL7 delimiters for repeating fields, components, and subcomponents
 * @param int     joinStrIdx       Index representing the current delimiter in joinStrArray to use (should be 0 on first call)
 * @param int     startComponentId Used for recursion; leave null for first call. (Represents the sub-field element the function is starting from.)
 *
 * @return string
 */
function xmlToPipes(nodeList, joinStrArray, joinStrIdx, startComponentId) {
	var elementList = [];
	var componentIndex = null;

	if (startComponentId !== undefined) {
		componentIndex = parseInt(startComponentId);
	}

	for each (node in nodeList) {
		var nodeChildren = node.elements();
		var nodeNameParts = node.name().toString().split('.');
		var nodeComponentIndex = parseInt(nodeNameParts.pop());
		
		if (componentIndex === null) {
			componentIndex = nodeComponentIndex;
		}
		
		var componentIndexDiff = nodeComponentIndex - componentIndex;
		
		if (componentIndexDiff > 0) {
			for (var i = 0; i < componentIndexDiff; i++) {
				elementList.push('');
				componentIndex++;
			}
		}

		if (nodeChildren.length() > 0) {
			elementList.push(xmlToPipes(nodeChildren, joinStrArray, joinStrIdx+1, 1));
		} else {
			elementList.push(node.toString());
		}

		componentIndex++;
	}

	return elementList.join(joinStrArray[joinStrIdx]);
}
Usage example:
Code:
// array should contain HL7 delimiters you use for (in order) repeating fields, components, and subcomponents
var joinStrStarterArray = ["~", "^", "&"];

var msh4 = xmlToPipes(msg['MSH']['MSH.4'], joinStrStarterArray, 0);
var pid3 = xmlToPipes(msg['ORU_R01.PATIENT_RESULT']['ORU_R01.PATIENT']['PID']['PID.3'], joinStrStarterArray, 0);
Thanks again for everybody's help!
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -8. The time now is 04:12 AM.


Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2020, vBulletin Solutions, Inc.
Mirth Corporation