如今,大多数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());
}
}
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存储库。