EDML - Electronic Data Markup Language

EDML - Electronic Data Markup Language Specification

Revision History
Date:  19/1/98
Version:   0.6
Comments:  first full draft; for comment

© I A Galbraith and D W Galbraith 1998. EDML is a trademark of OMS Services Ltd. Permission is given for this document to be copied or distributed in whole or in part subject to explicit acknowledgement being given in every case to the authors as the source and copyright owners of the material.

APPENDIX: EDML TYPES

EDML Types are defined by a subset of the generic EDML syntax and directories of Entities which may be used within an application.  Typically, an EDML Type will be based upon an existing standard - a Source Standard.  In such cases, a subset of the EDML syntax is defined which allows generation of EDML Messages, Records and Data Items compatible with the Source Standard, and the structures defined within the Source Standard are re-defined in EDML and incorporated into the EDML Types.  By ‘structures’ we mean message and record definitions, data sub-structure definitions, and code directories.

EDML Type definitions essentially are composed of two parts: message syntax, and message template definitions.  In the example applications below, we define EDML syntax sub-sets which allow will generation of Source Standard messages directly from EDML messages in each case, by program only; ie no table-lookup or mapping is required.

Note that there may be alternative EDML syntaxes possible for a particular Source Standard, though only one EDML Type should be defined.

A.1 EDML/EDIFACT

A.1.1 Syntax

The syntax here is based upon UN/EDIFACT version D.97A.

Syntax is as per EDML/GENERIC except for:
 
HeaderDataItem= "EDML.TYPE=EDIFACT&" | 
"EDML.TYPVER=97A&" | 
"EDML.MESS=MessType&" | 
  "EDML.MESSVER=MessTypeVer&" 
MessType= <name of EDML/EDIFACT message type, eg "PURORD"> 
MessTypeVer= <version number of the Message Type, eg "1.0">
EntityGroup= SegmentGroupGroup | SegmentGroup | ElementGroup 
SegmentGroupGroup= 1*SegmentGroup
SegmentGroup= 1*Segment 
Segment= 1*ElementGroup 
ElementGroup= 1*Element 
Element= CompositeElement | SimpleElement | ComponentElement 
EntityCode= GroupCode | SegmentCode | ElementCode 
ElementCode= CompositeElementCode | SimpleElementCode | ComponentElementCode 
SegmentGroupCode= 1*DIGIT 
SegmentCode= 1*DIGIT 
CompositeElementCode= 1*DIGIT 
SimpleElementCode= 1*DIGIT 
ComponentElementCode= 1*DIGIT 
SegmentTag= 3ALPHA 
EntityID= SegmentGroupID | SegmentID | ElementID 
EntityGroupID= SegmentGroupGroupID | SegmentGroupID | ElementGroupID 
SegmentGroupGroupID= 0*(SegmentGroupID EntityDelimiter) SegmentGroupID 
SegmentGroupID= 0*(NotLastSegmentID EntityDelimiter) LastSegmentID 
NotLastSegmentID= SegmentCode [InstanceDelimiter InstanceCode] 
LastSegmentID= SegmentCode InstanceDelimiter [InstanceCode] InstanceDelimiter  SegmentTag 
ElementGroupID= SimpleElementGroupID | CompositeElementGroupID 
SimpleElementGroupID= SimpleElementID 
CompositeElementGroupID= CompositeElementID EntityDelimiter ComponentElementID 
SimpleElementID= SimpleElementCode [InstanceDelimiter Instance Code] 
CompositeElementID= CompositeElementCode [InstanceDelimiter Instance Code] 
ComponentElementID= ComponentElementCode [InstanceDelimiter Instance Code] 
Name= 0*(SegmentGroupGroupID GroupDelimiter) SegmentGroup GroupDelimiter | ElementGroupID 

A.1.2 Example Message

There follows a fragment of an EDML/EDIFACT Purchase Order message (EDIFACT Message Type "ORDERS", Version D, Release 97A) and its EDIFACT equivalent.
 
