You are here: Jython Script Interfaces > Jython Code Examples for the Custom Task

Jython Code Samples for the Custom Task

 

Working with HL7 messages - getting and setting fields, optionally cancelling branch

hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom) 

gender = hl7msg.getField("PID", 8)
if gender in ['m', 'M', 'Male', 'male']:
hl7msg.setField('Male', "PID", 8)
elif gender in ['f', 'F', 'Female', 'female']:
hl7msg.setField('Female', "PID", 8)
else:
print >> engine.logwarn,'Execution cancelled due to incorrect patient gender.'
engine.cancel()

engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', hl7msg)

Input message:

MSH|^~\&|LAB|101|||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|3|TX|88304&MDT|1|MICROSCOPIC EXAM

Ouput message:

MSH|^~\&|LAB|101|||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|Female
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|3|TX|88304&MDT|1|MICROSCOPIC EXAM SHO


Working with HL7 messages - getting and setting components

hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)

eventType = hl7msg.getComponent("MSH", 9, 2)
patientId = hl7msg.getField("MRG", 1)
mrgField2Rep3 = hl7msg.getField("MRG", (2, -1))

if (eventType == "A06") and (int(patientId) > 1000) and (mrgField2Rep3 == "z"):
hl7msg.setComponent("xyz", "MRG", (3, 2), 4)
else:
engine.cancel()

engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', hl7msg)

Input message:

MSH|^~\&|1.5|101|||20110915124025||ADT^A06||P|2.3.1
EVN|A06|20130530||
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
MRG|1001|x~y~z|1~a^^^||||

Output message:

MSH|^~\&|1.5|101|||20110915124025||ADT^A06||P|2.3.1
EVN|A06|20130530||
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
MRG|1001|x~y~z|1~a^^^xyz||||


Removing HL7 segments

This code removes all the NK1 segments from the HL7 message:

hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
while hl7msg.numSegmentsWithId('NK1') > 0:
hl7msg.removeSegment('NK1')
engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', hl7msg)

This code keeps only the first NK1 segment in the HL7 message:

hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
while hl7msg.numSegmentsWithId('NK1') > 1:
hl7msg.removeSegment(('NK1', -1))
engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', hl7msg)  

Removing HL7 segments under certain conditions - remove all OBX segments that have an empty fifth field.

def removeOBXsWithBlankField5(hl7msg_):
segIdx = 1
while segIdx <= hl7msg_.numSegmentsWithId('OBX'):
if hl7msg_.getField(('OBX', segIdx), 5) == "":
hl7msg_.removeSegment(('OBX', segIdx))
segIdx -= 1
segIdx += 1

# After removing some of the OBX segments, there might be gaps in the indexes in OBX-1 -
# that is, the message might look like this:
# OBX|1|ST|...
# OBX|2|CE|...
# OBX|4|TX|...
# OBX|6|TX|...
# Note that '3' and '5' are skipped. This function will set those indexes to 1, 2, 3, 4.
def fixOBXsIds(hl7msg_):
segIdx = 1
while segIdx <= hl7msg_.numSegmentsWithId('OBX'):
hl7msg_.setField(str(segIdx), ('OBX', segIdx), 1 )
segIdx += 1

hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
removeOBXsWithBlankField5(hl7msg)
fixOBXsIds(hl7msg)
engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', hl7msg)

Input message:

MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|1|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||
OBX|2|CE|88304|1|T57000^GALLBLADDER^SNM
OBX|3|CE|88304|1|||
OBX|4|TX|88304&MDT|1|MICROSCOPIC EXAM SHOWS HISTOLOGICALLY NORMAL GALLBLADDER TISSUE
OBX|5|TX|88305|1|||
OBX|6|TX|88304|1|ORDER DATE: 20110815|

Output message:

MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|1|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||
OBX|2|CE|88304|1|T57000^GALLBLADDER^SNM
OBX|3|TX|88304&MDT|1|MICROSCOPIC EXAM SHOWS HISTOLOGICALLY NORMAL GALLBLADDER TISSUE
OBX|4|TX|88304|1|ORDER DATE: 20110815|



Splitting one segment into multiple segments (split long NTE-3 values)

