T2.4: Uses DTL Editor

Knowledge Review - HL7 Interface Specialist

1. Configure Source and Target Message Classes

Key Points

  • Message Class Options: EnsLib.HL7.Message for complete messages, EnsLib.HL7.Segment for segments
  • DocType Selection: Choose after class - Format: Version:MessageType (e.g., 2.5:ADT_A01)
  • Complete Messages: Use EnsLib.HL7.Message for most DTL transformations
  • Segment Transforms: Use EnsLib.HL7.Segment for reusable segment subtransforms

Detailed Notes

Overview

The Data Transformation Language (DTL) editor in InterSystems HealthConnect provides a powerful visual interface for creating message transformations. Before you can begin mapping fields, you must configure the source and target message classes. For HL7 transformations, you have two primary class options: EnsLib.HL7.Message for transforming complete HL7 messages, and EnsLib.HL7.Segment for transforming individual HL7 segments.

EnsLib.HL7.Message Class

EnsLib.HL7.Message is the most commonly used class for HL7 DTL transformations. When you select this class for both source and target, you're creating a transformation that takes a complete HL7 message as input and produces a complete HL7 message as output. This is appropriate for most integration scenarios where you need to transform messages between different HL7 versions, modify message content, or restructure messages to meet target system requirements.

DocType Configuration

After selecting the message class, the DTL editor prompts you to choose a DocType for both source and target. The DocType specifies the exact message structure using the format Version:MessageType, with a colon separator and underscore in the message type. For example, "2.5:ADT_A01" specifies an ADT patient admission message using HL7 version 2.5 structure. The DocType selection determines which segments and fields are available for mapping in the transformation.

EnsLib.HL7.Segment for Subtransforms

EnsLib.HL7.Segment is used less frequently but is valuable for creating reusable segment-level transformations. When you have similar segment transformation logic that needs to be applied in multiple message-level DTLs, you can create a segment-level subtransform using EnsLib.HL7.Segment. This subtransform can then be called from multiple message-level DTLs, promoting code reuse and consistency. For example, you might create a segment subtransform for standardizing PID segment content that's used across multiple message type transformations.

Documentation References

2. Differentiate Between Create=New and Create=Copy Settings

Key Points

  • Create=New: Target message starts empty - must copy all needed segments
  • Create=Copy: Target starts as complete copy of source - modify only what changes
  • When to use New: Different versions, different structures, selective segment copying
  • When to use Copy: Same version, same structure, minimal field changes

Detailed Notes

Key Configuration Decision

One of the most critical DTL configuration decisions is choosing between Create=New and Create=Copy modes. This choice fundamentally affects how the target message is initialized and what transformation logic you need to implement. Understanding when to use each mode is essential for creating efficient transformations and is a frequent exam topic.

Create=New Mode

Create=New initializes the target message as an empty message object. No segments are copied automatically from source to target. This means you must explicitly copy every segment and field you want in the target message. While this requires more transformation logic, it provides maximum control and is appropriate when the source and target have different structures. For example, if you're transforming from HL7 version 2.3.1 to version 2.5, the message structures differ significantly, and Create=New allows you to carefully map each segment according to the structural differences.

Create=New is also the right choice when you don't want all segments from the source to appear in the target. If the source message contains Z segments (custom segments) that shouldn't be included in the target, or optional segments that aren't needed, Create=New allows you to selectively copy only the segments you want. You can still copy segments individually - Create=New doesn't prevent copying, it just doesn't copy automatically.

Create=Copy Mode

Create=Copy takes the opposite approach - it initializes the target message as a complete copy of the source message. Before any transformation actions execute, the target already contains all segments and fields with identical values to the source. Your transformation logic then focuses only on modifying the fields that need to change. This is highly efficient when transforming messages of the same version and structure where only a few fields need modification.

Practical Example

For example, if you're receiving ADT_A01 messages in version 2.5 and need to send them to another system also using version 2.5, but you need to change the receiving facility code in MSH:6 and add a facility code to PV1:3, Create=Copy is ideal. The DTL only needs two simple field assignments - everything else is already correctly copied. Using Create=New for this scenario would require dozens of copy actions to rebuild the entire message structure.

