Documentation

Command line

Six crates ship a binary. They are useful without writing any Rust at all — looking at an unfamiliar message, checking a batch in a shell script, converting a directory of files.

The six binaries

BinaryFrom crateDoes
hl7-v2hl7-2Tree, query, check, edit, and re-emit an HL7 v2 message
hl7-2-from-er7-into-xmlsame nameER7 → v2.xml
hl7-2-from-xml-into-er7same namev2.xml → ER7
hl7-2-from-er7-into-jsonsame nameER7 → typed JSON
hl7-2-from-json-into-er7same nametyped JSON → ER7
hl7-2-from-xsd-into-json-dictionarysame nameA directory of v2.xml XSDs → the JSON dictionary hl7-2 reads

Install any of them with cargo install <crate> — see Install. Note that cargo install hl7-2 gives you a binary named hl7-v2.

hl7-v2 — the HL7 v2 tool

text
hl7-v2 [OPTIONS] [FILE]

Reads FILE, or standard input when FILE is absent or -. Input may hold one message, several, or a batch; each is handled separately.

Output modes — the first one given wins

OptionPrints
-t, --treeThe message as an indented tree. The default.
-q, --query PATHEvery value at PATH, one per line.
-c, --checkValidation diagnostics, or ok.
-e, --er7The message back as ER7.

Options

OptionEffect
-s, --set PATH=VALUESet a value before printing. Repeatable.
-n, --null PATHWrite the explicit HL7 null at a path before printing.
-v, --hl7-version VERForce a release rather than reading it from MSH-12.
-d, --dictionary FILERead the message through a JSON schema dictionary.
-f, --flatSuppress message-structure grouping.
-p, --pathsShow each node's path beside it.
-S, --strictFail on a validation error.
-o, --output FILEWrite to a file instead of stdout.

Successive trees are separated by a blank line. The value and ER7 outputs are not, so they can be piped straight into another tool.

sh
# Look at a message you have never seen
hl7-v2 samples/oru_r01.hl7

# Pull out every result value
hl7-v2 --query OBX-5 samples/oru_r01.hl7

# Check it, with an exit status a shell can act on
hl7-v2 --check samples/adt_a01.hl7

# Read a vendor dialect
hl7-v2 --dictionary samples/acme.json samples/vendor.hl7

# Change something and write it back out
hl7-v2 --set 'PID-8=F' --er7 samples/orm_o01.hl7
sh
$ hl7-v2 --paths samples/vendor.hl7
ADT_A01
  MSH  [MSH[1]]
    ...
  ZAC  [ZAC[1]]
    ZAC.1 = 7           [ZAC[1]-1[1]]
    ZAC.2               [ZAC[1]-2[1]]
      ZAC.2.1 = SMITH   [ZAC[1]-2[1].1]
      ZAC.2.2 = JOHN    [ZAC[1]-2[1].2]
    ZAC.3 = 20260814    [ZAC[1]-3[1]]

The four converters

All four read a file or standard input and write standard output or -o FILE. The ER7-side tools accept one message, several, or an HL7 batch file (FHS/BHS envelopes are dropped); each message becomes one output document.

ER7 → XML, and the same flags apply to ER7 → JSON

sh
# From a file to stdout
hl7-2-from-er7-into-xml samples/orm_o01.hl7

# From stdin, to a file
cat samples/oru_r01.hl7 | hl7-2-from-er7-into-xml -o out.xml

# Disable message-structure grouping
hl7-2-from-er7-into-xml --flat samples/orm_o01.hl7

# Convert against a dictionary built from XSDs instead of bundled v2.5
hl7-2-from-er7-into-xml --dictionary my-dialect.json samples/orm_o01.hl7

# Let that dictionary decide the document's exact shape
hl7-2-from-er7-into-xml --dictionary my-dialect.json --schema-shape samples/orm_o01.hl7

--dictionary FILE reads a JSON dictionary — such as one built by the XSD tool — in place of the bundled HL7 v2.5 tables. --schema-shape changes how that dictionary is read: instead of only naming what a field is, it decides what the document contains — required fields are written even when empty, fields that cannot repeat keep their repetition separator as text, and no field the dictionary does not declare is written.

The JSON converter has one flag of its own:

sh
# Compact (single-line) JSON instead of pretty-printed
hl7-2-from-er7-into-json --compact samples/orm_o01.hl7

The two reverse tools take the segment terminator instead:

sh
# v2.xml back to ER7
hl7-2-from-xml-into-er7 samples/orm_o01.xml

# Typed JSON back to ER7
hl7-2-from-json-into-er7 samples/orm_o01.json

# Choose the segment terminator
hl7-2-from-xml-into-er7 --terminator crlf samples/orm_o01.xml

Message-structure group elements and keys are flattened automatically, so grouped and --flat input from the forward tool both reconstruct the same message.

The dictionary builder

sh
hl7-2-from-xsd-into-json-dictionary schemas/paris -o paris.json

# Two things the schemas cannot tell you, so you pass them in
hl7-2-from-xsd-into-json-dictionary schemas/paris \
    --name paris \
    --alias ADT_A28=ADT_A05 \
    --alias ADT_A31=ADT_A05 \
    -o paris.json

# Layer the document over a bundled release instead of standing alone
hl7-2-from-xsd-into-json-dictionary schemas/paris --inherits 2.5 -o paris.json

--alias says which trigger events arrive carried by another message's structure. A directory holds ADT_A05.xsd but never says that an ADT^A28 is one, so that mapping has to come from you. See Vendor dictionaries.

Exit status, and using it in a shell

hl7-v2 exits:

  • 0 — success.
  • 1 — a usage error, or the input was not a message at all.
  • 2--check or --strict found something wrong with the message.

Those three are distinct on purpose: “this file is not HL7” and “this file is HL7 and it is wrong” need different handling, and a script that conflates them will quarantine the wrong things.

A triage script that uses the distinction

sh
#!/bin/sh
# Reject anything that does not conform before it reaches the interface engine.
for message in inbox/*.hl7; do
    if hl7-v2 --check "$message" >/dev/null; then
        mv "$message" accepted/
    else
        hl7-v2 --check "$message" >> rejected.log
        mv "$message" rejected/
    fi
done

Recipes

sh
# Every patient identifier in a directory of messages
cat inbox/*.hl7 | hl7-v2 --query PID-3

# Fix a sex code and re-emit, in one pass
hl7-v2 --set 'PID-8=F' --er7 in.hl7 > out.hl7

# Clear a field with the explicit HL7 null rather than emptying it
hl7-v2 --null 'PID-11' --er7 in.hl7

# Force a release when the sender's MSH-12 lies
hl7-v2 --hl7-version 2.3 vendor.hl7

# Round trip, as a smoke test
hl7-2-from-er7-into-xml in.hl7 | hl7-2-from-xml-into-er7 | diff - in.hl7

hl7-v2 --help lists everything, and each converter's own spec/index.md §8 is the normative statement of its command-line contract. See Specifications.