EDML/EDIFACT   EDIFACT 
1@@UNH.1-1=1234& 
1@@UNH.2-1=ORDERS& 
1@@UNH.2-2=D& 
1@@UNH.2-3=97A& 
1@@UNH.2-4=UN&
UNH+1234+ORDERS:D:97A:UN’ 
2@@BGM.1-4=PURCHASE ORDER MESSAGE& 
2@@BGM.2-1=1234&
BGM+:::PURCHASE ORDER MESSAGE+1234’
8-9@@RFF.1-1=105& 
8-9@@RFF.1-2=123&
RFF+105:123’ 
11@1.12@@NAD.1=BY& 
11@1.12@@NAD.2-1=OMS& 
11@1.12@@NAD.4-1=OMS LTD& 
11@1.12@@NAD.5-1=87 MOSS LANE& 
11@1.12@@NAD.6=PINNER& 
11@1.12@@NAD.7=MIDDX& 
11@1.12@@NAD.8=HA5 3AT&
NAD+BY+OMS++OMS LTD+87 MOSS LANE+PINNER+MIDDX+HA5 3AT’ 
11@1-21.22@@CTA.1=OC& 
11@1-21.22@@CTA.2-2=IAN&
CTA+OC+:IAN’ 
11@2.12@@NAD.1=SE& 
11@2.12@@NAD.2-1=RTA& 
11@2.12@@NAD.4-1=RTA LTD& 
11@2.12@@NAD.5-1=5 COTTONS GARDENS& 
11@2.12@@NAD.6=LONDON& 
11@2.12@@NAD.8=E2 8DN&
NAD+SE+RTA++RTA LTD+COTTONS GARDENS+LONDON++E2 8DN’ 
101@1.102@@LIN.1=1& LIN+1’
101@1.104@@IMD.3-4=PARTRIDGE& IMD+++:::PARTRIDGE’ 
101@1.106@@QTY.1-1=1& 
101@1.106@@QTY.1-2=1&
QTY+1:1’ 
101@1-128.129@@PRI.1-1=NE& 
101@1-128.129@@PRI.1-2=4.50& 
101@1-128.129@@PRI.1-3=PK&
PRI+NE:4.50:PK’ 
101@2.102@@LIN.1=2& LIN+2’ 
101@2.104@@IMD.3-4=TURTLE DOVES& IMD+++:::TURTLE DOVES’ 
101@2.106@@QTY.1-1=1& 
101@2.106@@QTY.1-2=2&
QTY+1:2’ 
101@2-128.129@@PRI.1-1=CAT& 
101@2-128.129@@PRI.1-2=1000.00& 
101@2-128.129@@PRI.1-3=PE&
PRI+CAT:1000.00:PE’ 
101@3.102@@LIN.1=3& LIN+3’ 
101@3.104@@IMD.3-4=FRENCH HENS& IMD+++:::FRENCH HENS’ 
101@3.106@@QTY.1-1=1& 
101@3.106@@QTY.1-2=3&
QTY+1:3’ 
101@3-128.129@@PRI.1-1=CAT& 
101@3-128.129@@PRI.1-2=0.50& 
101@3-128.129@@PRI.1-3=PE&
PRI+CAT:0.50:PE’ 
- -
- -
- -

A.1.3 Parsing EDML/EDIFACT

Below the results of parsing a series of EDML/EDIFACT data item from the above message are shown.  Each step involves traversing the data item from left to right until a delimiter character ("@", "-", "." , "=" or "&") is encountered.  The example shows how the equivalent EDIFACT records may be created directly from the EDML Data Items.

Example data item:  101@1.104@@IMD.3-4=PARTRIDGE&
 
In the interpretations below, "=>" means "implies"; "->" means "leads to".

Step:
 
Action Description
Split Data Items at  "=" to separate Name and Value 
Parse Name; Locate Group IDs:  101@1.   SegmentGroupGroupID; first occurrence 
104@@IMD.  second last group => SegmentGroupID 
3-4= last group => ElementGroup 
 Parse Group IDs:  101@1. 
      101@   SegmentGroup 28; Line item details 
      1.  first occurrence of Segment Group 28 
104@   Item Description segment 
      @    single occurrence 
 IMD.   SegmentTag = "IMD"; new Tag => new EDIFACT segment 
        (=> EDIFACT segemnt commences with string "IMD+") 
 3-    third element; composite 
        no previous elements 
        (=> concatenate EDIFACT string "++" -> "IMD+++") 
 4=    fourth component; 
        no previous component 
        (=> concatenate EDIFACT string ":::" -> "IMD+++:::") 
Incorporate Value in EDIFACT string   -> "IMD+++:::PARTRIDGE 
Parse next Name  SegmentTag is different  => terminate previous EDIFACT segment 
-> "IMD+++:::PARTRIDGE’" start to build up EDIFACT segment. 

Although in converting to EDIFACT much of the EDML data appears to be ignored - eg the Segment Group and Segment Codes, plus the Instance Codes - this data can be vital if the ordering of the fields within the Web form is not strictly as above.  EDML allows the form designer great latitude in how the form is laid out, and if the Data Items were transferred in a different order - even totally randomly - the EDML naming convention ensures that the correct EDIFACT message structure can be created automatically.
 
 
A.2 EDML/GEDCOM

A.2.1 Syntax

The syntax defined here, for Lineage-linked GEDCOM Form,  is based upon The GEDCOM Standard, Release 5.5 (Family History Department, The Church of Jesus Christ of Latter-day Saints).

Syntax as per generic EDML except for:
 
HeaderDataItem= "EDML.TYPE=GEDCOM&" | 
"EDML.TYPVER=5.5&" | 
"EDML.MESS=LINLINKED&"
EntityCode= RecordCode | SubstructureCode | ElementCode 
RecordCode= HeaderRecordCode | BodyRecordCode 
HeaderRecordCode= "0" 
BodyRecordCode= 1*DIGIT except "0" 
SubstructureCode= 1*DIGIT 
ElementCode= 1*DIGIT 
EntityTag= HeaderRecordTag | BodyRecordTag 
HeaderRecordTag= "HEAD" 
BodyRecordTag= 3*4ALPHA except "HEAD"  or "TRLR" 
EntityID= HeaderRecordID | BodyRecordID | SubstructureID | ElementID 
HeaderRecordID= HeaderRecordCode InstanceDelimiter 
BodyRecordID= BodyRecordCode InstanceDelimiter InstanceCode 
SubstructureID= SubstructureCode [InstanceDelimiter InstanceCode] 
ElementID= ElementCode [InstanceDelimiter InstanceCode] 
EntityGroupID= NotLastEntityGroupID | LastEntityGroupID| HeaderRecordGroupID | BodyRecordGroupID 
NotLastEntityGroupID= 0*(NotLastEntityID EntityDelimiter) NotLastEntityID 
LastEntityGroupID= 0*(NotLastEntityID EntityDelimiter) LastEntityID 
HeaderRecordGroupID= HeaderRecordID InstanceDelimiter HeaderRecordTag 
BodyRecordGroupID= BodyRecordID InstanceDelimiter BodyRecordTag 
NotLastEntityID= EntityCode [InstanceDelimiter InstanceCode] 
LastEntityID= ElementCode InstanceDelimiter [InstanceCode] InstanceDelimiter BodyTag 
Name= BodyRecordID EntityDelimiter (0*(SubstructureID GroupDelimiter) 0*(ElementID EntityDelimiter)) ElementID InstanceDelimiter InstanceDelimiter ElementTag  | 
BodyRecordGroupID 0*(NotLastEntityGroupID EntityGroupDelimiter)  LastEntityGroupID |
 HeaderRecordGroupID |
 BodyRecordGroupID 

A.2.2 Example Message

There follows part of an EDML/GEDCOM message and its GEDCOM equivalent.  The example is taken from GEDCOM Release 5.5 (Copyright © 1987, 1989, 1992, 1993, 1995 by The Church of Jesus Christ of Latter-day Saints.  This document may be copied for the purposes of review or programming of genealogical software.)  The Entity Codes used here are derived from the GEDCOM 5.5 Lineage-Linked Form specification.
 
