Текстовое сообщение HL7, как найти информацию о конкретном поле

MSH|^~\&|A|B|C|D|201402141402||ORM^O01|33987|D|2.3
PID|1|99989392|99989392||UHCMCDO^TWO^^^^||19810101|M|||5678 CANDY CANE LANE^^EUCLID^OH^44117^UNITED STATES||(212)353-6048|(212)323-6078||||99576837||||NonHispan||||||||N
PV1|1|O|320|R|C||49762^Abouassaly^Robert||||||||||||99576837||||||||||Y|||||||||||||||201402141402||||||A49417331
IN1|1|43||MEDICAID-OH: CUYAHOGA COUNTY DEPT OF CHILDREN & FAMILY SERVICES|3955 EUCLID AVE^^CLEVELAND^OH^44115-2505||(216)431-4500|||||||||UHCMCDO^TWO^|S|||||1||||||||||||||123456789001|||||||M
GT1|1||UHCMCDO^TWO^^^||5678 CANDY CANE LANE^^EUCLID^OH^44117|(212) 353-6048||19810101|||S
ORC|NW||||||||20140214140256
OBR|1|36358||GC1^Non GYN - Cytology|R||201403281402||||||||NONGYNC^Non GYN - Cytology|49762^Abouassaly^Robert|||||||||||^^^^^R
DG1|1|I9|V70.0|ROUTINE MEDICAL EXAM - V70.0
OBX|1|TX|PTH_SITE1^Site A|1|left||||||F|||||||
OBX|2|TX|PTH_SPEC1^Specimen A||C-FNA^Fine Needle Aspiration||||||F|||||||

У меня есть файлы HL7, которые мне нужно получить в сегменте PID, чтобы получить имя пациента «UHCMCDO ^ TWO ^ ^^^, а затем мне нужно перейти в сегмент OBR, чтобы получить идентификатор заказа 36358, а затем отправить в таблицу базы данных. Я устал искать PID, затем переходил к 5-му полю, чтобы получить имя пациента, но не смог.

Я знаю, как искать по определенному значению, а не с динамически меняющимися значениями, но у меня есть сотни файлов, и мне нужно получить имя каждого пациента и его идентификатор заказа, чтобы получить отчет.


person Zelig    schedule 14.04.2014    source источник


Ответы (3)


Если формат файла всегда один и тот же, вы можете использовать регулярные выражения для получения нужных данных.

string name = Regex.Match(inputString,@"^PID([\d\|]*)\|\|(.*?)\|\|").Groups[2].Value;
string obrId = Regex.Match(inputString,@"OBR\|[\d]*\|(\d*)\|").Groups[1].Value;

где первый ищет первое совпадение для чего-то между двойными трубами после PID, а второй ищет второе число между трубами.

Однако, если формат файлов несовместим, это не сработает.

Изменить: вот фрагмент кода, который я запустил на ideone.com (http://ideone.com/0HROlL), используя ваш образец как «сырая» строка

using System;
using System.Text.RegularExpressions;

public class Test
{
    public static void Main()
    {
        string raw = @""; //Paste text here, new lines and all
        string[] lines = raw.Split(new string[] { Environment.NewLine },  StringSplitOptions.None); 
        string name = "";
        string obrId = "";
        foreach (string line in lines)
        {
            if (line.Contains("PID"))
            {
                name = Regex.Match(line,@"^PID([\|]*[^\|]*){3}[\|]*([^\|]*)").Groups[2].Value;
            }
            else if (line.Contains("OBR"))
            {
                obrId = Regex.Match(line,@"OBR\|[\d]*\|(\d*)\|").Groups[1].Value;
            }
        }
        Console.WriteLine(name);
        Console.WriteLine(obrId);
    }
}

Вывод:

UHCMCDO^TWO^^^^
36358
person David M    schedule 14.04.2014
comment
Двойные каналы в PID могут иметь или не иметь данные ... можем ли мы специально искать 5-ю позицию в PID или любым другим способом получить эту позицию. Спасибо, что направили меня сюда. У меня нет хорошего опыта в REGEX - person Zelig; 14.04.2014
comment
Конечно, к 5-му месту предыдущие четыре гарантированно будут там? Если это так, что-то вроде @^PID([\|]*[^\|]*){3}[\|]*([^\|]*) должно работать. который ищет шаблон любого количества каналов, за которым следует любое количество не-каналов, и ищет 4-й (исключая PID) - person David M; 14.04.2014
comment
Привет, Дэвид, я пытаюсь запустить свое приложение в соответствии с предоставленным вами регулярным выражением, но оно ничего не выбирает из обоих регулярных выражений .... не могли бы вы снова помочь мне с этим. - person Zelig; 15.04.2014
comment
Добавлен пример кода в ответ; регулярное выражение не является самым интуитивно понятным для отладки, ответ sqlab может быть лучшим долгосрочным решением, если доступны сторонние библиотеки. - person David M; 15.04.2014
comment
Спасибо, Дэвид, теперь это работает :) Я только что удалил знак моркови из PID. Большое спасибо. но мне нужно узнать, как было разработано регулярное выражение, чтобы я мог аналогичным образом внести дополнительные поля в свой отчет. Если у вас есть что-то хорошее, что может мне помочь, пожалуйста, отправьте это на [email protected] - person Zelig; 15.04.2014

Пример анализа HL7 на C# с помощью nHapi . Вы найдете nHapi здесь или здесь

person sqlab    schedule 14.04.2014

Решение на основе LINQ — пример использования:

var fields = Field.Parse(hl7);
var name = fields.First(Field.Locate("PID:5")).Value;
var order = fields.First(Field.Locate("OBR:2")).Value;

где класс поля:

public class Field
{
    public int SegmentSequence { get; set; }
    public string SegmentId { get; set; }
    public int FieldIndex { get; set; }
    public string Value { get; set; }

    public static IList<Field> Parse(string hl7, string segmentDelimiter = "\r")
    {
        if(hl7 == null) throw new ArgumentNullException("hl7");
        if(hl7.Length < 4) throw new ArgumentException("Invalid HL7 syntax.");
        hl7 = hl7.Replace("\r\n", "\r");
        try
        {
            var fieldDelimiter = hl7[3];
            return hl7.Split(new string[] { segmentDelimiter }, StringSplitOptions.None)
                .Where (s => s.Length > 0)
                .SelectMany(
                    (s, i) => s.Split(fieldDelimiter)
                                .Select(
                                    (f, j) => new Field { 
                                                    SegmentSequence = i, 
                                                    SegmentId = s.Substring(0,3), 
                                                    FieldIndex = i==0 ? j+1 : j, 
                                                    Value = f
                                                }
                                        )
                ).Where(o => !(o.FieldIndex == 0) && !(o.SegmentSequence==0 && o.FieldIndex==1))
                .ToList();
        }
        catch
        {
            throw new ArgumentException("Invalid HL7 syntax.");
        }
    }

    public static Func<Field, bool> Locate(string descriptor)
    {
        if(descriptor == null) throw new ArgumentNullException(descriptor);
        Action throwSyntaxException = () => {
            var msg = string.Format("Invalid descriptor syntax: '{0}'", descriptor);
            throw new InvalidOperationException(msg);
        };

        var elements = descriptor.Split(':');
        if(elements.Length != 2) throwSyntaxException();

        int ndx;
        if(!int.TryParse(elements[1], out ndx)) throwSyntaxException();

        return (field) => field.SegmentId == elements[0] && field.FieldIndex == ndx;
    }
}
person Casey Chester    schedule 24.04.2014