用Java读取电子数据交换数据


在本Java教程中了解有关读取电子数据交换数据的更多信息。

如今,大多数Java开发人员希望与JSON打交道,以便与其他系统和企业交换数据。然而,当JSON不是一个选项时会发生什么呢?很容易忘记还有其他数据交换格式,其中一些更难处理。其中一种格式称为电子数据交换。EDI本身有多种风格——例如X12和EDITEL——因此代码读取可能并不总是“一刀切。”

你可能还喜欢:[DZone Refcard] Understanding Stream Processing

从表面上看,读取电子数据交换数据似乎是一项简单的工作。开发人员可能会看到一个示例文件,并试图使用他或她的编程语言标准库中可用的基本字符串解析API来读取它。不幸的是,这并不总是有效的,并且很难进行数据验证和有效地处理文档的结构。

什么是电子数据交换?导言

电子数据交换是一个通用术语,涵盖了企业(或任何两方)之间交换数据的几种标准数据格式。最常用的两个标准是X12和EDIFACT。这两种标准都表示一系列命名段(基本上是包含单个字段的记录)中的数据。例如,一个简单的段可能如下所示:

SEG*SMITH*JOHN*20190101~

在本例中,段的名称是“SEG”,它包含三个字段——两个字符串和一个日期。每个字段(称为一个元素)通过分隔符与其他字段分开*(星号),段的结尾用分隔符表示~(颚化符)。

电子数据交换也有类似于XML或JSON的结构,其中段嵌套在称为循环的开始/结束边界内。在这个例子中,X12确认交换如下所示;添加缩进是为了强调结构。然而,在实践中,通过查看未格式化的电子数据交换文件,结构并不明显。

ISA*00*          *00*          *ZZ*Receiver       *ZZ*Sender         *191031*1301*^*00501*000000001*0*P*:~
  GS*FA*ReceiverDept*SenderDept*20191031*130123*000001*X*005010X230~
    ST*997*0001~
      AK1*HC*000001~
        AK2*837*0001~
          AK3*NM1*8**8~
          AK4*8*66*7*MI~
        AK5*R*5~
      AK9*R*1*1*0~
    SE*8*0001~
  GE*1*000001~
IEA*1*000000001~


将电子数据交换解读为一系列事件

读取电子数据交换的一个选择是将数据作为事件流进行处理。这StAEDI(发音为“稳定”)Java库对电子数据交换采用与标准Java StAX应用编程接口处理XML(一系列事件)相同的方法。一个只列出片段名称的简单程序可能如下所示:

EDIInputFactory factory = EDIInputFactory.newFactory();
InputStream stream = new FileInputStream("my_edi_file.txt");
EDIStreamReader reader = factory.createEDIStreamReader(stream);
EDIStreamEvent event;

while (reader.hasNext()) {
  event = reader.next();

  if (event == EDIStreamEvent.START_SEGMENT) {
    System.out.println("Segment: " + reader.getText());
  }
}


如果您熟悉用于XML的StAX应用编程接口,这看起来应该很熟悉。这EDIStreamReader在类似于迭代器或数据库结果集的循环中使用。每次调用next方法将从EDI文件中返回下一个数据事件。除了用于段开始的事件外,还有用于处理的事件:
  • 交换的开始和结束(ISA /IEA 在X12中,UNB /UNZ 用于EDIFACT)
  • 消息组的开始和结束(GS /GE 在X12中,UNG /UNE 用于EDIFACT)
  • 交易的开始和结束(ST /SE 在X12中,UNH /UNT 用于EDIFACT)
  • 循环的开始和结束(取决于配置)
  • 段的开始和结束
  • 复合元素的开始和结束
  • 单个数据元素
  • 分段错误
  • 数据元素错误

结构和验证怎么样?

使用电子数据交换处理StAEDI将只给你基本的结构和验证(交换,分组和交易信封结构)。如果您需要处理事务中数据的结构和验证(您可能需要这样做),那么计划必须提供。模式松散地基于标准的XML模式语法,并提供事务中段和元素顺序的详细信息。此外,可以对元素的长度和数据类型进行约束。

X12示例的电子数据交换模式997 上面的事务可以用下面的XML来定义。这transaction 元素及其子元素定义了事务的结构。每个段引用segmentType 下面定义的元素,每个segmentType 参考elementType s和compositeType 这是必要的。枚举值identifier 为了简洁起见,大多数情况下省略了元素类型。

<schema xmlns="http://xlate.io/EDISchema/v2">
  <transaction>
    <sequence>
      <segment ref="AK1" minOccurs="1" />
      <loop code="2000" maxOccurs="999999">
        <sequence>
          <segment ref="AK2" />
          <loop code="2100" maxOccurs="999999">
            <sequence>
              <segment ref="AK3" />
              <segment ref="AK4" maxOccurs="99" />
            </sequence>
          </loop>
          <segment ref="AK5" minOccurs="1" />
        </sequence>
      </loop>
      <segment ref="AK9" minOccurs="1" />
    </sequence>
  </transaction>

  <elementType name="E0002" number="2" base="numeric" maxLength="6" />
  <elementType name="E0028" number="28" base="numeric" maxLength="9" />
  <elementType name="E0097" number="97" base="numeric" maxLength="6" />
  <elementType name="E0123" number="123" base="numeric" maxLength="6" />
  <elementType name="E0143" number="143" base="identifier" minLength="3" maxLength="3" />
  <elementType name="E0329" number="329" base="string" minLength="4" maxLength="9" />
  <elementType name="E0447" number="447" base="string" maxLength="4" />
  <elementType name="E0479" number="479" base="identifier" minLength="2" maxLength="2" />
  <elementType name="E0480" number="480" base="string" maxLength="12" />
  <elementType name="E0715" number="715" base="identifier">
    <enumeration>
      <value>A</value>
      <value>E</value>
      <value>M</value>
      <value>P</value>
      <value>R</value>
      <value>W</value>
      <value>X</value>
    </enumeration>
  </elementType>
  <elementType name="E0716" number="716" base="identifier" maxLength="3" />
  <elementType name="E0717" number="717" base="identifier">
    <enumeration>
      <value>A</value>
      <value>E</value>
      <value>M</value>
      <value>R</value>
      <value>W</value>
      <value>X</value>
    </enumeration>
  </elementType>
  <elementType name="E0718" number="718" base="identifier" maxLength="3" />
  <elementType name="E0719" number="719" base="numeric" maxLength="10" />
  <elementType name="E0720" number="720" base="identifier" maxLength="3" />
  <elementType name="E0721" number="721" base="string" minLength="2" maxLength="3" />
  <elementType name="E0722" number="722" base="numeric" maxLength="2" />
  <elementType name="E0723" number="723" base="identifier" maxLength="3" />
  <elementType name="E0724" number="724" base="string" maxLength="99" />
  <elementType name="E0725" number="725" base="numeric" maxLength="4" />
  <elementType name="E1528" number="1528" base="numeric" maxLength="2" />
  <elementType name="E1686" number="1686" base="numeric" maxLength="4" />
  <elementType name="E1705" number="1705" base="string" maxLength="35" />
  <compositeType name="C030">
    <sequence>
      <element ref="E0722" minOccurs="1" />
      <element ref="E1528" />
      <element ref="E1686" />
    </sequence>
  </compositeType>
  <segmentType name="AK1">
    <sequence>
      <element ref="E0479" minOccurs="1" />
      <element ref="E0028" minOccurs="1" />
      <element ref="E0480" />
    </sequence>
  </segmentType>
  <segmentType name="AK2">
    <sequence>
      <element ref="E0143" minOccurs="1" />
      <element ref="E0329" minOccurs="1" />
      <element ref="E1705" />
    </sequence>
  </segmentType>
  <segmentType name="AK3">
    <sequence>
      <element ref="E0721" minOccurs="1" />
      <element ref="E0719" minOccurs="1" />
      <element ref="E0447" />
      <element ref="E0720" />
    </sequence>
  </segmentType>
  <segmentType name="AK4">
    <sequence>
      <composite ref="C030" minOccurs="1" />
      <element ref="E0725" />
      <element ref="E0723" minOccurs="1" />
      <element ref="E0724" />
    </sequence>
  </segmentType>
  <segmentType name="AK5">
    <sequence>
      <element ref="E0717" minOccurs="1" />
      <element ref="E0718" />
      <element ref="E0718" />
      <element ref="E0718" />
      <element ref="E0718" />
      <element ref="E0718" />
    </sequence>
  </segmentType>
  <segmentType name="AK9">
    <sequence>
      <element ref="E0715" minOccurs="1" />
      <element ref="E0097" minOccurs="1" />
      <element ref="E0123" minOccurs="1" />
      <element ref="E0002" minOccurs="1" />
      <element ref="E0716" />
      <element ref="E0716" />
      <element ref="E0716" />
      <element ref="E0716" />
      <element ref="E0716" />
    </sequence>
  </segmentType>
</schema>


解析电子数据交换文件时使用模式是直截了当的。当程序遍历事件流时,应用程序代码必须在事务开始时提供一个模式对象。(段结束前)

EDIInputFactory factory = EDIInputFactory.newFactory();
InputStream stream = new FileInputStream("my_edi_file.txt");
EDIStreamReader reader = factory.createEDIStreamReader(stream);

while (reader.hasNext()) {
  EDIStreamEvent event = reader.next();

  if (event == EDIStreamEvent.START_TRANSACTION) {
    SchemaFactory schemaFactory = SchemaFactory.newFactory();
    Schema txSchema = schemaFactory.createSchema(new FileInputStream("my_edi_schema.xml"));
    reader.setTransactionSchema(txSchema);
  } else {
    // Do something else with the event
  }
}


摘要

你是在用Java编写自定义代码来处理电子数据交换数据吗?你试过吗StAEDI遇到了问题?在评论中给出您的反馈,或者在StAEDIGitHub存储库。

进一步阅读

[DZone Refcard] Understanding Stream Processing

Streaming Data With Spring Boot RESTful Web Services