Quick start
Install one crate, parse a real ORU^R01, read a value out of it, and send back an acknowledgement.
hl7-rust
Parse, navigate, validate, modify, and render Health Level Seven messages. HL7 v2 releases 2.1 through 2.9 with a real dictionary behind them; HL7 v3's RIM backbone and message envelope; MLLP and SOAP transports; and lossless conversion between ER7, v2.xml, and JSON. Small dependency trees, permissive licensing, and a normative specification for every crate whose behavior is normative.
cargo add hl7
Install one crate, parse a real ORU^R01, read a value out of it, and send back an acknowledgement.
One task per page: parsing, navigating, validating, converting, MLLP, SOAP, vendor dictionaries.
Longer walkthroughs — taming a vendor dialect, standing up an MLLP listener that answers.
Fourteen workspace members, each with its features, dependencies, and API tour.
HL7 v2 is pipes and carets. The hard part is not the syntax — it is knowing what the pipes and carets mean in the release the sender speaks. That is what the dictionary is for.
A lipid panel result, as it arrives on the wire
MSH|^~\&|LAB|ACME|EHR|CLINIC|20260814080000||ORU^R01|MSG00042|P|2.5
PID|1||444333222^^^ACME&1.2.3.4&ISO^MR||EVERYWOMAN^EVE^E||19620320|F
OBR|1|ORD776655|LAB2233|24331-1^Lipid Panel^LN|||20260813071500
OBX|1|NM|2093-3^Cholesterol^LN||187|mg/dL|<200|N|||FRead from it by path or by name
use hl7::v2;
let message = v2::parse(text)?;
// A path addresses a value; the tree names it.
assert_eq!(message.get("PID-5.1")?.as_deref(), Some("EVERYWOMAN"));
assert_eq!(message.tree().find("XPN.1").unwrap().text(), "EVERYWOMAN");
// Every node knows the path that reads it back.
let second = message.tree().find_all("OBX").nth(1);
assert_eq!(message.structure_id(), "ORU_R01");The same ER7 fragment PID|1||241900||TEST^FOUAZ converts to the official v2.xml
representation and to a typed JSON mapping designed to preserve everything v2.xml preserves.
Piping either back through its reverse crate reproduces the original message.
hl7-2-from-er7-into-xml
<PID>
<PID.1>1</PID.1>
<PID.3>
<CX.1>241900</CX.1>
</PID.3>
<PID.5>
<XPN.1><FN.1>TEST</FN.1></XPN.1>
<XPN.2>FOUAZ</XPN.2>
</PID.5>
</PID>hl7-2-from-er7-into-json
{
"PID": {
"PID.1": "1",
"PID.3": { "CX.1": "241900" },
"PID.5": {
"XPN.1": { "FN.1": "TEST" },
"XPN.2": "FOUAZ"
}
}
}One crate per layer, one module per standard. Each seam is a place you can stop: take the ER7 encoding alone, take v2 without a transport, take a transport without the dictionary. This groups crates by family and layer, not by literal Cargo dependency edges — see what actually depends on what.
er7 the ER7 encoding: delimiters,
escapes, paths, byte-for-byte
rendering, batch splitting
|
hl7-2 the HL7 v2 dictionary: releases
| 2.1-2.9, data types, message
| structures; three parsing modes;
| mutation; validation
|
+-- hl7-2-mllp transport: HL7 v2 over TCP (MLLP)
+-- hl7-2-soap transport: HL7 v2 over HTTP (SOAP)
+-- hl7-2-from-er7-into-json format conversions
+-- hl7-2-from-er7-into-xml
+-- hl7-2-from-json-into-er7
+-- hl7-2-from-xml-into-er7
+-- hl7-2-from-xsd-into-json-dictionary writes the dictionaries
| hl7-2 reads, from HL7
| v2.xml XSDs
+-- hl7-2-xml-lite-helper shared minimal XML reader, also
| used directly by:
+-- hl7-3 HL7 v3: RIM backbone classes,
| coded values, the three-level
| message envelope
+-- hl7-3-derive #[derive(FromElement)]
+-- hl7-3-soap transport: HL7 v3 over HTTP (SOAP)
hl7 the umbrella crate — hl7::v2 and
hl7::v3 today, room for hl7::fhirThe standards themselves, and the umbrella crate that re-exports them.
The umbrella crate: one module per HL7 standard
HL7 v2 itself: parse, navigate, validate, modify, render
HL7 v3: the RIM backbone, the data types, the message envelope
Getting messages across a network, and answering them.
MLLP: HL7 v2 framed on a TCP stream
HL7 v2 carried in a SOAP envelope over HTTP
HL7 v3 carried in a SOAP envelope over HTTP
ER7 in both directions against both target formats.
ER7 → the official v2.xml XML representation
v2.xml XML → ER7
ER7 → typed JSON
Typed JSON → ER7
The macros, the dictionary builder, and the shared XML reader.
#[derive(FromHl7)] and #[derive(ToHl7)] for struct mode
#[derive(FromElement)] for HL7 v3 struct mode
HL7 v2.xml XSDs → the JSON dictionary hl7-2 reads
The small, dependency-free XML reader this family shares
14 crates in one Cargo workspace, plus er7, which is its own.