def insertMultipleNTEs(hl7msg_, pos_, origNTESeg_, comments_):
for i in range(len(comments_)):
newNTESeg = origNTESeg_.clone()
newNTESeg.setField(comments_[i], 3)
hl7msg_.addSegment(pos_, newNTESeg)
pos_ = pos_ + 1

def splitNTEsByCommentWidth(hl7msg_, width_):
for segIdx in range(hl7msg_.numSegments(), 0, -1): #iterate in reverse
hl7seg = hl7msg_.getSegment(segIdx)
if hl7seg.getSegmentName() == 'NTE':
origNTESeg = hl7seg
comment = origNTESeg.getField(3)
comments = util.splitTextByWidth(comment, width_)
hl7msg_.removeSegment(segIdx) #remove orig NTE
insertMultipleNTEs(hl7msg_, segIdx, origNTESeg, comments)
return hl7msg_

def fixNTEsIds(hl7msg_):
idx = None
for segIdx in range(1, hl7msg_.numSegments() + 1):
hl7seg = hl7msg_.getSegment(segIdx)
if hl7seg.getSegmentName() == 'NTE':
if idx == None:
idx = 1
hl7seg.setField(str(idx), 1)
idx = idx + 1
else:
idx = None

hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
newHl7msg = splitNTEsByCommentWidth(hl7msg.clone(), 40)
fixNTEsIds(newHl7msg)
engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', newHl7msg)

Input message:

MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|70||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|20|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||
NTE|1|20|The erythrocyte sedimentation rate (ESR), also called a sedimentation rate or Westergren ESR, is the rate at which red blood cells sediment in a period of one hour.
NTE|2|20| is the rate at which red blood cells sediment in a period of one hour.
OBX|21|CE|88304|1|T57000^GALLBLADDER^SNM
NTE|1|21|In vertebrates the gallbladder (cholecyst, gall bladder, biliary vesicle) is a small organ that aids mainly in fat digestion and concentrates bile produced by the liver.|FT
OBX|22|TX|88304&MDT|1|MICROSCOPIC EXAM SHOWS HISTOLOGICALLY NORMAL GALLBLADDER TISSUE

Output message:

MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|70||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|20|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||
NTE|1|20|The erythrocyte sedimentation rate
NTE|2|20|(ESR), also called a sedimentation
NTE|3|20|rate or Westergren ESR, is the rate at
NTE|4|20|which red blood cells sediment in a
NTE|5|20|period of one hour.
NTE|6|20| is the rate at which red blood cells
NTE|7|20|sediment in a period of one hour.
OBX|21|CE|88304|1|T57000^GALLBLADDER^SNM
NTE|1|21|In vertebrates the gallbladder |FT
NTE|2|21|(cholecyst, gall bladder, biliary |FT
NTE|3|21|vesicle) is a small organ that aids |FT
NTE|4|21|mainly in fat digestion and |FT
NTE|5|21|concentrates bile produced by the |FT
NTE|6|21|liver.|FT
OBX|22|TX|88304&MDT|1|MICROSCOPIC EXAM SHOWS HISTOLOGICALLY NORMAL GALLBLADDER TISSUE

 

 


HL7 - alternate syntax

In addition to the getField / getComponent (and setField / setComponent) functions described above, there is an alternate syntax based on two functions: "get" and "set". For example, consider this HL7 message:

MSH|^~\&|LAB||||20170915124025||ORU^R01||P|2.6
PID|201||1200^^^other~1201^^^self~1202^^^hosp||PARRISH^JESSICA||1960/11/21|F
OBX|1|CE|Volume||30|mm3
OBX|2|CE|Mass||37|mg
OBX|3|CE|Score^^ScoringSystem1||1.3|
OBX|4|CE|Score^^ScoringSystem2||5.7|

 

To retrieve simple fields and components:  

hl7msg.get('MSH-3') returns 'LAB'

hl7msg.get('MSH-9-2') returns 'R01'

hl7msg.get('PID-3') returns '1200^^^other~1201^^^self~1202^^^hosp'

To specify field repetitions numerically:

hl7msg.get('PID-3[2]') returns '1201^^^self'

