Skip to content

An easy to use HL7 v2 parsing library based on typical hl7 notiation (e.g. PID.3.1)

License

Notifications You must be signed in to change notification settings

mwarnock/hl7find

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HL7Find

HL7Find is an HL7 v2 parsing library that uses typical HL7 location notation as a means of retrieving values.

This library is not for sending or receiving HL7.

It's distinguishing feature is that it uses common (with some extensions) notation to access and update HL7 v2 messages. For example, to access PID.3.1 simply use my_message.find('PID.3.1') instead of inventing syntax in the programming language.

Installation

This library is written using only the standard library for python 3. You can install it like most python packages:

pip install hl7find

Use

The library is primarly a single class which takes an HL7 string (\r or \n delimeters on the segments) as its first argument.

There is also no need to specify the delimerters, repeating operator, or esacape character. HL7 does that in the MSH segment.

from hl7find import HL7Message

hl7_string = """
MSH|^~\&|SendingApp|SendingFac|ReceivingApp|ReceivingFac|20120411070545||ORU^R01|59689|P|2.3
PID|1|12345|12345^^^MIE&1.2.840.114398.1.100&ISO^MR||MOUSE^MINNIE^S||19240101|F|||123 MOUSEHOLE LN^^FORT WAYNE^IN^46808|||||||||||||||||||
OBX|1|NM|wbc^Wbc^Local^6690-2^Wbc^LN||7.0|/nl|3.8-11.0||||F|||20120410160227|lab|12^XYZ LAB|
OBX|2|NM|neutros^Neutros^Local^770-8^Neutros^LN||68|%|40-82||||F|||20120410160227|lab|12^XYZ LAB|
OBX|3|NM|lymphs^Lymphs^Local^736-9^Lymphs^LN||20|%|11-47||||F|||20120410160227|lab|12^XYZ LAB|
ZF1|TEST|REPEAT 1~REPEAT 2~REPEAT 3|This^Still^Works|deeper^repeat^1~deeper^repeat^2|other^deepest~repeating~field|z end
"""

msg = HL7Message(hl7_string)

Find

With an HL7Message instance you can use the find function to retrieve parts of the message. Using the example HL7 message above, this includes simple descrete values:

msg.find("PID.3.1") # -> 12345
msg.find("PID.3.4.1") # -> MEI

Repeating segments or values:

msg.find("OBX*.3")   # -> A tuple of all obx segments at position 3
msg.find("ZF1.2")     # -> The repeating field at ZF1.2 as a tuple: ('REPEAT 1', 'REPEAT 2'...)
msg.find("ZF1.4*.3") # -> The third position of the repeating value at ZF1.4: ('1','2')
msg.find("OBX[3].1") # -> The third obx segment and its value at position 1: 3

If you want to count from the opposite direction you can use a negative position value:

msg.find("MSH.-1") # -> The last position on the MSH segment: 2.3

If there is a repeating field or segment but your search string is ambiguous it will raise HL7AmbiguousSegmentException.

Update

Components of the HL7 message can be changed using the same find syntax. The one exception is repeating fields. These need to be changed on the level they repeat.

To change a field value just reference it and provide the updated value:

msg.update("MSH.2","New Facility")
msg.find("MSH.2") # -> "New Facility"

msg.update("PID.-1","last element")
msg.find("PID.-1") # -> "last element"

This works with specific segments when there are multiple.

msg.update("OBX[1].1","Yay!")
msg.find("OBX[1].1") # -> "Yay!"

You can also update part of a segment that isn't there yet and the structure will be extended to accomidate the update.

msg.update("MSH.100","added elements automatically")
msg.find("MSH.100") # -> "added elements automatically"

msg.update("PID.3.12","added elements")
msg.find("PID.3.12") # -> "added elements"

It's also possible to update an entire segment at once or another part of a segment but adding to the structure. The internal structure of HL7Message is a list of tuples(segment name, segment structure) and the segment structure is a list of lists. Repeating fields are represented as a tuple. You can access the internal structure via the internal_structure function.

When updating a segment or a more complex component of a segment all at once you can reflect this same internal structure and delimeters will be placed accordingly when outputting with to_string.

msg.update("ZF1",['test','a','value',['a','sub','value'],('and','a','repeating','field')])
msg.find("ZF1.1") # -> 'test'
msg.find("ZF1.4.2") # -> 'sub'
msg.find("ZF1.5[3]") # -> 'repeating'

Add Segment

It's also possible to add a segment that doesn't exist. Use the add_segment function providing the segment name followed by the initial values. You can also specify a third argument of where (1-N) in the list of segments it should be inserted. It will not override the existing segment of that position but instead move the trailing segments (including the one at the specified index) down one index. The function will not take index 0 as an option as this should already be an MSH segment which is how a message must start.

msg.add_segment("ZBS",['new','segment',['with','initial','values']]) # -> adds the ZBS segment to the last position
msg.add_segment("ZCS",['another','segment','right','after','msh'], 1) # -> adds the ZCS segment as the second segment (right after msh)

Emit or Copy

HL7Messages can be turned back into an HL7 string with the to_string function which takes an optional keyword parameter to set the newline/break character (newline_char='\r')

Also, as updates cause mutation there a copy of an HL7Message object can be made using the copy function.

Contributing

Contributions are welcome via pull request.

To report issues use github issues.

There is a test.sh file that sets the PYTHONPATH so that pytest runs successfully from the root of the project.

About

An easy to use HL7 v2 parsing library based on typical hl7 notiation (e.g. PID.3.1)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published