Documentation References

3. Add Functions to DTL Expressions

Key Points

  • Function Access: Magnifying glass icon opens function selector
  • Common Functions: Lookup, Strip, ToLower, ToUpper, Pad, Replace
  • Lookup(): Search lookup tables - parameters: table name, search value, default actions
  • String Functions: Strip whitespace, change case, pad strings, replace text

Detailed Notes

Accessing Functions

DTL transformations often need to manipulate data beyond simple field copying. The DTL editor provides a comprehensive library of functions for data transformation, validation, and lookup operations. These functions are accessed through the expression editor by clicking the magnifying glass icon next to any field mapping, which opens the function selector interface showing available functions organized by category.

The Lookup() Function

The Lookup() function is one of the most important DTL functions for healthcare integrations. It enables code translation by searching lookup tables for value mappings. For example, you might use a lookup table to map internal department codes to external facility codes, or to translate gender codes between different systems' conventions. The Lookup() function takes several parameters: the lookup table name, the search value (typically a source field), and configuration for what to do if the value isn't found in the table (use a default value, generate an error, or pass through the original value).

String Manipulation Functions

String manipulation functions handle common data cleaning and formatting requirements. Strip() removes leading and trailing whitespace from strings, which is valuable when source systems include extra spaces that target systems don't expect. ToLower() and ToUpper() provide case conversion, useful when systems have different case sensitivity requirements. These simple functions can prevent integration issues caused by data format mismatches.

The Pad() function adds padding characters to strings to reach a required length, which is occasionally needed when target systems expect fixed-length fields. The Replace() function performs string replacement operations, allowing you to replace specific characters or substrings with other values. For example, you might replace hyphens with spaces in phone numbers if the target system uses a different format.

Best Practices

Each function has specific parameter requirements that you must understand to use them correctly. The function selector interface shows parameter descriptions, but understanding common functions and their usage patterns is important for exam preparation. Practice using these functions in the DTL editor to become familiar with their parameters and behavior.

Documentation References

4. Apply foreach Actions in DTL

Key Points

  • foreach Purpose: Iterate over repeating segments or fields
  • Loop Variable: k1, k2, k3... for nested loops
  • Common Use Cases: OBX results, multiple insurances, repeating identifiers
  • Nested Loops: Inner loop uses higher k number (k2 inside k1)

Detailed Notes

Purpose and Use Cases

The foreach action in DTL provides iteration capability for processing repeating segments and repeating fields within HL7 messages. HL7 messages frequently contain repeating elements - a laboratory result message (ORU) can have dozens of OBX observation segments, a patient may have multiple insurance coverages in multiple IN1 segments, or a single field like patient identifier might contain multiple values. The foreach action enables you to process each occurrence individually.

Loop Variables

The basic foreach structure defines a loop over a repeating element and assigns each iteration to a loop variable. The DTL editor suggests loop variable names starting with k1 for the first foreach, k2 for nested foreachs inside k1, k3 for foreachs inside k2, and so on. These loop variables are index numbers that identify which occurrence is being processed in the current iteration.

Practical Example

A common scenario is transforming laboratory results where you need to iterate over each OBX segment in the source and create corresponding OBX segments in the target. The foreach action would iterate over source.OBXgrp(k1), and within the loop body, you'd have actions that copy or transform fields from source.OBXgrp(k1).OBX to target.OBXgrp(k1).OBX. The k1 variable automatically increments for each segment occurrence, allowing you to process all results regardless of how many exist.

Nested Loops

Nested foreach loops handle multi-level repeating structures. For example, you might have an outer foreach iterating over OBX segments (k1), and an inner foreach iterating over repeating values within OBX-5 (k2). The inner loop would reference source.OBXgrp(k1).OBX.5(k2), using both loop variables to access the specific occurrence of the repeating field within the specific occurrence of the repeating segment. Understanding nested loop variable usage is important for complex transformations and exam questions.

Documentation References

5. Apply if Actions for Conditional Logic

Key Points

  • if Condition: Apply transformation based on source field criteria
  • Condition on Source: Conditions typically evaluate source message fields
  • Nested Actions: Use right arrow button to nest actions within if block
  • if/else Logic: Add else actions for alternative transformation paths