hl7msg.get('PID-3[2]-1') returns '1201'

To specify field repetitions based on a component value:

hl7msg.get('PID-3[^4=self]-4') returns '1201'

To specify segment repetitions numerically: 

hl7msg.get('OBX[2]-3') returns 'Mass'

To specify segment repetitions based on a field value: 

hl7msg.get('OBX[|3=Score^^ScoringSystem2]-5') returns '5.7'

To specify segment repetitions based on a component value: 

hl7msg.get('OBX[|3-3=ScoringSystem2]-5') returns '5.7'

To set a value, using any of the "get" syntax above:

hl7msg.set('PID-3[^4=self]-4', 'zzz')



Lookup Tables


From a Jython script you can also perform a lookup from a text file in "CSV" (comma separated values) format.  If you have a spreadsheet in, for example, Microsoft Excel, you must first export ("Save As") your spreadsheet to CSV format.  Then you can, from your Jython script, tell MD Link to read this file and get values from it.

In this example text file, the first column is a person's name, the second their gender, the third their bed number, and the fourth the floor that bed is on.

For our example here, the lookupFile.csv contains three lines:

Richard,M,403,4
Jessica,F,115,1
Steve,M,320,3

path = r'c:\cygwin\tmp\lookupFile.csv'

# Note: The "createLookupTable" line can go here, in the "Run" script, but for better performance,
# put it in the "Load" script of your Custom Task.
lookup = util.createLookupTable(path, valuecolumn = 3)

bedNum = lookup.getValue('Richard')
print bedNum # Will print '403' to the MD Link logs
print lookup.getValue('Jessica') # Will print '115'
print lookup.getValue('Maria') # This will fail the execution, because 'Maria' is not in the table.

lookup = util.createLookupTable(path, valuecolumn = 3, defaultvalue = 'XYZ')
print lookup.getValue('Maria') # This will now print 'XYZ'.
# It will no longer fail the execution, because we provided a default value in the "createLookupTable" line.

lookup = util.createLookupTable(path, valuecolumn = 3, defaultaction = 'passthrough')
print lookup.getValue('Maria') # This will print 'Maria', because we specified 'passthrough' as the default action.

lookup = util.createLookupTable(path, ignorecase = True, valuecolumn = 3)
print lookup.getValue('richard') # Will print '403'
print lookup.getValue('JESSICA') # Will print '115'

lookup = util.createLookupTable(path, keycolumn = 3, valuecolumn = 1)
print lookup.getValue('115') # Will print 'Jessica'
print lookup.getValue('320') # Will print 'Steve'

Manipulating dates and times

MD Link Jython API provides several functions for managing date and time values:

currentDate = util.getCurrentDateTime('yyyyMMdd') # Will set 'currentDate' to, for example, '20130530'. 

timeFromMsg = "2011/10/23-09:34:50:123"
msgDate = util.convertDateTimeFormat(timeFromMsg, 'yyyy/MM/dd-HH:mm:ss:SSS', 'yyyyMMdd') # Sets msgDate to '20111023'

print util.dateIsGreaterThanOrEqualTo(msgDate, currentDate) # Prints 'False'
newMsgDate = util.addToDate(msgDate, 'YEAR', 3) # Sets newMsgDate to '20141023'.
print util.dateIsGreaterThanOrEqualTo(newMsgDate, currentDate) # Prints 'True'.

currentTime = util.getCurrentDateTime('HHmmssSSS') # Sets currentTime to, for example, '051425893'.
msgTime = util.convertDateTimeFormat(timeFromMsg, 'yyyy/MM/dd-hh:mm:ss:SSS', 'HHmmssSSS') # Sets msgTime to '093450123'.

if util.timeIsGreaterThanOrEqualTo(msgTime, currentTime):
print 'Timestamp in message is in the future.' # (Or, technically, in the present millisecond.)
else:
print 'Input msg time is in the past.'

newMsgTime = util.addToTime(msgTime, 'HOUR', -6) # This sets 'newMsgTime' to 'msgTime' minus 6 hours.
# For example, if msgTime was '093450123' (9:34 AM) then newMsgTime will be '033450123' (3:34 AM).



Outputting custom XML elements

