65.9K
CodeProject 正在变化。 阅读更多。
Home

将 HL7 转换为 XML

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.17/5 (15投票s)

2008年9月25日

CPOL

2分钟阅读

viewsIcon

172483

一个初步尝试,用于将 HL7 转换为 XML 的类。欢迎贡献。

引言

对于我们这些不幸需要处理它的人来说,HL7 是一种医疗系统之间常用的通信语言。它是在 XML 发明之前,有人梦寐以求创造出来的。事实上,HL7 的最新版本就是 XML。然而,对于那些仍然需要使用旧系统的人来说,它是一种笨拙且不友好的语言,消息组件使用回车符、管道符、波浪线和井号分隔。

由于大多数应用程序使用 XML 进行数据交换,而且 XML 无论如何都更容易处理,因此如果有一个可免费获得的 HL7 到 XML 转换库将会很有帮助。遗憾的是,尽管我在网上搜索了很久,但我没有找到一个可以轻松集成到应用程序中的(免费)类或实用程序。有一些 Java 库,还有一个著名的(优秀的)商业应用程序,但没有免费且易于使用的。

本文是我的尝试创建这样一个库的 v1 版本。请随意使用和扩展它——最重要的是,修复我遗漏的任何错误。

使用代码

一个非常简单的 HL7 消息如下所示

MSH|^~\&|||||20080925161613||ADT^A05||P|2.6

这个类和方法只是生成相同消息的 XML 表示形式。请注意,这个类不够聪明,无法知道它正在转换的 HL7 消息类型——它只是创建了它的 XML 版本。关键在于,然后你可以使用 XPath 来检索你想要使用的段,因为你知道它的位置。该方法返回的上述 HL7 消息如下所示

<HL7Message>
    <MSH>
        <MSH.0>MSH</MSH.0>
        <MSH.1>^~\&</MSH.1>
        <MSH.2/>
        <MSH.3/>
        <MSH.4/>
        <MSH.5/>
        <MSH.6>20080925161613</MSH.6>
        <MSH.7/>
        <MSH.8>
            <MSH.8.0>ADT</MSH.8.0>
            <MSH.8.1>A05</MSH.8.1>
        </MSH.8>
        <MSH.9/>
        <MSH.10>P</MSH.10>
        <MSH.11>2.6</MSH.11>
    </MSH>
</HL7Message>

这是一个静态类,它返回一个 XML 字符串(作为一个字符串;它可以很容易地修改为返回一个 XmlDocument)。

使用该类

string sHL7asXml = HL7ToXmlConverter.ConvertToXml(myHL7string);

完整的类如下所示

/// 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 return
        string[] sHL7Lines = sHL7.Split('\r');

        // Now we want to replace any other unprintable control
        // characters with whitespace otherwise they'll break the XML
        for (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 lines
            if (sHL7Lines[i] != string.Empty)
            {
                // Get the line and get the line's segments
                string 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 HL7
                for (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 repetition
                                        string[] 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;
    }
}

关注点

这是我在 The Code Project 上的第一篇文章。HL7 的新版本(一直应该用 XML 编写)将使这个类变得多余,但我希望在此期间它对人们有用。

我讨厌 HL7!:-)

历史

目前还没有历史记录。

© . All rights reserved.