EDML/GEDCOM  GEDCOM 
0@@HEAD=&  0 HEAD 
0-1@@SOUR=PAF&  1 SOUR PAF 
0-1-1@@VERS=2.1&  2 VER 2.1 
0-2@@DEST=ANSTFILE&  1 DEST ANSTFILE 
0-4@@SUBM=@5@&  1 SUBM @5@ 
0-5@@SUBN=@8@&  1 SUBN @8@ 
0-8@@GEDC=&  1 GEDC 
0-8-1@@VERS=5.4&  2 VERS 5.4 
0-8-2@@FORM=Lineage-Linked&  2 FORM Lineage-Linked 
0-9@@CHAR=ANSEL&  1 CHAR ANSEL 
2@1@INDI=&  0 @1@ INDI 
2@1-2.1@@NAME=Robert Eugene/Williams/&  1 NAME Robert Eugene/Williams/ 
2@1-3@@SEX=M&  1 SEX M 
2@1-4.1@@BIRT=&  1 BIRT
2@1-4.1-1.2@DATE=02 OCT 1822&  2 DATE 02 OCT 1822 
2@1-4.1.3.1@@PLAC=Weston, Madison, CT&  1 PLAC Weston, Madison, CT 
2@1-4.1-1.8.1@@SOUR=@6@&  1 SOUR @6@ 
2@1-4.1-1.8.1-1@@PAGE=Sec.2, p.45&  2 PAGE Sec.2, p.45 
2@1-4.1-1.8.1-2@EVEN=BIRT&  2 EVEN BIRT 
2@1-4.1-1.8.1-2-1@@ROLE=CHIL&  3 ROLE CHIL 
2@1-4.3@@DEAT=&  1 DEAT 
2@1-4.3-1.2@@DATE=14 APR 1905&  2 DATE 14 APR 1905 
2@1-4.3-1.3.1@@PLAC=Stamford, CT&  2 PLAC Stamford, CT 
2@1-4.4@@BURI=&  1 BURI 
2@1-4.4-1.3.1@@PLAC=Spring Hill Cem., Stamford, CT&  2 PLAC Spring Hill Cem., Stamford, CT 
2@1-5.11@@RESI=&  1 RESI 
2@1-5.11-1.4.1@@ADDR=73 North Ashley&  2 ADDR 73 North Ashley 
2@1-5.11-1.4.1-1@@CONT=Spencer, UT84991&  3 CONT Spencer, UT84991 
2@1-5.11-1.2@@DATE=from 1900 to 1905&  2 DATE from 1900 to 1905 
- -
- -
- -

A.2.3 Parsing EDML/GEDCOM

Below the results of parsing an EDML/GEDCOM data item from the above message are shown.  Each step involves traversing the data item from left to right until a delimiter character ("@", "-", "." , "=" or "&") is encountered.  GEDCOM entity names are shown in capitals.

Note that parsing of EDML Names is not necessarily required, since the Name itself defines uniquely how the Value is to be interpreted.  For example, where standard message templates are used to transfer data (eg a Purchase Order), both sender and receiver will ‘know’ what the complete Name string means, with no need for parsing beyond that necessary to distinguish between occurrences of the same Entity.

Example data item:  2@1-4.1-1.8.1-2-1@@ROLE=CHIL&

In this example, ignoring the Instance Code in the first Entity ID gives: 2-4.1-1.8.1-2-1 as the unique identifier for a specific type of data; the Entity Tag is redundant in EDML, and is only present to facilitate direct conversion to the Source Standard format

This identifier may be defined as identifying the role played by an individual in the event described in a source document relating to an individual event.

In the interpretations below, "=>" means "implies"; "->" means "leads to".  Entity names are taken from the GEDCOM 5.5 specification.
 
Step   Interpretation 
2@  RecordCode = 2 => Record = INDIVIDUAL_RECORD.  InstanceCode or InstanceDelimiter should follow.
1-  InstanceCode = 1 => first instance for this record type.  "-" => next entity is nested . 
4. EntityCode = 4 => fourth nested entity within INDIVIDUAL_RECORD  -> INDIVIDUAL_EVENT_STRUCTURE.  "." => next entity starts new group; not nested. 
1-  EntityCode = 1 => first entity within INDIVIDUAL_EVENT_STRUCTURE -> BIRT.  Next entity is nested. 
1.  EntityCode = 1 => first entity nested within BIRT -> EVENT_DETAIL. Next entity is new group; not nested. 
8. EntityCode = 8 => 8th entity within EVENT_DETAIL -> SOURCE_CITATION. Next entity starts new group; not nested.
1- EntityCode = 1 => first entity within SOURCE_CITATION -> SOUR.  Next entity is nested. 
2- EntityCode = 2 => second entity within SOUR -> EVEN.  Next entity is nested. 
1@ EntityCode = 1 => first entity nested within EVEN -> ROLE.  InstanceCode or InstanceDelimiter follows.
@ No InstanceCode is specified. Next entity is EntityTag. 
ROLE= EntityTag = ROLE.  "=" => Name is complete; next string is Value component of data item.
CHIL& Value = "CHIL".

A.3 EDML/HL7
The draft syntax here is based upon the Health Level 7, version 2.3 standard.  The syntax has not yet been fully tested against HL7 message structures.

Syntax is as per generic EDML, except for:
 
HeaderDataItem= "EDML.TYPE=HL7&" |
"EDML.TYPVER=2.3&" |
"EDML.MESS=MessType&" 
MessType= <name of EDML/HL7 message type, eg "ack", "udm", "rde", etc> 
EntityGroup= SegmentGroupGroup | SegmentGroup | FieldGroup 
SegmentGroupGroup= 1*SegmentGroup
SegmentGroup= 1*Segment 
Segment= 1*FieldGroup 
FieldGroup= 1*Field 
Field= SimpleField | CompositeField | ComponentField | SubcomponentField 
EntityCode= SegmentGroupCode | SegmentCode | FieldCode 
FieldCode= SimpleFieldCode | CompositeFieldCode | ComponentFieldCode | SubcomponentFieldCode 
SegmentGroupCode= 1*DIGIT 
SegmentCode= 1*DIGIT 
CompositeFieldCode= 1*DIGIT 
SimpleFieldCode= 1*DIGIT 
ComponentFieldCode= 1*DIGIT 
SubcomponentFieldCode= 1*DIGIT 
SegmentTag= 3ALPHA 
EntityID= SegmentGroupID | SegmentID | FieldID 
EntityGroupID= SegmentGroupGroupID | SegmentGroupID | FieldGroupID 
SegmentGroupGroupID= 0*(SegmentGroupID EntityDelimiter) SegmentGroupID 
SegmentGroupID= 0*(NotLastSegmentID EntityDelimiter) LastSegmentID 
NotLastSegmentID= SegmentCode [InstanceDelimiter InstanceCode] 
LastSegmentID= SegmentCode InstanceDelimiter [InstanceCode] InstanceDelimiter SegmentTag 
FieldGroupID= SimpleFieldGroupID | CompositeFieldGroupID 
SimpleFieldGroupID= SimpleFieldID
CompositeFieldGroupID= CompositeFieldID EntityDelimiter ComponentFieldID [SubcomponentFieldID] 
SimpleFieldID= SimpleFieldCode [InstanceDelimiter Instance Code] 
CompositeFieldID= CompositeFieldCode [InstanceDelimiter Instance Code] 
ComponentFieldID= ComponentFieldCode [InstanceDelimiter Instance Code] 
SubcomponentFieldID= SubcomponentFieldCode [InstanceDelimiter Instance Code] 
Name= 0*(SegmentGroupGroupID GroupDelimiter) SegmentGroupID GroupDelimiter | FieldGroupID