HL7-based solutions in MD Link are usually simple from the XML perspective.  Their XML contains a single element, which contains a single string value - which is the HL7 message content.  However MD Link and the Custom Task's Jython API are not limited to this.  You can also create an XML structure which contains multiple XML elements and string values from your Jython code:
today = util.getCurrentDateTime('yyyyMMdd') #20110322
yesterday = util.addToDate(today, 'DAY', -1)

today = util.convertDateTimeFormat(today, 'yyyyMMdd', 'MM/dd/yyyy')
yesterday = util.convertDateTimeFormat(yesterday, 'yyyyMMdd', 'MM/dd/yyyy')

engine.outputDom = util.makeXMLDocument('TaskData')
util.addXMLElement(engine.outputDom, 'startDate', yesterday)
util.addXMLElement(engine.outputDom, 'endDate', today)

Ouput Dom:

<?xml version="1.0" encoding="UTF-8"?>
<TaskData>
  <startDate>03/21/2011</startDate>
  <endDate>03/22/2011</endDate>
</TaskData>


Split one HL7 message into multiple HL7 messages

In most HL7-based solutions your Custom Tasks will create one output message for one input message.  However you can also create multiple output messages from a single input message.  To do this, instead of settingengine.outputDom as in the previous examples, set engine.outputDoms (note the 's' on the end), which is a list of DOM objects.

So where you would normally write "engine.outputDom = ...", you can write "engine.outputDoms.add(...)" to add that message to the list of messages that this task will output.  For example if you wanted to output three copies of the input message, you could write this:

engine.outputDoms.add(engine.inputDom)
engine.outputDoms.add(engine.inputDom)
engine.outputDoms.add(engine.inputDom)

Outputting three copies of the input message is not very useful, so here is an example of implementing a more practical requirement.  This example takes a single HL7 message with multiple OBX segments as input, and it outputs one message for each OBX segment:
def createSingleOBXMessage(hl7msg_, obxId_):
newHL7msg = util.makeHL7Message()
for segIdx in range(1, hl7msg_.numSegments() + 1):
hl7seg = hl7msg_.getSegment(segIdx)
if hl7seg.getSegmentName()!='OBX':
newHL7msg.addSegment(hl7seg)
else:
newHL7msg.addSegment(hl7msg_.getSegment(('OBX', obxId_)))
return newHL7msg

def outputMultipleSingleOBXMessages(hl7msg_):
for obxId in range(1, hl7msg_.numSegmentsWithId('OBX')+1):
newHL7msg= createSingleOBXMessage(hl7msg_, obxId)
engine.outputDoms.add(util.makeXMLDocumentFromHL7Message('TaskData', newHL7msg))

hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
outputMultipleSingleOBXMessages(hl7msg)

Input message:

MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|1|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||
OBX|2|CE|88304|1|T57000^GALLBLADDER^SNM
OBX|3|TX|88304&MDT|1|MICROSCOPIC EXAM SHOWS HISTOLOGICALLY NORMAL GALLBLADDER TISSUE
OBX|4|TX|88304|1|ORDER DATE: 20110815|

Output messages:

Message 1:

MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|1|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||

Message 2:

MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|2|CE|88304|1|T57000^GALLBLADDER^SNM

Message 3:

MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|3|TX|88304&MDT|1|MICROSCOPIC EXAM SHOWS HISTOLOGICALLY NORMAL GALLBLADDER TISSUE

Message 4:

MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|4|TX|88304|1|ORDER DATE: 20110815|


String manipulation

Manipulating a string (that is, a sequence of characters) is a common requirement, and the Jython language provides ample facilities for string manipulation.  Below are some examples.

hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)

sendingApp = hl7msg.getField('MSH', 3) # Using the input message below as reference -
# This line sets 'sendingApp' to 'LAB101'.
hl7msg.setField(sendingApp[:3],'MSH', 3) # Sets MSH-3 to 'LAB'.
hl7msg.setField(sendingApp[-3:],'MSH', 4) # Sets MSH-4 to '101'.

# Remove whitespace at beginning and end of PID-7:
hl7msg.setComponent(hl7msg.getComponent('PID', 7, 1).strip(), 'PID', 7, 1)

# Remove whitespace at beginning of OBR-16-2 (the 'l' in 'lstrip' is for 'left'):
hl7msg.setComponent(hl7msg.getComponent('OBR', 16, 2).lstrip(), 'OBR', 16, 2)

# Remove whitespace at end of OBR-16-3 (the 'r' in 'rstrip' is for 'right'):
hl7msg.setComponent(hl7msg.getComponent('OBR', 16, 3).rstrip(), 'OBR', 16, 3)

# Remove any asterisk characters from the beginning and end of OBR-7:
hl7msg.setField(hl7msg.getField('OBR', 7).strip('*'), 'OBR', 7)

# Remove any 'plus sign' characters from the end of OBR-3:
hl7msg.setField(hl7msg.getField('OBR', 3).rstrip('+'), 'OBR', 3)

# Remove any asterisk characters from anywhere in OBR-4-2:
hl7msg.setComponent(hl7msg.getComponent('OBR', 4, 2).replace('*',''), 'OBR', 4, 2)

# Truncate OBX-5 to 20 characters. That is, if the input is more than than 20 characters long,
# remove the 21st character onward:
hl7msg.setField((hl7msg.getField('OBX', 5))[:20], 'OBX', 5)

engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', hl7msg)

Input message:

MSH|^~\&|LAB101||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||   1960/11/21  |F
OBR|1||+2080904050+++|34908^lower part *****gall bladder**^L|||*20110815124025**|||||||||^           Dr.Wang^Lucy        |||||||
OBX|3|TX|88304&MDT|1|MICROSCOPIC EXAM SHOWS HISTOLOGICALLY NORMAL GALLBLADDER TISSUE

Output message:

MSH|^~\&|LAB|101|||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||+2080904050|34908^lower part gall bladder^L|||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|3|TX|88304&MDT|1|MICROSCOPIC EXAM SHO


Advanced string search & replace - 'regular expressions'

The above section shows how to do simple search and replace in strings, with the 'replace' function.  To do more advanced search and replace in strings, the best way is usually to use 'regular expressions'.  Regular Expressions allow you to write more advanced search-and-replace operations using a compact syntax for matching characters in the input string.

This code removes all non-digits from a phone number.  It does using a regular expression that specifies all non-digits in the input string, and using an empty string as the string to replace the matched characters with - which is the same as removing them.

import re
hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
phoneNumber = hl7msg.getField('PID',13)
hl7msg.setField(re.sub(r'[^\d]', '', phoneNumber), 'PID', 13)
# ^^^^^^^^ This is the 'regular expression'.
# The [] define a 'character class' (that is, group of characters),
# The \d specifies all 'digits' (that is, numbers 0 to 9),
engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', hl7msg)

Input message:

MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F|^^^^^||3000 BLOOR E^^TOR^ON^X0X 0Y0|1811|(416) 555 - 5555||E|M|DECL|AC06464/01
OBR|70||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|20|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||

Output message:

MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21  |F|^^^^^||3000 BLOOR E^^TOR^ON^X0X 0Y0|1811|4165555555||E|M|DECL|AC06464/01
OBR|70||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|20|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||

This code replaces all groups of more than one whitespace characters with a single whitespace character:

import re
hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
inputAddress = hl7msg.getComponent('PID', 11, 1)
outputAddress = re.sub(r'\s+', ' ', inputAddress)
# In the above regular expression, the \s specifies all whitespace characters - whether that is a regular
# space, a tab, or a newline. The + sign quantifies the whitespace character part, and it specifies
# more than one.
hl7msg.setComponent(outputAddress, 'PID', 11, 1)
engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', hl7msg)

Input message:

MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F|^^^^^||3000      BLOOR     E^^TOR^ON^X0X 0Y0|1811|(416) 555-5555||E|M|DECL|AC06464/01
OBR|70||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|20|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||

Output message:

MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21  |F|^^^^^||3000 BLOOR E^^TOR^ON^X0X 0Y0|1811|(416) 555-5555||E|M|DECL|AC06464/01
OBR|70||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|20|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||

See also:

Regular expressions are a powerful part of the Jython / Python language, and are too extensive to document here.  See this page for more information.