Hl7引擎的目标主要是解决将数据按HL7协议的要求标准化,和标准业务的集成和不同系统间标准业务数据的同步。在多年的医院集成平台信息化过程中,HL7标准组织和解析最复杂了,下面是我用了多年HL7引擎解析,因公司升级使用了HL73.0版本,决定把HL72.X引擎放到博客上保存。
(引擎解析类)Decode.cs
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Xml;
- using System.Text.RegularExpressions;
- namespace com.china.hl7
- {
- /// <summary>
- /// HL7解析器
- /// </summary>
- public static class HL7ToXmlConverter
- {
- private static XmlDocument _xmlDoc;
- /// <summary>
- /// 把HL7信息转成XML形式
- /// 分隔顺序 \n,|,~,^,&
- /// </summary>
- /// <param name="sHL7">HL7字符串</param>
- /// <returns></returns>
- public static string ConvertToXml(string sHL7)
- {
- _xmlDoc = ConvertToXmlObject(sHL7);
- return _xmlDoc.OuterXml;
- }
- public static XmlDocument ConvertToXmlObject(string sHL7)
- {
- _xmlDoc = CreateXmlDoc();
- //把HL7分成段
- string[] sHL7Lines = sHL7.Split('\n');
- //去掉XML的关键字
- for (int i = 0; i < sHL7Lines.Length; i++)
- {
- sHL7Lines[i] = Regex.Replace(sHL7Lines[i], @"[^ -~]", "");
- }
- for (int i = 0; i < sHL7Lines.Length; i++)
- {
- // 判断是否空行
- if (sHL7Lines[i] != string.Empty)
- {
- string sHL7Line = sHL7Lines[i];
- //通过/r 或/n 回车符分隔
- string[] sFields = HL7ToXmlConverter.GetMessgeFields(sHL7Line);
- // 为段(一行)创建第一级节点
- XmlElement el = _xmlDoc.CreateElement(sFields[0]);
- _xmlDoc.DocumentElement.AppendChild(el);
- // 循环每一行
- for (int a = 0; a < sFields.Length; a++)
- {
- // 为字段创建第二级节点
- XmlElement fieldEl = _xmlDoc.CreateElement(sFields[0] + "." + a.ToString());
- //是否包括HL7的连接符
- if (sFields[a] != @"^~\&")
- {//0:如果这一行有任何分隔符
- //通过~分隔
- string[] sComponents = HL7ToXmlConverter.GetRepetitions(sFields[a]);
- if (sComponents.Length > 1)
- {//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)
- {//2.如果有字组,一般是没有的。。。
- for (int c = 0; c < subComponents.Length; c++)
- {
- //修改了一个错误
- string[] subComponentRepetitions = GetComponents(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
- {//2.如果没有字组了,一般是没有的。。。
- string[] sRepetitions = HL7ToXmlConverter.GetComponents(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
- {//1:如果不可以分隔,可以直接写节点值了。
- fieldEl.InnerText = sFields[a];
- el.AppendChild(fieldEl);
- }
- }
- else
- {//0:如果不可以分隔,可以直接写节点值了。
- fieldEl.InnerText = sFields[a];
- el.AppendChild(fieldEl);
- }
- }
- }
- }
- return _xmlDoc;
- }
- /// <summary>
- /// 通过|分隔 字段
- /// </summary>
- /// <param name="s"></param>
- /// <returns></returns>
- private static string[] GetMessgeFields(string s)
- {
- return s.Split('|');
- }
- /// <summary>
- /// 通过^分隔 组字段
- /// </summary>
- /// <param name="s"></param>
- /// <returns></returns>
- private static string[] GetComponents(string s)
- {
- return s.Split('^');
- }
- /// <summary>
- /// 通过&分隔 子分组组字段
- /// </summary>
- /// <param name="s"></param>
- /// <returns></returns>
- private static string[] GetSubComponents(string s)
- {
- return s.Split('&');
- }
- /// <summary>
- /// 通过~分隔 重复
- /// </summary>
- /// <param name="s"></param>
- /// <returns></returns>
- private static string[] GetRepetitions(string s)
- {
- return s.Split('~');
- }
- /// <summary>
- /// 创建XML对象
- /// </summary>
- /// <returns></returns>
- private static XmlDocument CreateXmlDoc()
- {
- XmlDocument output = new XmlDocument();
- XmlElement rootNode = output.CreateElement("HL7Message");
- output.AppendChild(rootNode);
- return output;
- }
- public static string GetText(XmlDocument xmlObject, string path)
- {
- XmlNode node = xmlObject.DocumentElement.SelectSingleNode(path);
- if (node != null)
- {
- return node.InnerText;
- }
- else
- {
- return null;
- }
- }
- public static string GetText(XmlDocument xmlObject, string path, int index)
- {
- XmlNodeList nodes = xmlObject.DocumentElement.SelectNodes(path);
- if (index <= nodes.Count)
- {
- return nodes[index].InnerText;
- }
- else
- {
- return null;
- }
- }
- public static String[] GetTexts(XmlDocument xmlObject, string path)
- {
- XmlNodeList nodes = xmlObject.DocumentElement.SelectNodes(path);
- String[] arr = new String[nodes.Count];
- int index = 0;
- foreach (XmlNode node in nodes)
- {
- arr[index++] = node.InnerText;
- }
- return arr;
- }
- }
- }
测试方法:
- String myHL7string = "MSH|^~\\&|455755610_0100||0200||20110624160404|000|QRY^A19^QRY_A19|0123456001|P|2.6\nQRD|||||||||0001^郭靖^体检号^EQ^AND~0002^东一区^病区号^EQ^AND\nQRF||20110627|20110803";
- string sHL7asXml = HL7ToXmlConverter.ConvertToXml(myHL7string);
- XmlDocument xmlObject = HL7ToXmlConverter.ConvertToXmlObject(myHL7string);
- String value = HL7ToXmlConverter.GetText(xmlObject, "QRD/QRD.9/QRD.9.0",0);
- String value2 = HL7ToXmlConverter.GetText(xmlObject, "QRD/QRD.9/QRD.9.0");
- String nodeValue = xmlObject.DocumentElement.SelectSingleNode("MSH/MSH.1").InnerText;
- String nodeValue2 = xmlObject.DocumentElement.SelectSingleNode("QRD/QRD.9/QRD.9.0").InnerText;