Skip to content

Latest commit

 

History

8 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

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

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages