Skip to content

Validation

Michael Edgar edited this page Aug 2, 2020 · 6 revisions

Overview

Validation of EDI data is performed when reading or writing a stream of data using a schema object. All schemas are instantiated using a SchemaFactory, by providing an InputStream or URL to a schema definition declared using EDI schema syntax. StAEDI supports two types of schemas - a control schema and a transaction schema.

Control Schemas

Control schemas are used for handling the structural segments and elements of a message's envelop. That is, the interchange, group, and transaction header and trailer segments. Developers may provide their own control schemas or use those built in to StAEDI. When providing a custom control schema, it must be given to the EDIStreamReader or EDIStreamWriter prior to the start of an interchange.

Transaction Schemas

Transaction schemas are used to validate the structure and content of a transaction/message. These are the segments and elements that occur within the transaction/message envelop (i.e. ST/SE or UNH/UNT). Developers must always provide a customer transaction schema if required. When reading EDI, the schema must be set on the EDIStreamReader only at the point in the stream where the message header is being handled. In the case of X12, this would be any time between the start of the ST segment and the end of the ST segment. When writing EDI, the schema must be set on the EDIStreamWriter at any time. Developers are responsible for managing whether the writer's transaction schema is set to null or a non-null value. The writer will always use the transaction schema if configured, unless the client application is writing control segment known to the currently-active control schema.

Behavior

Validation errors are reported differently depending on whether an application is reading or writing data.

When reading, errors are signaled as stream events using one of the error values defined in EDIStreamEvent. At the point in the stream where an error occurred, developers may call the getErrorType method to obtain an EDIStreamValidationError value that represents the current error.

When writing, errors will be thrown to the application using EDIValidationException. Each instance of EDIValidationException contains one or more errors that have occurred as a result of the most recent "write" method call. Additional errors may be retrieved using EDIValidationException's getNextException` method.

Both the reader and the writer support the use of error reporters. Using the EDIInputFactory or the EDIOutputFactory, applications may register an EDIInputErrorReporter or EDIOutputErrorReporter instance. The reporters provide an interface for error notification that overrides the default behavior of having the error reported in-stream (during reading) or via an exception (during writing).

Standard Versus Implementation

Often when handling EDI, programs need to make the distinction between the standard schema and an implementation of that schema. For example, the standard may declare that a particular segment may occur five times whereas an implementation agreed upon by trading partners may further define that the same segment may only occur twice, and may even define the allowable values or elements that may be used in each occurrence.

StAEDI supports implementation schemas as an extension to a standard and requires that both are defined in the schema XML file - see example in one of StAEDI's test cases. The information pertaining to the standard is defined by the <transaction> element whereas the implementation is defined by the <implementation> element that follows.

When defining an implementation of a segment or loop structure, the developer may either include or omit the structures components. If a component is omitted it is considered to be "not used" in that implementation.

Consider the following fictional segment definition and implementation.

<schema xmlns="http://xlate.io/EDISchema/v4">
  <transaction>
    <sequence>
      <segment type="S13" maxOccurs="5" />
    </sequence>
  </transaction>

  <implementation>
    <sequence>
      <!--
        When element S13-01 contains "ONE", this occurrence
        of S13 is used for validation.

        Element S13-02 has a minimum occurs of "1", which means it is required for this occurrence.
        Element S13-03 is not listed and would result in an error if found in the EDI data.
      -->
      <segment type="S13" discriminator="1">
        <sequence>
          <element position="1">
            <enumeration>
              <value>ONE</value>
            </enumeration>
          </element>
          <element position="2" minOccurs="1" />
        </sequence>
      </segment>
      <!--
        When element S13-01 contains "TWO", this occurrence
        of S13 is used for validation.

        Element S13-02 is optional.
        Element S13-03 is a required element in this occurrence.
      -->
      <segment type="S13" discriminator="1">
        <sequence>
          <element position="1">
            <enumeration>
              <value>TWO</value>
            </enumeration>
          </element>
          <element position="2" />
          <element position="3" minOccurs="1" />
        </sequence>
      </segment>
    </sequence>
  </implementation>

  <elementType name="E001" base="string" maxLength="5" />
  <elementType name="E002" base="string" maxLength="10" />

  <segmentType name="S13">
    <sequence>
      <element type="E001" />
      <element type="E002" />
      <element type="E001" />
    </sequence>
  </segmentType>
</schema>

A simple transaction containing a single segment (S13) is defined along with an implementation that allows for two occurrences. The differences between the two occurrences are noted in the comments of the schema.

The occurrences are differentiated using an element referenced by the discriminator attribute (the first position in the example). When using the discriminator attribute, the corresponding element must contain an enumeration of values that uniquely identifies the segment/loop occurrence from its peers (segments/loops of the same type in the standard).

If an implementation of a loop, segment, composite, or element does not declare minOccurs or maxOccurs, the value is inherited from the standard. If the standard does not declare the same attributes, the defaults are 0 for minOccurs and 1 for maxOccurs.

Lax Validation (since 1.6.0)

There may be times where you wish to relax validation for the content of some elements, but still ensure segments are received in the correct sequence. This is supported using the any schema element as a child of compositeType and segmentType definitions. When any is used in a segmentType, validation will succeed for any simple or composite element encountered in the segment while parsing (except for binary data). Similarly, when any is used in a compositeType, validation will success for any component element in the composite.

<elementType name="E0143" number="143" base="string" minLength="3" maxLength="3"/>
<elementType name="E0329" number="329" base="string" minLength="4" maxLength="9" />

<compositeType name="C900">
  <sequence>
    <element type="E0143" minOccurs="1" />
    <element type="E0329" />
    <!--
      Two (2) additional components MAY appear in C900 (maxOccurs = 2).
      The first component is REQUIRED due to 'minOccurs'
    -->
    <any minOccurs="1" maxOccurs="2" />
  </sequence>
<compositeType>

<segmentType name="FOO">
  <sequence>
    <element type="E0143" minOccurs="1" />
    <composite type="C900" />
    <!--
      Five (5) additional elements and/or composites MAY appear in segment FOO (maxOccurs = 5).
      None of the undefined elements are required (minOccurs = 0 by default)
    -->
    <any maxOccurs="5" />
  </sequence>
<segmentType>

<segmentType name="BAR">
  <sequence>
    <!--
      Twenty (20) elements and/or composites MAY appear in segment BAR (maxOccurs = 20).
      None of the undefined elements are required (minOccurs = 0 by default)
    -->
    <any maxOccurs="20" />
  </sequence>
<segmentType>