Skip to main content

EDI and Business Documents

TransformScript treats EDI and healthcare business documents (ANSI X12, UN/EDIFACT, and HL7 v2) as structured formats, the same way it treats JSON or CSV. When you set one of these as your input, TransformScript reads the raw interchange into a structure your script can navigate through payload. When you set one as your output, it writes your script's result back into a conforming interchange.

This page covers the data model you work with and how fields get their names. For the format identifiers, delimiters, and per-format properties, see Input and Output Formats.

How EDI Data Is Modeled

An EDI interchange is a sequence of segments. Each segment carries ordered elements (also called fields), which can break down into components and, in HL7, subcomponents, and an element can repeat. TransformScript reads that structure and gives each field a meaningful name.

For X12, EDIFACT, and HL7, payload is an array of segment objects in document order. There is no envelope wrapping the segments. The ISA/GS/ST grouping in X12, or the UNB/UNH grouping in EDIFACT, appears as those segments in sequence. Your script walks the array and reads each segment by name.

Every segment object has a segment key naming it ("ST", "PID", "BEG"). The rest of the keys are its fields:

  • Recognized segments get a named key per field, taken from the field's standard name, such as transaction_set_identifier_code or purchase_order_number.
  • Unrecognized segments fall back to positional keys (field_1, field_2, and so on) in element order.

Here is an X12 ST and BEG read into JSON:

[
  {
    "segment": "ST",
    "transaction_set_identifier_code": "850",
    "transaction_set_control_number": "0001",
    "implementation_convention_preference": null
  },
  {
    "segment": "BEG",
    "transaction_set_purpose_code": "00",
    "purchase_order_type_code": "SA",
    "purchase_order_number": "PO-12345",
    "release_number": null,
    "date": "20200101"
  }
]

Composite elements become nested objects keyed by component name, and repeating elements become arrays. An HL7 MSH with its message-type composite reads like this:

{
  "segment": "MSH",
  "sending_application": "SENDAPP",
  "message_type": {
    "message_code": "ADT",
    "trigger_event": "A01",
    "message_structure": null
  },
  "message_control_id": "MSG00001",
  "version_id": "2.6"
}

Delimiters

TransformScript reads the delimiters from the message itself wherever the format provides them: X12 from the ISA segment, EDIFACT from a leading UNA service-string segment when present, and HL7 from the MSH segment. The message's own delimiter declarations win unless you override them with format properties. For input, you rarely set delimiters by hand. The full property names are on the Input and Output Formats page.

How Fields Get Their Names

Named, readable fields are what make EDI transforms practical. You reference segment.purchase_order_number instead of counting to the third element of BEG. Files.com maintains the field definitions for the standard EDI and HL7 versions, so your transforms use them directly without any external lookup.

TransformScript picks the right definitions by detecting the version from the message: the functional-group version in X12, the directory version in EDIFACT's UNH, and the version field in HL7's MSH. If it can't determine the version, it uses the format's default. Any segment without a definition still appears in payload, with positional field_N keys you can read by counting elements.

Field definitions also carry a type, so recognized numeric fields come back as numbers and date fields are parsed, rather than every value being a string.

Validation

TransformScript uses these definitions for structure and naming, not strict validation. It does not reject a message for unknown segments, extra elements, missing required elements, or out-of-range values. Unknown segments degrade to field_N keys, and extra elements on a known segment simply have no name. It does report an error on genuinely malformed input, such as empty input, a segment with no name, or an invalid header.

On output, the X12 serializer fills in control totals for you: the SE01 segment count and the GE and IEA group counts, and it keeps the ISA separator fields consistent with your configured delimiters.

Because payload is an ordinary array of objects, you navigate it with standard selectors and functions. There is no special EDI query syntax.

%files 1.0
input x12
output json
---
{
  lines: payload filter ($.segment == "PO1"),
  header: payload filter ($.segment == "BEG") [0],
  poNumber: (payload filter ($.segment == "BEG") [0]).purchase_order_number,
  lineCount: sizeOf(payload filter ($.segment == "N1"))
}

HL7 works the same way. Filter by segment ("PID", "OBX"), read named fields, and descend into composite objects (patient.patient_name.family_name) and repeat arrays as needed.

Writing EDI Transforms

An EDI transform is an ordinary TransformScript: set input and output, then filter and map over the segment array.

%files 1.0
input x12
output json pretty=true
---
{
  poNumber: (payload filter ($.segment == "BEG") [0]).purchase_order_number,
  shipTo: payload filter ($.segment == "N1" and $.entity_identifier_code == "ST")
}

To produce EDI, build the same array of segment objects under an EDI output directive. TransformScript maps your named fields back to their positions, applies the delimiters, and fills in X12 control totals.

For examples, see the Cookbook.