efferent-health / hl7-dotnetcore Goto Github PK
View Code? Open in Web Editor NEWThis project forked from j4jayant/hl7-csharp-parser
Lightweight HL7 C# parser and composer for .NET Core, .NET Standard and .NET 5+
License: MIT License
This project forked from j4jayant/hl7-csharp-parser
Lightweight HL7 C# parser and composer for .NET Core, .NET Standard and .NET 5+
License: MIT License
I tried to follow the samples from the README and this is how I create a basic message for now:
Message mdmMessage = new Message();
HL7Encoding hl7Encoding = new HL7Encoding();
//################################
// Add a field e.g. TXA.1
Segment txaSegment = new Segment("TXA", hl7Encoding);
txaSegment.AddNewField("1" /* the Id */, 1);
mdmMessage.AddNewSegment(txaSegment);
//################################
// Add a component field e.g. PID.5.1
Segment pidSegment = new Segment("PID", hl7Encoding);
Field patientNameField = new Field(hl7Encoding);
Component pidFamilyNameComponent = new Component("Doe" /* The family name */, hl7Encoding);
patientNameField.AddNewComponent(pidFamilyNameComponent, 1 /* PID.5.1 */);
pidSegment.AddNewField(patientNameField, 5 /* PID.5 */);
mdmMessage.AddNewSegment(pidSegment);
// This throws an exception on validation
// "Failed to validate the message with error - No Message Found"
string messageString = mdmMessage.SerializeMessage(false);
"Failed to validate the message with error - No Message Found"
do you have any ideas why?
Message mdmMessage = new Message();
// This will throw an exception because the segment
// does not exist nor the field nor the component
mdmMessage.SetValue("PID.5.1", "Doe");
but as described in the comments this doesn't seem to be possible because I have to create the elements first. Any improvements?
I just noticed the following: There seems to be an incorrect order when getting all the fields for a segment. Obviously, the code does not state that it actually does guarantee any order but I obviously expected some by gut feeling.
I am opening this issue as a point of discussion. I have attached two NUnit-Tests to show the problem, one that I would have expected to work and one that actually works.
Task: Generate Ack message from:
MSH|^~\&|||||20180504113248||ORU^R01|1525433568114-1|P|2.6
PID|1||PatientID_1||Patient Name
OBR|1||1|^Serotonin Test
OBX|1|ST|Serotonin||100|µg|||||F|||20180504013248
OBX|2|ST|HIV||Negative||||||F|||20180504013248
ACK Message of HL7-dotnetcore:
MSH|^~\&||20180504113248|||20180504133248.1424|ORU^R01|ACK|1525433568114-1|P|2.6
MSA|AA|1525433568114-1
ACK Message of 7Edit:
MSH|^~\&|||||20180504130942||ACK|1525432181978-1|P|2.6
MSA|AA|1525432181978-1
HL7-dotnect library has 20180504113248
as Sending Facility and ORU^R01
in the Security field which doesn't seem correct, but I'm no expert.
I guess, GetNACK()
has the same problem.
Hi, is there any support for removing Segment?
Thanks
If I include the following code, then I get the exception here:
var hl7Encoding = new HL7Encoding() { };
var msh = new Segment("MSH", hl7Encoding);
var msh_2 = new Field("MSH2", hl7Encoding);
msh_2.Value = @"^~\&"; // problem here
msh.AddNewField(msh_2);
How can I include MSH.2 with the value ^~\&
in the serialized message?
First off, thanks for nhapi alternative. Nhapi just does too many checks (no one implements the norm anyway - it seems) and throws totally meaningless and confusing errors.
As for multiple segment-repititions, you have an example on how to access it directly using the Segments property.
But.. I mostly use the SetValue and GetValue functions. Could you add the ability to reference segment repitions there too? I tried to google a syntax, I think others (nhapi??) do it with the repetition number in (braces), like DG1(2).2.1, not sure about best syntax though.
Also, sorry to mix 2 things here, for me I found it useful to have a SetValue and GetValue that always succeeds (never throws but just returns null or empty) and created some helpers for that. I don't know whether it would be an idea to add that code here.
I've created a very simple attribute/model binding addition. Wondering if you would like it included. The problem I was solving with your code was parsing a message into a model, but I was getting tired of writing the same code over and over. What I've come up with is the following:
Let's say you have a Patient object that you need to get data in from the HL7 message. In the end, what you call is like this.
Message message = new Message(strMsg);
message.ParseMessage(); // For brevity, don't check.
Patient patient = message.Bind<Patient>();
Bind is an extension method (for now), but it works because the fields of Patient
are decorated with custom attributes like this:
public class Patient {
[HL7StringField("ERQ", Field=4)]
public string HealthNumber { get;set; }
[HL7DateTimeField("PID", Field=3, Component=2, Repetition=2, Format="yyyyMMddd")]
public string DateTime BirthDate { get; set; }
[HL7EnumField("PID", Field=3, Component=3, SubComponent=1, EnumType=typeof(Gender))]
public Gender Gender { get;set; }
// etc
}
It works absolutely brilliantly, I think it would be a good addition to your library as filling a model is most likely one of first things people want to do with a parsed HL7 message.
Let me know if you would like this as a PR.
thanks for this project which is great for IVD software work with LIS or HIS.
I try to download the project through Nuget but fail.
the environment here is .NETFramework,Version=v4.5.2 in Windows Form project.
Does this library only work in .net core?
--- Lan from China / [email protected]
Hello there.
First of all I want to thank you about this awesome tool, it really helps me to solve HL7 based problems.
I am stuck in one scenario Like I have OBR elements like below
OBR|42|11474-211913|K7084882|5272^HLA DRB1 HR-DRB3,4,5 INTERMEDIATE RESOLUTION|||202002111020|||||||||1912089277^Hello^world^^^^^^N||||||20200221|||F
And after that there is OBX element
OBX|1|ST|R166215^DBR1^^^LN||Comment||||||F||||LI5
And after this I have NTE element
NTE|1|| DRB1*14:04:01:01
Now the problem is the OBR element have result value in NTE element that is DRB1*14:04:01:01
So any idea that how I reach to the next NTE element and pick the result value. NTE elements are repeated and coming after every OBR elements. I can't hardcode the index of these elements.
I really appreciate if you let me know is that possible with this parser.
Thanks
Empty fields at the end of segments are ommitted.
E.g. it seems:
ORC|RO|2001290459^CS|||A|F|^^^20171102^^R|||||I12007^Doe, D.|CHI||||E||
becomes:
ORC|RO|2001290459^CS|||A|F|^^^20171102^^R|||||I12007^Doe, D.|CHI||||E
and therefore the entire message is never succesfully parsed!
Hello im trying to use it on 4.5.2 Framework version but im vs is unable to install the nuget, what .netframework is necessary?
any chance to get a github release created and matched to a nupkg?
I am having problems with certain escape characters in messages.
Specifically one laboratory uses \X00d as an escape sequence for Carriage Return and \X0A as New Line. The library however uses a weird \X00D and \X00A (1.5 bytes?). The error is in Encoding.Encode line 89.
According to HL& standards both implementations are wrong, it should use 1 byte (two hexadecimal numbers) for sub 32 ascii characters, however I think for maximum compatibility it should somehow ignore whether 1/1.5/2 bytes are used for escaped characters.
MSH|^~\&|iLab|CibaLab|Joystick|АГ Д-р Щерев|20200304170212||ORU^R01^ORU_R01|XATQXL2UYUP5SJDERAXH|P|2.5.1
SFT|SKYWARE Group|5.0.0.6775|iLabCourier|5.0.0.6775
PID|1||0000000000^^^GRAO^NI~5948556^^^Laboratory^MR~3700023^^^LIS^XX||^^||19921029^D|F
NTE|1||--- Footnotes ---\X000d\\X0A\ * 1. (LH ( Лутеинизиращ Хормон )): \X000d\\X0A\Референтни граници на Лутеинизиращ хормон ( LH ) за жени в репродуктивна възраст по фази в IU/L: \X000d\\X0A\фоликулна 2.4-12.6; овулаторна 14-96; лутеална 1.0-11.4; \X000d\\X0A\Референтни граници за жени в менопауза 7.7-59 IU/L;\X000d\\X0A\Референтни граници за мъже в репродуктивна възраст: 1.7-8.6 IU/L;\X000d\\X0A\ * 2. (Estradiol (Естрадиол)): \X000d\\X0A\Референтни граници на Естрадиол ( Estradiol ) за жени в репродуктивна възраст по фази в pmol/L:\X000d\\X0A\фоликулна 45.4-854; овулаторна 151-1461; лутеална 81.9-1251; Референтни граници за жени в менопауза: до 505 pmol/L;\X000d\\X0A\Референтни граници за бременни в pmol/L по триместри:\X000d\\X0A\1-ви триместър 563 - 11902,\X000d\\X0A\2-ри триместър 5729 - 78098, \X000d\\X0A\3-ти триместър от 31287 до над 110100;\X000d\\X0A\Референтни граници за мъже в репродуктивна възраст: 94.8-223 pmol/L;\X000d\\X0A\ * 3. (Progesterone ( Прогестерон )): \X000d\\X0A\Референтни граници на Прогестерон ( Progesterone ) за жени в репродуктивна възраст по фази в nmol/L: \X000d\\X0A\фоликулна 0.18-2.84; овулаторна 0.38-38.1; лутеална 5.82-75.9;\X000d\\X0A\За жени в менопауза: до 0.40 nmol/L;\X000d\\X0A\Референтни граници за бременни в nmol/L: \X000d\\X0A\1-ви трим. 35.0-141 \X000d\\X0A\2-ри трим. 80.8-264 \X000d\\X0A\3-ти трим. 187-681;\X000d\\X0A\Референтни граници за мъже в репродуктивна възраст: до 0.474 nmol/L;|RE^^HL70364
PV1|1|N|||||||||||||||||5948556^^^Laboratory^MR|||||||||||||||||||||||||202003041653^M|||||||V
ORC|RE|250042|5948556^iLab||A||^^^202003041653|||||^Лаборатория^Кл.^^^^^^BLS^^^^DN
OBR|1|250042|5948556^iLab|2579-1^LH ( Лутеинизиращ Хормон )^LN^0-64^^HCPT|||202003041653^M|||||||||||||Хормонален анализ|0
OBX|1|NM|2579-1^LH ( Лутеинизиращ Хормон )^LN^0-64^^HCPT|||IU/l|Виж забележка под черта||||I|||202003041653^M||2300006863^Калъчев^Недялко^Иванов^^Д-р^^^BLS^^^^DN
SPM|1|^S20IMQ||SER^Серум^HL70487|||||||||||||202003041653
ORC|RE|250042|5948556^iLab||A||^^^202003041653|||||^Лаборатория^Кл.^^^^^^BLS^^^^DN
OBR|2|250042|5948556^iLab|14715-7^Estradiol (Естрадиол)^LN^0-67^^HCPT|||202003041653^M|||||||||||||Хормонален анализ|0
OBX|1|NM|14715-7^Estradiol (Естрадиол)^LN^0-67^^HCPT|||pmol/l|Виж забележка под черта||||I|||202003041653^M||2300006863^Калъчев^Недялко^Иванов^^Д-р^^^BLS^^^^DN
SPM|1|^S20IMQ||SER^Серум^HL70487|||||||||||||202003041653
ORC|RE|250042|5948556^iLab||A||^^^202003041653|||||^Лаборатория^Кл.^^^^^^BLS^^^^DN
OBR|3|250042|5948556^iLab|14890-8^Progesterone ( Прогестерон )^LN^0-68^^HCPT|||202003041653^M|||||||||||||Хормонален анализ|0
OBX|1|NM|14890-8^Progesterone ( Прогестерон )^LN^0-68^^HCPT|||nmol/l|Виж забележка под черта||||I|||202003041653^M||2300006863^Калъчев^Недялко^Иванов^^Д-р^^^BLS^^^^DN
SPM|1|^S20IMQ||SER^Серум^HL70487|||||||||||||202003041653
How do I access the value 13000722 ?
PID|1||13000722^^^CS^PI^^^~154921123^^^NLMINBIZA^NNNLD^^20120425^~""^^^NLMINBIZA^PPN~4866812344^^^NLRDW^DL~""^^^NLIND^CZ~""^^^NLMINBUZA^CZ ...
This works:
message.Segments("PID")[0].Fields(3).Repetitions(1).Components(1).Value
But what if I want to use a syntax like message.getValue("PID.3.1")
When referencing the published nuget package (v2.10.0) BenchmarkDotNet fails with the following error:
Assembly ConsoleApp1 which defines benchmarks references non-optimized HL7-dotnetcore
If you own this dependency, please, build it in RELEASE.
If you don't, you can create custom config with DontFailOnError to disable our custom policy and allow this benchmark to run.
Given the performance critical nature of most HL7 codebases publishing an optimised release build seems worthwhile 👍
Can you release debug on nuget? So that I could debug without referencing the source code
The parse throws an exception if it can't parse the message.
The expected behavior based on the method should be that it returns a false if the message is not being able to be parsed.
Thanks
Looking at Microsoft's base types like int
, DateTime
or DateTimeOffset
I can find two different kinds of parsing methods:
DataType.Parse(...)
that returns DateType
or throws an informative exception if parsing somehow fails.DataType.TryParse(...)
that returns true
+ out parameter or false
if parsing was not successful.Returning DateTime?
(nullable type) as option type is a well known pattern from FP languages. However, it prevents me from seeing the exact exception message. I'd suggest three signatures:
DateTime ParseDateTime(string value)
(this one throws exceptions. Cannot be added because it conflicts with the current signature)DateTime? TryParseDateTime(string value)
(option type, Try* indicates it could return null
)bool TryParseDateTime(string value, out DateTime result)
(old fashion Try-Pattern)I'm using the tool 7Edit to send HL7 messages from my application to the 7Edit HL7 listener for testing purposes.
My TCP socket receives the following NACK response message (I converted the bytes to a string)
\vNACK\u001c\r
// This returns an array with 1 element with the content "NACK"
string[] hl7MessageStrings = MessageHelper.ExtractMessages(responseString);
// Parse the message strings to HL7 message objects
Message[] hl7Messages = hl7MessageStrings
.Select(hl7MessageString =>
{
Message hl7Message = new Message(hl7MessageString);
hl7Message.ParseMessage();
return hl7Message;
})
.ToArray();
When parsing the HL7 message it throws the following exception
Failed to validate the message with error - Message Length too short:
4 chars.
The code fails because of the validateMessage
method. I found it at
https://github.com/Efferent-Health/HL7-dotnetcore/blob/master/src/Message.cs#L699
So does 7Edit send invalid response messages? Is it a little bug in this package? The 7Edit log clearly shows its response here
and I'm not sure if they are missing the MSH segment.
For what version will this work? There are some difference between versions, so I'm asking for what versions will this work.
Good work BTW
Hello,
I would like to know if threre is a way to create a repeated field CX when sending an HL7 message?
Now, only the received messages are allowed to create repeated fields.
Best regards.
Hi.
I believe I have found a bug.
I believe that the boolean property IsComponentized on a field should be TRUE if the field consists only of one component which is SubComponentized and nothing else.
Example of that is OBR segment and field 33, which can have 11 components.
However this is what I get in a message:
|23&xxx&yyy&&&&&&zzz|
This is FIELD 33 => COMPONENT1 => SUBCOMPONENTS [1...9]
The IsComponentized for this field returns FALSE, I believe it should return TRUE and one (1) component with subcomponents. Am I right or am I doing something wrong?
Hi,
I could not find an example how I create a MSH segment.
Here is a minimal example what I tried:
[Fact]
public void Escaping()
{
Segment mshSeg = new Segment("MSH", new HL7Encoding());
mshSeg.AddNewField(@"^~\&", 1);
Message message = new Message();
message.AddNewSegment(mshSeg);
var str = message.SerializeMessage(false);
Assert.Equal("MSH|^~\\&\r", str);
}
Unfortunatelly I get following error:
HL7.Dotnetcore.HL7Exception : Invalid escape sequence in HL7 string
This happens in HL7Encoding.Decode()
.
Am I creating a MSH segment the wrong way or is this a bug?
When a field contains two double quotes, "field.Value" returns only one double quote. Is this by design or is this a bug? I find this odd behavior.
If I attempt to parse a long message (this one in particular contains large amounts of Base64 encoded data in the form of GIF/PNG/PDF/JPG/TIF, nothing breaks but the parsing is incomplete.
I've tried "cheating" a bit and breaking up the message to circumvent any internal length restriction that's happening during parsing like so:
public bool ParseAllMessage(HL7.Dotnetcore.Message message)
{
try
{
var hl7 = message.HL7Message;
var segments = hl7.Split('\r').ToList();
List<string> hl7SubBlocks = new List<string>();
int counter = 0;
string currentBlock = "";
string msh = "";
List<string> waitingSegments = new List<string>() { "MSH", "MSA", "QAK", "ERQ", "PID", "PV1", "ORC", "OBR", "ZBR", "BLG", "OBX", "ZBX", "NTE", "ZNT" };
foreach (var segment in segments)
{
if (segment.Substring(0, 3) == "MSH") msh = segment;
if (waitingSegments.Contains(segment.Substring(0, 3))) waitingSegments.Remove(segment.Substring(0, 3));
currentBlock += segment + '\r';
if (segment.Substring(0, 3) == "BLG" && waitingSegments.Count == 0) counter++;
if (counter >= 5)
{
hl7SubBlocks.Add(currentBlock);
currentBlock = "";
counter = 0;
}
}
foreach (var hl7SubBlock in hl7SubBlocks)
{
HL7.Dotnetcore.Message tmpMessage = new HL7.Dotnetcore.Message(msh+'\r'+hl7SubBlock);
tmpMessage.ParseMessage();
foreach (var innerSegment in tmpMessage.Segments())
{
message.Segments(innerSegment.Name).Add(innerSegment);
}
}
return true;
}
catch (Exception ex)
{
return false;
}
}
But this doesn't have the desired effect. I can't just add the segment data in this way. Is there an internal limit being placed on the parse method? I don't see it in your code, though stepping through it is in the next step.
The library crashes parsing a hl7 message when the patients lastname equals a backslash
eg:
PID|||||^\|||W
You have added a Unit Test when fixing #28 however this seems incomplete. Modify the test as follows:
[Test]
public void EmptyAndNullFields()
{
const string sampleMessage = "MSH|^~\\&|SA|SF|RA|RF|20110613083617||ADT^A04|123|P|2.7||||\r\nEVN|A04|20110613083617||\"\"";
var message = new Message(sampleMessage);
//the changed part:
var parseResult = message.ParseMessage();
Assert.That( parseResult, Is.True, "!!> FAILED TO PARSE A MESSAGE HERE IN THE TEST <!!" );
Assert.That( message.SegmentCount, Is.GreaterThan(0), "!!> FAILED TO PARSE A MESSAGE HERE IN THE TEST, PRODUCED ZERO SEGMENTS <!!" );
var evn = message.Segments("EVN")[0];
var expectEmpty = evn.Fields(3).Value;
Assert.AreEqual(string.Empty, expectEmpty);
var expectNull = evn.Fields(4).Value;
Assert.AreEqual(null, expectNull);
}
Now, the test fails. Aka your test message is not being parsed correctly and the behavior of 2.10 is actually rather undefined.
Upon parsing existing HL7 data using HL7-dotnetcore
version 2.8.0
from NuGet, MSH
segment fields cannot be accessed by their correct index. They suffer from an off-by-1 index issue. Specifically, it appears that MSH.1
is being misparsed. This severely impacts querying MSH
data.
Expectation
According to the spec ( https://www.hl7.org/documentcenter/public_temp_CACD15D9-1C23-BA17-0C050D19F5A35765/wg/conf/HL7MSH.htm ), MSH.1
should be have a value of |
for conventional messages and MSH.2
should have a value of ^~\&
.
Result
Actual parsing of a very simple, faux message results in MSH.1
getting parsed with the MSH.2
value and all subsequent MSH.#
queries are 1 index higher than they should be.
Code to reproduce
static void Test()
{
// HL7 string is intentionally multi-line to ensure segment delimiter is recognized
const string dummyA08 = @"MSH|^~\&|sendingApplication|sendingFacility|receivingApplication|receivingFacility|20100314063000||ADT^A08|-1|D||||
";
var message = new Message(dummyA08);
message.ParseMessage();
Console.WriteLine($"MSH.1 - expected '|' - actual '{message.GetValue("MSH.1")}'");
const string msh2Expectation = @"^~\&";
Console.WriteLine($"MSH.2 - expected '{msh2Expectation}' - actual '{message.GetValue("MSH.2")}'");
Console.WriteLine($"MSH.3 - expected 'sendingApplication' - actual '{message.GetValue("MSH.3")}'");
}
It would be great to have a helper method to parse a DateTime value field in the following format "YYYY[MM[DD[HH[MM[SS[.S[S[S[S]]]]]]]]][+/-ZZZZ]".
See documentation: http://www.hl7.eu/refactored/dtDTM.html
Any chance for .NET Standard 2.0 support?
I noticed that Message object has setValue(), getAck() methods which are public, they should be uppercase of first letter in NET naming convention, ex: SetValue() or GetAck().
Hope this nice library can follow it, otherwise it's so weird in using.
BTW, it's a good library, thanks.
Hello, can you publish manual for using your code? Thank you.
When accessing a field with a specified repetition, the library wrongly returns the value of the first repetition if there are no others.
So
getting from "PV1.8(2).1"
will return value from "PV1.8.1"
if there are no repetitions.
This could be fixed in Message.cs getField e. g. by replacing
if (field.HasRepetitions)
field = field.RepeatitionList[repetition];
return field;
with
if (field.HasRepetitions)
return field.RepeatitionList[repetition];
else if (repetition == 0)
return field;
else
return null;
Not beautiful, maybe you see something better.
Also, there is a typo, "RepeatitionList".
When I set a value on any level, this only works for already existing elements.
But.. sometimes, when I set a value, I don't want to care if the value is existing and want a convenient way of saying something like SetOrAddAndSetThen. That would be a variation of the existing
public bool SetValue(string strValueFormat, string strValue)
in Message.cs.
I already implemented this in a local copy, though it is not really nice (a little bit forced) and also now have to merge it each time there is a change in the library code.
I want to create a MDM_T02 message with a MSH, PID, TXA and OBX segment. Based on
https://github.com/Efferent-Health/HL7-dotnetcore#adding-a-message-header
I started with this
Message mdmMessage = new Message();
mdmMessage.AddSegmentMSH(
"sendingApplication",
"sendingFacility",
"receivingApplication",
"receivingFacility",
string.Empty,
"MDM_T02",
$"Id{DateTime.Now.Ticks}",
"P",
"2.6");
But unfortunately AddSegmentMSH
throws the following exception
Failed to validate the message with error - Message Type & Trigger Event value not found in message
What is missing?
Thanks in advance
I want to parse incoming HL7 ADT messages and create HL7 ACK messages as responses. I created the following code based on the samples from the docs
string messageString = "\vMSH|^~\\&|KISsystem|ZTM|NIDAklinikserver|HL7Connector|201902271130||ADT^A01|68371142|P|2.3\rEVN|A01|201902271130|201902271130\rPID|1||677789||Aubertin�^Letizia||19740731|F||\rPV1|1|O|||||||||||||||||456456456\rIN1|1||999567890|gematik Musterkasse1GKV||||||||||||Prof. Dr.Aubertin�^Letizia||19740731|||||||||||201902271101|||||||X110173919\u001c\r"
string[] hl7MessageStrings = MessageHelper.ExtractMessages(messageString);
foreach (string hl7MessageString in hl7MessageStrings)
{
/*
hl7MessageString has almost the same
content as messageString but without the
prefixes and suffixes. The content is:
"MSH|^~\\&|KISsystem|ZTM|NIDAklinikserver|HL7Connector|201902271130||ADT^A01|68371142|P|2.3\rEVN|A01|201902271130|201902271130\rPID|1||677789||Aubertin�^Letizia||19740731|F||\rPV1|1|O|||||||||||||||||456456456\rIN1|1||999567890|gematik Musterkasse1GKV||||||||||||Prof. Dr.Aubertin�^Letizia||19740731|||||||||||201902271101|||||||X110173919"
*/
Message hl7Message = new Message(hl7MessageString);
List<Segment> segments = hl7Message.Segments(); // This has a count of 0
Message ackMessage = hl7Message.GetACK(); // This throws an exception, because MSH is missing
}
When generating the ACK message I get the following exception
System.Collections.Generic.KeyNotFoundException: The given key 'MSH'
was not present in the dictionary.
but the MSH segment is present? How can I fix this?
Is there any way to use it with 4.5?
HL7-dotnetcore version: 2.0.5
From your example:
//Create a Segment with name ZIB
Segment newSeg = new Segment("ZIB");
The actual constructor is:
public Segment(HL7Encoding encoding);
public Segment(string name, HL7Encoding encoding);
The PV1 segment "PV1.7.1" for example doesn't parse out. It behaves as if it thinks PV1.7 is not componentized.
Here's a test that shows the issue (should be copiable to VS):
[Test]
public void ParsePV1()
{
string hl7File =
@"MSH|^&|EPIC||||20191107134803|ALEVIB01|ORM^O01|23|T|2.3|||||||||||WEINSM06^WEINSTEIN^MICHAEL^^^^^^KID^^^^KID|1447312459^WEINSTEIN^MICHAEL^^^^^^EPIC^^^^PNPI
PID|1||10034926^^^NYU MRN^MRN||OSTRICH^DODUO||19820605|M||U|360 PARK AVE SOUTH^^NEW YORK^NY^10010^US^^^60|60|(615)613-2113^HOME^PH|||S|||999-99-9999|||U||N||||||||
PV1||O|NWSLED^^^NYULHLI^^^^^LI NW SLEEP DISORDER^^DEPID||||1447312459^WEINSTEIN^MICHAEL^^^^^^EPIC^^^^PNPIWEINSM06^WEINSTEIN^MICHAEL^^^^^^KID^^^^KID|||||||||||496779945|||||||||||||||||||||||||20191107|||||||VWEINSM06^WEINSTEIN^MICHAEL^^^^^^KID^^^^KID|1084022001^^^1084022^^^^^LI NW SLEEP DISORDER&NYU WINTHROP SLEEP CENTER|(516)663-2834|||||||||||||||O|
ORC|NW|162431500^EPC|30011922^EPC||Scheduled||^^^20191107134353^^R||20191107134806|ALEVIB01^ALEVIS^BRIAN^^||1447312459^WEINSTEIN^MICHAEL^^^^^^EPIC^^^^PNPI
OBR|1|162431500^EPC|30011922^EPC|IMG16525^SLEEP STUDY UNATTENDED^NAT^^SLEEP STUDY UNATTENDED|R|20191107134744|||||Ancillary Pe|||||1447312459^WEINSTEIN^MICHAEL^^^^^^EPIC^^^^PNPIWEINSM06^WEINSTEIN^MICHAEL^^^^^^KID^^^^KID|(516)663-2834|NWSLED^^^^^^^^LI NW SLEEP DISORDER^^DEPIDLI NW SLEEP HOME STUDY||||||OT| Scheduled ||^^^20191107134355^^R|||||||||20191107134500||||||||IMG16525^SLEEP STUDY UNATTENDED^NAT^^SLEEP STUDY UNATTENDED|
NTE|1||Where will this exam be scheduled?->NYU Winthrop Sleep Disorders Center||
DG1|1|ICD-10-CM|W58.03XA^Crushed by alligator, initial encounter^ICD-10-CM|Crushed by alligator, initial encounter||^180;ORD
ZDS|1.2.840.114350.2.232.3.798268.2.162431500.1^EPIC^APPLICATION^DICOM";
Message msg = new Message(hl7File);
msg.ParseMessage();
//This is OK
string PID = msg.GetValue("PID.3.1");
Assert.AreEqual("10034926", PID);
//This fails, actually throws exception:
try
{
string attendingDrId = msg.GetValue("PV1.7.1");
Assert.AreEqual("1447312459", attendingDrId);
}catch(Exception parseEx)
{
string err = parseEx.Message;
}
}
When parsing a message, a tab space will be treated as white space and after the message is parsed, is no longer equal to the original message, causing the message parsed to fail the final check.
Please add following test in your master branch:
[Fact]
public void AddComponents()
{
//Create a Segment with name ZIB
Segment newSeg = new Segment("ZIB", new HL7Encoding());
// Create Field ZIB_1
Field ZIB_1 = new Field("ZIB1", new HL7Encoding());
// Create Field ZIB_5
Field ZIB_5 = new Field("ZIB5", new HL7Encoding());
// Create Component ZIB.5.2
Component com1 = new Component("ZIB.5.2", new HL7Encoding());
// Add Component ZIB.5.2 to Field ZIB_5
ZIB_5.AddNewComponent(com1, 2);
// Add Field ZIB_1 to segment ZIB, this will add a new filed to next field location, in this case first field
newSeg.AddNewField(ZIB_1);
// Add Field ZIB_5 to segment ZIB, this will add a new filed as 5th field of segment
newSeg.AddNewField(ZIB_5, 5);
// Add segment ZIB to message
var message = new Message(this.HL7_ADT);
message.AddNewSegment(newSeg);
string serializedMessage = message.SerializeMessage(false);
Assert.Equal("ZIB|ZIB1||||^ZIB.5.2", serializedMessage);
}
And you get following error:
HL7.Dotnetcore.HL7Exception: "Unable to add new component Error - Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index"
The test is based on your example code.
When sending back ACK messages I'm currently doing
Message ackMessage = hl7Message.GetACK();
string ackMessageString = ackMessage.HL7Message;
byte[] ackMessageBytes = Encoding.UTF8.GetBytes(ackMessageString);
// ... Send message via TCP ...
The problem is that ackMessageString
does not contain the pre- and suffixes required for the MLP. This package is able to parse message strings containing those pre- and suffixes as desribed here
https://github.com/Efferent-Health/HL7-dotnetcore#message-extraction
but is it also able to encode messages back to strings? My current dirty solution would be something like this:
string ackMessageString = $"{(char) 11}{ackMessage.HL7Message}{(char) 28}{(char) 13}";
but maybe the package is able to do it for me :)
Good evening,
First of all, thank you for this project, it is very helpful.
I have problem, because in my program I have to add into the segment PID, a repeating field, for the phone and mobile numbers, but unfortunately I do not have access to the internal RepeatitionList property.
Can you tell me how can I implement this, without changing the accessibility operator?
I need this output :
PID||||||||||||||(0033)4521254215^PRN^PH~(0033)62512455^ORN^CP~^NET^Internet^[email protected]
Best regards,
Constantin
Hello! Good joob for de library but i have a problem
When i trie tu use message.AddSegmentMSH(...)
i obtain this error: System.InvalidOperationException: 'Sequence contains no matching element'
i use this method becouse i have an error when i trie "newSeg.AddNewField(encoding.AllDelimiters, 2);"
My best regards!
In HL7 section 2.5.3.0, Field or Component Status, it specifies that a field value of "" (e.g. |""|) is considered to be a null value and should not be used for any other purpose. In the parser, a field value of "" is returned as a string value of 2 double quotes, not a null string value.
I know this is primarily targeting .NET standard, but there's nothing in here that limits it specifically to NetStandard1.3+. The library I'm building is targeting NetStandard2.0 AND Net45 so I would love if this would get pulled in. I've redone the tests to target everything as well.
When using this package in a .Net Core 2.1 application in Visual Studio 2017, the following warnings are displayed during compilation. This appears to be a result of the way these dependencies are referenced in the .csproj file.
The nuget refs in the .csproj file look like this:
<PackageReference Include="System.Runtime" Version="*" />
I believe that the Version="*"
is causing this problem, as the compiler is attempting to reference version 2.9.0 of each nuget package, which is the current version of this package.
Warning NU1603 HL7-dotnetcore 2.9.0 depends on System.Linq (>= 2.9.0) but System.Linq 2.9.0 was not found. An approximate best match of System.Linq 4.0.0 was resolved.
Warning NU1603 HL7-dotnetcore 2.9.0 depends on System.Runtime (>= 2.9.0) but System.Runtime 2.9.0 was not found. An approximate best match of System.Runtime 4.0.0 was resolved.
Warning NU1603 HL7-dotnetcore 2.9.0 depends on System.Runtime.Extensions (>= 2.9.0) but System.Runtime.Extensions 2.9.0 was not found. An approximate best match of System.Runtime.Extensions 4.0.0 was resolved.
Warning NU1603 HL7-dotnetcore 2.9.0 depends on System.Text.RegularExpressions (>= 2.9.0) but System.Text.RegularExpressions 2.9.0 was not found. An approximate best match of System.Text.RegularExpressions 4.0.0 was resolved.
Running ParseTest with Message based on HL7_ADT which points to Sample-ADT.txt returns isParsed = false.
on or thereabouts line 111, there is the following:
if (this.Equals(strSerializedMessage)) isParsed = true;
this fails because the two messages are different in that the original has a blank segment and therefore 5 segments instead of the parsed version which has 4.
is it true that a Message would not be equivalent if the difference were extra blank segments?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.