Detailed Notes

Purpose of Conditional Logic

Conditional logic is essential in DTL transformations when different source data requires different transformation handling. The if action provides standard conditional logic, executing nested actions only when the specified condition evaluates to true. This allows you to implement business rules, handle optional data, or apply different transformations based on message content.

Defining Conditions

If conditions are typically defined on source message fields. For example, you might check if source.PID:8 (patient gender) equals "M" before applying male-specific transformations, or check if source.PV1:2 (patient class) equals "I" to identify inpatient visits requiring special handling. The condition syntax supports standard comparison operators including equals (=), not equals (!=), greater than (>), less than (<), and the Contains operator for substring matching.

Nesting Actions

To nest transformation actions within an if block, you use the right arrow button in the DTL editor. When you create an if action, it appears in the action list with an expandable/collapsible structure. You then create the actions you want conditionally executed (like field assignments or other if actions), select them, and use the right arrow button to indent them under the if action. This visual nesting makes the conditional logic clear and easy to understand.

If/Else Logic

The if action can include an else clause for alternative actions when the condition is false. This provides complete if/else logic similar to programming languages. For example, if source.PID:8 = "M", copy "Male" to target.PID:8, else copy "Female" to target.PID:8. The else actions are nested under the if action just like the true-condition actions, but marked as belonging to the else path. Understanding how to implement and read if/else structures is important for complex transformations and exam scenarios.

Documentation References

6. Apply group Actions for Organization

Key Points

  • Visual Organization: Group related actions for clarity
  • No Processing Logic: Groups don't affect execution or conditions
  • Documentation: Add descriptions to groups for maintainability
  • Collapsible: Groups can be collapsed to simplify complex DTL view

Detailed Notes

Purpose of Groups

The group action in DTL provides organizational structure for complex transformations but doesn't add any processing logic or conditional execution. Groups are purely for visual organization and documentation, allowing you to cluster related transformation actions together with descriptive labels. This makes large DTLs easier to understand, maintain, and troubleshoot.

Creating and Naming Groups

When you create a group action, you give it a descriptive name or description that explains what the grouped actions accomplish. For example, you might create a group called "Copy Demographics" containing all the actions that transform patient demographic fields from PID and PD1 segments, or a group called "Calculate Financial Class" containing logic that determines and sets financial class codes. These descriptions serve as inline documentation within the DTL.

Nesting and Collapsibility

Actions are nested within a group using the same right arrow button used for if actions and foreach loops. The group creates a collapsible section in the DTL editor - you can expand the group to see all nested actions, or collapse it to show just the group header. This collapsibility is valuable in large DTLs with hundreds of actions, allowing you to focus on specific sections while hiding others.

Execution Behavior

It's important to understand that groups have no effect on execution. Unlike if actions which execute nested actions only when conditions are true, or foreach actions which execute nested actions repeatedly, groups always execute their nested actions exactly once in sequential order. Groups also don't affect scope or variable visibility - they're purely organizational. If an exam question asks about execution flow or conditional logic, groups don't factor into the answer.

Documentation References

7. Apply switch Actions for Multiple Conditions

Key Points

  • switch Block: Automatic default case created
  • case Conditions: Add multiple case conditions for different scenarios
  • First Match Wins: Only first matching case executes
  • Remaining Cases Skip: Subsequent cases don't evaluate after match
  • default Case: Executes when no case conditions match

Detailed Notes

Switch Overview

The switch action provides multi-condition branching logic in DTL transformations, similar to switch/case statements in programming languages. When you have multiple possible conditions that require different transformation logic, switch is often clearer and more efficient than nested if/else structures. A switch block automatically includes a default case that executes when none of the case conditions match.

Adding Case Conditions

After creating the switch block, you add individual case conditions. Each case defines a specific condition to test (like source.PID:8 = "M" for male patients, or source.PV1:2 = "I" for inpatients). Under each case, you nest the transformation actions that should execute when that condition is true. The case actions can include any DTL actions - field assignments, function calls, nested if statements, foreach loops, or even other switch statements.

First Match Behavior

