HL7 To XML

This is a VBA port of a C# class that takes an HL7 message and converts it to an XML document object and returns the resulting xml as a string.

The original article can be found here: http://www.codeproject.com/Articles/29670/Converting-HL7-to-XML

The port was triggered by this UA discussion: http://www.utteraccess.com/forum/Hl7-Messaging-Class-t1985123.html

Option Compare Database
Option Explicit

' This class takes an HL7 message
' and transforms it into an XML representation.
' A reference to the Microsoft XML library is required

Private xmlDoc As DOMDocument

' Converts an HL7 message into an XML representation of the same message.
Public Function ConvertToXml(sHL7 As String) As String


Dim sHL7Lines As Variant
Dim sComponents As Variant
Dim b As Integer
Dim subComponents As Variant
Dim c As Integer
Dim subComponentRepetitions As Variant
Dim d As Integer
Dim sRepetitions As Variant
Dim repetitionEl As IXMLDOMElement
Dim componentEl As IXMLDOMElement
Dim subComponentEl As IXMLDOMElement
Dim subComponentRepEl As IXMLDOMElement
Dim i As Integer
Dim sFields As Variant
Dim sHL7Line As String
Dim fieldEl As IXMLDOMElement
Dim el As IXMLDOMElement

'Create the base XML
Set xmlDoc = CreateXmlDoc()

' HL7 message segments are terminated by carriage returns,
' so to get an array of the message segments, split on carriage return

sHL7Lines = Split(sHL7, vbLf)

' Now we want to replace any other unprintable control
' characters with whitespace otherwise they'll break the XML
For i = 0 To UBound(sHL7Lines)
sHL7Lines(i) = Replace(sHL7Lines(i), " |", "|")
sHL7Lines(i) = Replace(sHL7Lines(i), " ^", "^")
sHL7Lines(i) = Replace(sHL7Lines(i), " ~", "~")
sHL7Lines(i) = Replace(sHL7Lines(i), " &", "&")
Next i

' Go through each segment in the message
' and first get the fields, separated by pipe (|),
' then for each of those, get the field components,
' separated by carat (^), and check for
' repetition (~) and also check each component
' for subcomponents, and repetition within them too.

For i = 0 To UBound(sHL7Lines)
' Don't care about empty lines
If Len(sHL7Lines(i)) > 0 Then

' Get the line and get the line's segments
sHL7Line = sHL7Lines(i)
sFields = GetMessgeFields(sHL7Line)

' Create a new element in the XML for the line
Set el = xmlDoc.createElement(sFields(0))
xmlDoc.documentElement.appendChild el

' For each field in the line of HL7
Dim a As Integer

For a = 0 To UBound(sFields)

' Create a new element
Set fieldEl = xmlDoc.createElement(sFields(0) & "." & CStr(a))

' Part of the HL7 specification is that part
' of the message header defines which characters
' are going to be used to delimit the message
' and since we want to capture the field that
' contains those characters we need
' to just capture them and stick them in an element.
If sFields(a) <> "^~\&" Then

' Get the components within this field, separated by carats (^)
' If there are more than one, go through and create an element for
' each, then check for subcomponents, and repetition in both.

sComponents = GetComponents(sFields(a))
If UBound(sComponents) > 1 Then

For b = 0 To UBound(sComponents)

Set componentEl = xmlDoc.createElement(sFields(0) & _
"." & CStr(a) & _
"." & CStr(b))

subComponents = GetSubComponents(sComponents(b))
If UBound(subComponents) > 1 Then
' There were subcomponents

For c = 0 To UBound(subComponents)

' Check for repetition
subComponentRepetitions = GetRepetitions(subComponents(c))
If UBound(subComponentRepetitions) > 1 Then

For d = 0 To UBound(subComponentRepetitions)

subComponentRepEl = xmlDoc.createElement(sFields(0) & _
"." & CStr(a) & _
"." & CStr(b) & _
"." & CStr(c) & _
"." & CStr(d))
subComponentRepEl.Text = subComponentRepetitions(d)
componentEl.appendChild (subComponentRepEl)
Next d

Else

Set subComponentEl = xmlDoc.createElement(sFields(0) & _
"." & CStr(a) & "." & _
CStr(b) & "." & CStr(c))
subComponentEl.Text = subComponents(c)
componentEl.appendChild (subComponentEl)

End If
Next c
fieldEl.appendChild (componentEl)

Else ' There were no subcomponents

sRepetitions = GetRepetitions(sComponents(b))
If UBound(sRepetitions) > 1 Then
'Set repetitionEl = Null

For c = 0 To UBound(sRepetitions)

Set repetitionEl = xmlDoc.createElement(sFields(0) & "." & _
CStr(a) & "." & CStr(b) & _
"." & CStr(c))
repetitionEl.Text = sRepetitions(c)
componentEl.appendChild repetitionEl
Next c
fieldEl.appendChild componentEl
el.appendChild fieldEl

Else

componentEl.Text = sComponents(b)
fieldEl.appendChild componentEl
el.appendChild fieldEl
End If
End If

Next b
el.appendChild fieldEl
Else
fieldEl.Text = sFields(a)
el.appendChild fieldEl
End If
Else
fieldEl.Text = sFields(a)
el.appendChild fieldEl
End If
Next a
End If
Next i

ConvertToXml = xmlDoc.XML
End Function


' Split a line into its component parts based on pipe.
Private Function GetMessgeFields(s) As Variant
GetMessgeFields = Split(s, "|")
End Function

' Get the components of a string by splitting based on carat.

Private Function GetComponents(s) As Variant
GetComponents = Split(s, "^")
End Function


' Get the subcomponents of a string by splitting on ampersand.

Private Function GetSubComponents(s) As Variant
GetSubComponents = Split(s, "&")
End Function

' Get the repetitions within a string based on tilde.

Private Function GetRepetitions(s) As Variant
GetRepetitions = Split(s, "~")
End Function


' Create the basic XML document that represents the HL7 message

Private Function CreateXmlDoc() As DOMDocument
Dim output As DOMDocument
Dim rootNode As IXMLDOMElement

Set output = New DOMDocument

Set rootNode = output.createElement("HL7Message")
output.appendChild rootNode
Set CreateXmlDoc = output
End Function