For those of us unfortunate enough to have to deal with it, HL7 is a commonly encountered language used by medical systems to communicate with each other. It is what someone dreamed up way back when before XML was invented. Indeed, the most recent version of HL7 is XML. However, for those of us that still have to use older systems, it's an unwieldy and unfriendly language to deal with; message components are delimited using carriage returns, pipe symbols, tildes, and ampersands.
Since most applications use XML for data exchange, and XML is much nicer to deal with anyway, it would be helpful if there were an HL7 to XML conversion library that was freely available. Sadly, despite scouring the web, I have not found a (free) class or utility that can easily be integrated into applications. There are a few Java libraries, and one well known (excellent) commercial application, but nothing free and easy to use.
This article is v1 of my attempt at creating such a library. Please feel free to use and extend it - and most importantly, fix any bugs I've missed.
Using the code
A very simple HL7 message looks something like this:
MSH|^~\&|||||20080925161613||ADT^A05||P|2.6
This class and method simply produces an XML representation of the same message. Note that this class isn't nearly clever enough to know what type of HL7 message it is converting - it merely creates an XML version of it. The point is that you can then use XPath to retrieve the segment you want to use since you know its location. The HL7 above returned by this method would look like this:
/// This class takes an HL7 message/// and transforms it into an XML representation.
public static class HL7ToXmlConverter
{
// This is the XML document we'll be creating
private static XmlDocument _xmlDoc;
/// <summary>/// Converts an HL7 message into an XML representation of the same message./// </summary>/// <param name="sHL7">The HL7 to convert</param>/// <returns></returns>
public static string ConvertToXml(string sHL7)
{
// Go and create the base XML
_xmlDoc = CreateXmlDoc();
// HL7 message segments are terminated by carriage returns,// so to get an array of the message segments, split on carriage returnstring[] sHL7Lines = sHL7.Split('\r');
// Now we want to replace any other unprintable control// characters with whitespace otherwise they'll break the XMLfor (int i = 0; i < sHL7Lines.Length; i++)
{
sHL7Lines[i] = Regex.Replace(sHL7Lines[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 (int i = 0; i < sHL7Lines.Length; i++)
{
// Don't care about empty linesif (sHL7Lines[i] != string.Empty)
{
// Get the line and get the line's segmentsstring sHL7Line = sHL7Lines[i];
string[] sFields = HL7ToXmlConverter.GetMessgeFields(sHL7Line);
// Create a new element in the XML for the line
XmlElement el = _xmlDoc.CreateElement(sFields[0]);
_xmlDoc.DocumentElement.AppendChild(el);
// For each field in the line of HL7for (int a = 0; a < sFields.Length; a++)
{
// Create a new element
XmlElement fieldEl = _xmlDoc.CreateElement(sFields[0] +
"." + a.ToString());
/// 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] != @"^~\&")
{
/// 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.string[] sComponents = HL7ToXmlConverter.GetComponents(sFields[a]);
if (sComponents.Length > 1)
{
for (int b = 0; b < sComponents.Length; b++)
{
XmlElement componentEl = _xmlDoc.CreateElement(sFields[0] +
"." + a.ToString() +
"." + b.ToString());
string[] subComponents = GetSubComponents(sComponents[b]);
if (subComponents.Length > 1)
// There were subcomponents
{
for (int c = 0; c < subComponents.Length; c++)
{
// Check for repetitionstring[] subComponentRepetitions =
GetRepetitions(subComponents[c]);
if (subComponentRepetitions.Length > 1)
{
for (int d = 0;
d < subComponentRepetitions.Length;
d++)
{
XmlElement subComponentRepEl =
_xmlDoc.CreateElement(sFields[0] +
"." + a.ToString() +
"." + b.ToString() +
"." + c.ToString() +
"." + d.ToString());
subComponentRepEl.InnerText =
subComponentRepetitions[d];
componentEl.AppendChild(subComponentRepEl);
}
}
else
{
XmlElement subComponentEl =
_xmlDoc.CreateElement(sFields[0] +
"." + a.ToString() + "." +
b.ToString() + "." + c.ToString());
subComponentEl.InnerText = subComponents[c];
componentEl.AppendChild(subComponentEl);
}
}
fieldEl.AppendChild(componentEl);
}
else// There were no subcomponents
{
string[] sRepetitions =
HL7ToXmlConverter.GetRepetitions(sComponents[b]);
if (sRepetitions.Length > 1)
{
XmlElement repetitionEl = null;
for (int c = 0; c < sRepetitions.Length; c++)
{
repetitionEl =
_xmlDoc.CreateElement(sFields[0] + "." +
a.ToString() + "." + b.ToString() +
"." + c.ToString());
repetitionEl.InnerText = sRepetitions[c];
componentEl.AppendChild(repetitionEl);
}
fieldEl.AppendChild(componentEl);
el.AppendChild(fieldEl);
}
else
{
componentEl.InnerText = sComponents[b];
fieldEl.AppendChild(componentEl);
el.AppendChild(fieldEl);
}
}
}
el.AppendChild(fieldEl);
}
else
{
fieldEl.InnerText = sFields[a];
el.AppendChild(fieldEl);
}
}
else
{
fieldEl.InnerText = sFields[a];
el.AppendChild(fieldEl);
}
}
}
}
return _xmlDoc.OuterXml;
}
/// <summary>/// Split a line into its component parts based on pipe./// </summary>/// <param name="s"></param>/// <returns></returns>
private static string[] GetMessgeFields(string s)
{
return s.Split('|');
}
/// <summary>/// Get the components of a string by splitting based on carat./// </summary>/// <param name="s"></param>/// <returns></returns>
private static string[] GetComponents(string s)
{
return s.Split('^');
}
/// <summary>/// Get the subcomponents of a string by splitting on ampersand./// </summary>/// <param name="s"></param>/// <returns></returns>
private static string[] GetSubComponents(string s)
{
return s.Split('&');
}
/// <summary>/// Get the repetitions within a string based on tilde./// </summary>/// <param name="s"></param>/// <returns></returns>
private static string[] GetRepetitions(string s)
{
return s.Split('~');
}
/// <summary>/// Create the basic XML document that represents the HL7 message/// </summary>/// <returns></returns>
private static XmlDocument CreateXmlDoc()
{
XmlDocument output = new XmlDocument();
XmlElement rootNode = output.CreateElement("HL7Message");
output.AppendChild(rootNode);
return output;
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步