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 |