A critical characteristic of switch behavior is that only the first matching case executes. The DTL engine evaluates case conditions in order from top to bottom. When it finds the first case whose condition is true, it executes the nested actions for that case and then exits the switch entirely, skipping evaluation of all remaining cases. Even if multiple case conditions would be true, only the first match executes.

For example, consider a switch with case1: source.PID:8 = "M", case2: source.PV1:2 = "I", case3: source.PID:8 = "M" AND source.PV1:2 = "I". If the source message has a male inpatient (both conditions true), only case1 executes because it's evaluated first and matches. case2 and case3 are never evaluated. This first-match behavior is important for understanding exam questions about switch execution flow.

The Default Case

The default case executes when none of the case conditions match. This provides a fallback transformation for unexpected or unhandled scenarios. For example, if you have cases for gender "M" and "F" but the source message has gender "U" (unknown), the default case would execute. Understanding how default interacts with the case conditions is important for exam scenarios about switch behavior.

Documentation References

8. Test DTL Transformations

Key Points

  • Compilation Required: Must compile DTL before testing
  • Test Button: Opens testing interface with source input area
  • Changed Segments: Marked with asterisk (*) or shown in red
  • Content Persistence: Source message persists between test runs
  • Compilation Reminder: Error message if DTL not compiled

Detailed Notes

Testing Overview

The DTL editor includes built-in testing functionality that allows you to validate transformations without deploying them to a production environment. This testing capability is essential for development and troubleshooting, enabling rapid iteration on transformation logic. However, there are important requirements and behaviors to understand for effective DTL testing.

Compilation Requirement

Before you can test a DTL, it must be compiled. If you've created a new DTL or made changes since the last compilation, you must save and compile the DTL before testing. If you attempt to test an uncompiled or modified DTL, the testing interface displays an error message indicating that compilation is required. This is a common source of confusion during development but is essential because the test function executes the compiled DTL class, not the DTL definition in the editor.

Using the Test Interface

To test a DTL, click the Test button in the editor toolbar. This opens a testing interface with two main panels: a source message input area at the top, and a target message result area at the bottom. You paste or type an HL7 message into the source area and click the Transform button. The DTL executes with your test message as input, and the resulting transformed message appears in the target area.

Identifying Changes

The testing interface helps identify what changed in the transformation by marking modified segments. Segments that were added, removed, or had fields changed are marked with an asterisk (*) in some versions of the editor, or displayed in red text. This visual highlighting helps you quickly verify that the transformation affected the expected segments. However, the interface doesn't highlight individual fields within segments - the marking is at the segment level.

Message Persistence

An important behavior to understand is that the testing interface persists the source message between test runs. After testing a DTL with a particular message, if you make changes to the DTL and test again, the same source message is still in the input area. You don't need to re-paste it. This persistence is convenient for iterative development but can be confusing if you forget which test message you're using.

Documentation References

Exam Preparation Summary

Critical Concepts to Master:

  1. Message Classes: EnsLib.HL7.Message (full messages), EnsLib.HL7.Segment (subtransforms)
  2. DocType Format: Version:MessageType with colon separator (e.g., 2.5:ADT_A01)
  3. Create=New vs Create=Copy: New=empty target, Copy=source duplicated to target
  4. Subtransformations: Reusable segment-level transforms called from message DTLs
  5. Action Types: Set (copy), Clear (remove), If (conditional), ForEach (loops)
  6. Property Path Syntax: Segment:Field.Component.Subcomponent notation
  7. Functions: String manipulation, date formatting, lookup tables

Common Exam Scenarios:

  • Selecting appropriate message class for DTL requirements
  • Choosing Create=New vs Create=Copy for different use cases
  • Building subtransformations for reusable segment logic
  • Using conditional actions (If) for data-dependent transformations
  • Applying functions for data formatting and conversion
  • Testing DTLs with sample messages
  • Debugging transformation errors

Hands-On Practice Recommendations:

  • Create DTLs with both Create=New and Create=Copy settings
  • Build segment-level subtransformations for reuse
  • Use ForEach for repeating segments and fields
  • Apply string and date functions in transformations
  • Configure lookup tables for code translations
  • Test transformations with various message samples
  • Debug DTL issues using the testing interface

Report an Issue