Documentation
¶
Overview ¶
Package parse provides HL7 v2.x message parsing functionality.
The parse package converts raw HL7 message bytes or strings into structured hl7.Message objects. It handles delimiter detection, segment splitting, field parsing, escape sequence processing, and validation.
Basic Usage ¶
Parse a message from bytes:
p := parse.New()
msg, err := p.Parse(data)
if err != nil {
log.Fatal("parse error:", err)
}
// Access message data
msgType := msg.Type() // e.g., "ADT^A01"
controlID := msg.ControlID() // e.g., "12345"
version := msg.Version() // e.g., "2.5.1"
Parse a message from a string:
msg, err := p.ParseString(hl7String)
if err != nil {
log.Fatal("parse error:", err)
}
Parser Options ¶
The parser supports functional options for configuration:
// Enable strict parsing mode
p := parse.New(parse.WithStrictMode(true))
// Allow empty segments
p := parse.New(parse.WithAllowEmptySegments(true))
// Use custom delimiters (for non-standard messages)
delims := &hl7.Delimiters{
Field: '|',
Component: '^',
Repetition: '~',
Escape: '\\',
SubComponent: '&',
}
p := parse.New(parse.WithCustomDelimiters(delims))
// Set DoS protection limits
p := parse.New(
parse.WithMaxSegments(500),
parse.WithMaxFieldLength(32768),
)
// Use a different segment terminator (default is CR)
p := parse.New(parse.WithSegmentTerminator('\n'))
Delimiter Detection ¶
By default, the parser automatically detects delimiters from the MSH segment:
- MSH-1 (position 3) contains the field separator
- MSH-2 (positions 4-7) contains the encoding characters
For standard HL7 messages, delimiters are typically:
MSH|^~\&|...
Where | is the field separator, ^ is component, ~ is repetition, \ is escape, and & is subcomponent.
Strict Mode ¶
When strict mode is enabled, the parser performs additional validation:
- Segment names must be exactly 3 uppercase alphanumeric characters
- MSH segment must be first
- Required fields in MSH must be present
- Field lengths are validated against maximums
In non-strict mode (default), the parser is more lenient and will accept messages with minor formatting issues.
DoS Protection ¶
The parser includes built-in protection against denial-of-service attacks:
- Maximum segment count (default: 1000)
- Maximum field length (default: 65536 bytes)
These limits prevent maliciously crafted messages from consuming excessive memory or CPU time.
Error Handling ¶
Parse errors include detailed information about what went wrong:
msg, err := p.Parse(data)
if err != nil {
// Error contains location and description
fmt.Println("Parse failed:", err)
}
Common error conditions:
- Missing or invalid MSH segment
- Invalid delimiters
- Segment count exceeds maximum
- Field length exceeds maximum
- Invalid escape sequences (in strict mode)
Example: Complete Parsing Workflow ¶
// Create parser with options
p := parse.New(
parse.WithStrictMode(true),
parse.WithMaxSegments(500),
)
// Parse message
msg, err := p.Parse(rawHL7Data)
if err != nil {
return fmt.Errorf("failed to parse HL7 message: %w", err)
}
// Extract message metadata
fmt.Printf("Message Type: %s\n", msg.Type())
fmt.Printf("Control ID: %s\n", msg.ControlID())
fmt.Printf("Version: %s\n", msg.Version())
// Access patient data
patientID, _ := msg.Get("PID.3.1")
patientName, _ := msg.Get("PID.5")
dob, _ := msg.Get("PID.7")
fmt.Printf("Patient: %s (ID: %s, DOB: %s)\n",
patientName, patientID, dob)
// Iterate over observations
for _, obx := range msg.Segments("OBX") {
obsID, _ := obx.Get("3")
value, _ := obx.Get("5")
units, _ := obx.Get("6")
fmt.Printf(" %s: %s %s\n", obsID, value, units)
}
Package parse provides HL7 v2.x message parsing functionality.
Package parse provides HL7 v2.x message parsing functionality.
Package parse provides HL7 v2.x message parsing functionality.
Index ¶
- Variables
- type Parser
- type ParserOption
- func WithAllowEmptySegments(allow bool) ParserOption
- func WithCustomDelimiters(d *hl7.Delimiters) ParserOption
- func WithMaxFieldLength(limit int) ParserOption
- func WithMaxSegments(limit int) ParserOption
- func WithSegmentTerminator(term rune) ParserOption
- func WithStrictMode(strict bool) ParserOption
- type Scanner
- type ScannerOption
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrTooManySegments is returned when the message exceeds maxSegments. ErrTooManySegments = errors.New("message exceeds maximum segment count") // ErrFieldTooLong is returned when a field exceeds maxFieldLength. ErrFieldTooLong = errors.New("field exceeds maximum length") // ErrContextCanceled is returned when the parsing context is canceled. ErrContextCanceled = errors.New("parsing canceled") // ErrEmptySegment is returned when an empty segment is found and not allowed. ErrEmptySegment = errors.New("empty segment not allowed") )
Parser-specific errors.
var ( // ErrMessageTooLarge is returned when a message exceeds the maximum size. ErrMessageTooLarge = errors.New("message exceeds maximum size") )
Scanner-specific errors.
Functions ¶
This section is empty.
Types ¶
type Parser ¶
type Parser interface {
// Parse parses raw HL7 message data into a Message.
// The input data may include MLLP framing which will be stripped.
Parse(data []byte) (hl7.Message, error)
// ParseContext parses raw HL7 message data with context support.
// Allows for cancellation during parsing of large messages.
ParseContext(ctx context.Context, data []byte) (hl7.Message, error)
}
Parser defines the interface for HL7 message parsing.
type ParserOption ¶
type ParserOption func(*parserConfig)
ParserOption is a functional option for configuring the parser.
func WithAllowEmptySegments ¶
func WithAllowEmptySegments(allow bool) ParserOption
WithAllowEmptySegments configures whether empty segments are allowed. When enabled, segments with no fields (just the segment name) are permitted.
func WithCustomDelimiters ¶
func WithCustomDelimiters(d *hl7.Delimiters) ParserOption
WithCustomDelimiters sets custom delimiters for parsing. When set, the parser will use these delimiters instead of extracting them from the MSH segment. This is useful for parsing non-standard messages or message fragments.
func WithMaxFieldLength ¶
func WithMaxFieldLength(limit int) ParserOption
WithMaxFieldLength sets the maximum field length allowed. This is a DoS protection mechanism to prevent processing of messages with excessively large fields. Default is 65536 bytes.
func WithMaxSegments ¶
func WithMaxSegments(limit int) ParserOption
WithMaxSegments sets the maximum number of segments allowed in a message. This is a DoS protection mechanism to prevent processing of maliciously large messages. Default is 1000.
func WithSegmentTerminator ¶
func WithSegmentTerminator(term rune) ParserOption
WithSegmentTerminator sets the segment terminator character. The default is carriage return (CR, 0x0D) as per HL7 standard. Some implementations use line feed (LF, 0x0A) or other characters.
func WithStrictMode ¶
func WithStrictMode(strict bool) ParserOption
WithStrictMode enables or disables strict parsing mode. In strict mode, the parser is more rigorous about HL7 compliance and will reject messages with minor formatting issues.
type Scanner ¶
type Scanner interface {
// Scan advances to the next message. Returns true if a message was found.
Scan() bool
// Message returns the last parsed message.
// Returns nil if Scan hasn't been called or returned false.
Message() hl7.Message
// Err returns any error encountered during scanning.
// Returns nil if no error occurred.
Err() error
}
Scanner provides streaming HL7 message parsing from an io.Reader. It supports both MLLP-framed messages and plain CR-delimited messages.
Example (MultipleMessages) ¶
// Stream containing multiple HL7 messages
input := "MSH|^~\\&|APP|FAC|||2023||ADT|MSG1|P|2.5\rPID|1||12345\r\r" +
"MSH|^~\\&|APP|FAC|||2023||ORU|MSG2|P|2.5\rOBX|1|NM|WBC||7.5\r"
r := strings.NewReader(input)
scanner := NewScanner(r)
messages := []hl7.Message{}
for scanner.Scan() {
messages = append(messages, scanner.Message())
}
// messages now contains both parsed messages
_ = messages
func NewScanner ¶
func NewScanner(r io.Reader, opts ...ParserOption) Scanner
NewScanner creates a new Scanner that reads from the given io.Reader. The scanner will parse messages using the provided ParserOptions.
Example ¶
Example tests
input := "MSH|^~\\&|SEND|FAC|||2023||ADT^A01|MSG001|P|2.5\rPID|1||12345\r"
r := strings.NewReader(input)
scanner := NewScanner(r)
for scanner.Scan() {
msg := scanner.Message()
_ = msg // Process message
}
if err := scanner.Err(); err != nil {
_ = err // Handle error in real code
}
func NewScannerWithOptions ¶
func NewScannerWithOptions(r io.Reader, parserOpts []ParserOption, scannerOpts ...ScannerOption) Scanner
NewScannerWithOptions creates a new Scanner with additional scanner-specific options.
type ScannerOption ¶
type ScannerOption func(*scanner)
ScannerOption is a functional option for configuring the scanner.
func WithMaxMessageSize ¶
func WithMaxMessageSize(size int) ScannerOption
WithMaxMessageSize sets the maximum allowed message size in bytes. Default is 10 MB.