EDIFACT dialects and profiles

Define the EDIFACT dialects your trading partners use as plain Python classes.

EDIFACT in production is a family of dialects. Standards bodies and national networks publish their own segment tables and message structures, and two dialects can reuse the same segment tag with entirely different meanings. Zato handles this by making dialects plain Python. A dialect is a set of segment and message classes, and the engine resolves the right class for each message at parse time.

The platform ships one complete dialect - the Dutch healthcare profiles (MEDLAB, MEDVRI, MEDRAD, MEDSPE) - as a worked example. Everything on this page applies to any dialect you define yourself.

Defining segments

A segment class names its wire tag and declares each element with its position, usage, and format:

from zato.edifact import EDIComponent, EDIComposite, EDIElement, EDISegment, Usage

class Address(EDIComposite):
    street          = EDIComponent[str](position=1, usage=Usage.CONDITIONAL, format='an..24')
    building_number = EDIComponent[str](position=2, usage=Usage.CONDITIONAL, format='an..8')
    city            = EDIComponent[str](position=4, usage=Usage.REQUIRED, format='an..24')
    postcode        = EDIComponent[str](position=5, usage=Usage.OPTIONAL, format='an..10')

class PAD(EDISegment):
    """ The patient's address.
    """
    _segment_tag = 'PAD'

    address = EDIElement[Address](position=1, usage=Usage.REQUIRED, composite='Address')
    phone   = EDIElement[str](position=2, usage=Usage.OPTIONAL, format='an..20')

Attribute names are yours to choose - pick names that read well in services, regardless of what the specification calls the fields.

Defining messages

A message class declares its segments in wire order. Optional and repeatable segments are flagged as such, and nested repeating structures become groups:

from zato.edifact import EDIGroup, EDIGroupAttr, EDIMessage, EDIRepeatableList, EDISegmentAttr, UNH, UNT

class ResultGroup(EDIGroup):
    """ One specimen and its determinations - repeats within the message.
    """
    _leader_tag = 'DET'

    det            = EDISegmentAttr[DET](DET)
    ide            = EDISegmentAttr[IDE](IDE)
    determinations = EDISegmentAttr[EDIRepeatableList](BEP, optional=True, repeatable=True)

class MyLabReport(EDIMessage):
    """ A laboratory report in our dialect.
    """
    _message_type = 'MYLAB'
    _message_version = '1'

    unh       = EDISegmentAttr[UNH](UNH)
    pid       = EDISegmentAttr[PID](PID)
    pad       = EDISegmentAttr[PAD](PAD, optional=True)
    materials = EDIGroupAttr[EDIRepeatableList](ResultGroup)
    unt       = EDISegmentAttr[UNT](UNT)

Because a segment attribute refers to its class directly, two dialects can define segments with the same tag - a PID in one dialect never collides with a PID in another.

Registration and resolution

Defining a message class registers it automatically. At parse time, the engine reads the UNH message identifier and resolves the class from the most specific identity to the least:

  1. The association assigned code, e.g. MRPN32 or NHS003 - profile-specific variants
  2. The type and version pair, e.g. MEDLAB:1
  3. The bare type, e.g. MEDLAB

A message that matches none of these parses into a generic message that stays navigable and serializable - see Message parsing.

Importing the module that contains the classes activates the dialect - there is no other registration step:

# Registers everything the module defines
import my_company.edifact.lab_dialect

from zato.edifact import parse_edifact

msg = parse_edifact(raw).message   # resolves to MyLabReport

Versions and profile variants

Profile variants build on the three-level resolution. A national profile that issues variant codes per message revision registers one class per association code, while a catch-all class under the bare type matches everything else:

class LabReportBase(EDIMessage):
    _message_type = 'MYLAB'          # any MYLAB version

class LabReportV2(LabReportBase):
    _message_type = 'MYLAB'
    _message_version = '2'           # MYLAB:2 specifically

class LabReportRegional(LabReportBase):
    _association = 'RGN014'          # a profile-assigned variant code

The shipped example dialect

zato.edifact.nl contains the Dutch healthcare profiles in full - segments like ZKH, PID, PAD, and BEP, composites for names, addresses, and dates, and the four message classes. Use it directly if you work with these profiles, or read it as a reference implementation when defining a dialect of your own - it exercises groups, repeatable segments and tag-embedded repeat counters.

See also

PageWhat it covers
Message parsingWhat happens between the wire text and your registered classes
Field accessHow the names a dialect declares read and write in services
EDIFACT in healthcare tutorialThe shipped Dutch dialect at work in a complete integration

Learn more


Schedule a meaningful demo

Book a demo with an expert who will help you build meaningful systems that match your ambitions

"We evaluated 12 integration platforms and Zato was the only one to score 100%."

Philip Zuñiga, Assistant Professor, University of the Philippines