Crates
hl7-2-from-xml-into-er7
v2.xml XML → ER7
What it is
Convert HL7 v2.5 messages from the official HL7 v2.xml XML representation
(urn:hl7-org:v2xml) back to the traditional pipe-delimited ER7 encoding, as a Rust
library and command-line tool.
It is the inverse of hl7-2-from-er7-into-xml, and it reads
back exactly what that crate writes.
Why it needs no dictionary
Which is why this crate is so much smaller than its forward counterpart: reversal is a purely
structural, position-based rebuild. It depends on er7 for the encoding layer and, since
0.5.0, on hl7-2-xml-lite-helper for reading the
XML — it used to carry its own minimal XML reader.
What it produces
A v2.xml fragment such as:
<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>converts back to:
PID|1||241900||TEST^FOUAZCommand line
# From a file to stdout
hl7-2-from-xml-into-er7 samples/orm_o01.xml
# From stdin, to a file
cat samples/oru_r01.xml | hl7-2-from-xml-into-er7 -o out.hl7
# Choose the segment terminator
hl7-2-from-xml-into-er7 --terminator crlf samples/orm_o01.xmlMessage-structure group elements (<ORM_O01.PATIENT>, <ORU_R01.ORDER_OBSERVATION>, …) are flattened automatically; grouped and --flat input from the forward crate both reconstruct the same message.
Namespace prefixes are ignored: a document that binds urn:hl7-org:v2xml to a prefix
converts to exactly the same ER7 as one that makes it the default namespace, whatever prefix the
sending system happened to pick.
Library
let xml = r#"<ORM_O01 xmlns="urn:hl7-org:v2xml">
<MSH>
<MSH.1>|</MSH.1>
<MSH.2>^~\&</MSH.2>
<MSH.9><MSG.1>ORM</MSG.1><MSG.2>O01</MSG.2></MSH.9>
</MSH>
<ORM_O01.PATIENT>
<PID><PID.5><XPN.1><FN.1>TEST</FN.1></XPN.1><XPN.2>FOUAZ</XPN.2></PID.5></PID>
</ORM_O01.PATIENT>
</ORM_O01>"#;
let er7 = hl7_2_from_xml_into_er7::convert(xml)?;use hl7_2_from_xml_into_er7::parse;
// When you want the full er7::Message — to query or edit it — rather than
// just its ER7 text.
let message = parse(xml)?;
assert_eq!(message.query("PID-5.1")?.as_deref(), Some("TEST"));convert, convert_with_options, and parse return Result<_, Hl7Error>; an Err only ever means the input is not
well-formed XML, or the message has no usable MSH/FHS/BHS header. Everything else converts, falling back gracefully rather than failing.
convert_with_options takes the segment terminator, as er7::RenderOptions, re-exported here as hl7_2_from_xml_into_er7::er7::RenderOptions.
What it does
- XML reading for exactly the subset v2.xml uses: nested elements, text, the predefined entities and numeric character references, with attributes, comments, and the XML declaration recognized and skipped.
- Position-based reconstruction, no data-type dictionary — see above.
- Group flattening: message-structure group elements are recognized by their dotted name and flattened back into a plain segment sequence. No message-structure grammar is needed in this direction.
- Delimiter recovery: the header's
.1and.2fields are reassembled into a synthetic header line and handed toer7::Separators::from_header, reusinger7's own delimiter parsing. - Faithful re-escaping: decoded leaf text is retokenized against
er7's own escape-sequence vocabulary, so delimiter characters are re-escaped while formatting sequences the forward crate never decoded (\.br\,\H\, …) are written back exactly as they were. - HL7 null versus empty: an element whose text is
""reconstructs as the explicit null (“delete this”); a self-closing or empty element reconstructs as an empty value (“nothing was sent”). The XML Encoding Rules give the two opposite meanings, so this crate keeps them apart — padding an XSD-shaped document with empty elements does not turn it into a message full of deletion markers.
Limitations
- A field repetition that was present but entirely blank (not the explicit null) is dropped by the forward crate's own encoding and cannot be recovered here — a property of v2.xml as that crate writes it, not something this crate's reversal introduces.
- One v2.xml document converts to one ER7 message; there is no batch-file convention on the XML side to split.
See spec/index.md §5 for the full list.
Related crates
hl7-2-from-er7-into-xml
ER7 → the official v2.xml XML representation
hl7-2-from-json-into-er7
Typed JSON → ER7
hl7-2-xml-lite-helper
The small, dependency-free XML reader this family shares