Skip to content

tcmarkfeld/HL7Kit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HL7Kit

HL7Kit is a strict HL7 v2 parser for .NET that converts pipe-delimited HL7 messages into strongly-typed C# POCOs.

It is designed for modern integration work where you need:

  • Strongly typed access to common segments
  • Strict malformed-message detection with clear exceptions
  • Proper handling of HL7 delimiters, escapes, repeats, and character sets
  • Safe access to custom and unknown segments without losing data

Install

dotnet add package HL7Kit  --version 0.1.0

Or with PackageReference:

<ItemGroup>
  <PackageReference Include="HL7Kit" Version="0.1.0" />
</ItemGroup>

FHIR converter package:

dotnet add package HL7Kit.Fhir --version 1.0.0

Or with PackageReference:

<ItemGroup>
  <PackageReference Include="HL7Kit.Fhir" Version="1.0.0" />
</ItemGroup>

Quick Start

using HL7Kit;

var raw = "MSH|^~\\&|ADTAPP|HOSP|EHR|FAC|20260430103045||ADT^A01^ADT_A01|MSG00001|P|2.5\r"
    + "PID|1||123456^^^HOSP^MR||Doe^Jane^Alice^^Ms\r"
    + "OBX|1|ST|94531-1^COVID result^LN||Negative|||||F\r";

Hl7Message message = Hl7Message.Parse(raw);

string? sendingApp = message.Msh.SendingApplication;
string? familyName = message.Pid?.PatientName.FamilyName;
string? obxValue = message.Obx.FirstOrDefault()?.ObservationValue;

FHIR Conversion (HL7Kit.Fhir)

HL7Kit.Fhir converts parsed HL7Kit HL7 v2 message objects into Firely .NET SDK FHIR R4 resources.

Supported mappings

  • PID -> Patient
  • PV1 -> Encounter
  • OBX -> Observation
  • NK1 -> RelatedPerson
  • AL1 -> AllergyIntolerance
  • DG1 -> Condition
  • ToBundle() -> transaction Bundle with all successfully converted resources

Converter quick start

using HL7Kit;
using HL7Kit.Fhir;
using Hl7.Fhir.Model;

Hl7Message message = Hl7Message.Parse(raw);

Patient patient = Hl7FhirConverter.ToPatient(message);
Encounter encounter = Hl7FhirConverter.ToEncounter(message);
Observation observation = Hl7FhirConverter.ToObservation(message);
Bundle bundle = Hl7FhirConverter.ToBundle(message);

Why HL7Kit?

If you already know libraries like NHapi, HL7Kit is intentionally opinionated in a few areas:

  • Strict-first parsing: malformed input throws clear Hl7ParseException errors instead of silently tolerating questionable structure.
  • Modern .NET ergonomics: nullable-aware POCOs, focused value types (PersonName, CodifiedValue, Hl7DateTime), and straightforward APIs.
  • Delimiter/escape correctness per message: respects dynamic MSH.1 / MSH.2, escapes, repeats, and charset behavior.
  • No data loss for unsupported segments: captures both Z segments and other unknown segments so integrations stay forward-compatible.
  • Incremental typed coverage model: strongly typed where implemented, practical string fallback where not yet implemented.

What You Get

Strongly typed message model

Top-level parsed message includes typed access to:

  • MSH, PID, PV1, OBR, OBX, NK1
  • EVN, AL1, DG1, IN1, MSA, ERR, NTE, ORC, SCH

Strict parser behavior

Hl7Message.Parse(...) throws Hl7ParseException for malformed input, including:

  • Missing/invalid MSH
  • Invalid segment IDs
  • Invalid date/time formats
  • Invalid or unsupported escape sequences
  • Invalid repeat usage in fields expected to be single-valued

HL7 delimiter and encoding support

Per-message delimiter set is read from MSH.1 and MSH.2.

Supported:

  • Field delimiter (usually |)
  • Component delimiter (usually ^)
  • Repetition delimiter (usually ~)
  • Escape delimiter (usually \\)
  • Subcomponent delimiter (usually &)

Supported escapes:

  • \F\, \S\, \R\, \E\, \T\
  • \.br\
  • \X...\ hex-encoded bytes
  • \Cxxxx\ single-byte character set switches (C2842, C2D41)

Character set resolution from MSH.18 includes:

  • ASCII variants
  • ISO-8859-1 variants
  • UTF-8 variants (UTF-8, UTF8, UNICODE UTF-8, UNICODE UTF8)

HL7 null and whitespace behavior

  • HL7 null literal "" is interpreted as null
  • Empty field is null
  • Leading/trailing spaces in field values are preserved
  • Whitespace-only field values are preserved

Custom and Unknown Segment Access

Z-segments

Custom Zxx segments are captured in message.ZSegments.

if (message.ZSegments.TryGetValue("ZPI", out var zpiSegments))
{
    var first = zpiSegments[0];

    string? rawField1 = first.GetField(1);
    string? component2 = first.GetComponent(1, 2);
    string rawLine = first.Raw;
}

Non-Z unknown segments

Unknown non-Z segments are captured in message.UnknownSegments.

if (message.UnknownSegments.TryGetValue("ABC", out var abcSegments))
{
    string? field1 = abcSegments[0].GetField(1);
}

Value Types

HL7Kit includes reusable value types:

  • PersonName
  • CodifiedValue
  • Hl7DateTime

Hl7DateTime supports:

  • YYYY
  • YYYYMM
  • YYYYMMDD
  • YYYYMMDDHHmm
  • YYYYMMDDHHmmss

Segment Field Coverage

For supported segments, properties are mapped to HL7 field positions with XML docs.

  • Fields with implemented parsing use strong types where applicable
  • Fields not fully implemented are currently represented as string? with TODO markers

Target Framework

  • .NET 10 (net10.0)

License

MIT. See LICENSE.

About

Strongly typed HL7 v2 message parser for .NET with full segment coverage, repeating fields, escape sequences, and FHIR conversion.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages