EDI报文解析本质是字符串分段+结构映射,需依ISA段动态读取分隔符、用状态机处理引号内分隔符、借助EdiFabric等专用库并注意版本支持与空段/转义等真实场景问题。

EDI报文解析本质是字符串分段+结构映射,不是XML/JSON那种有通用解析器的东西
EDI(比如X12、EDIFACT)没有内置schema机制,ISA、GS、ST这些段落靠固定分隔符(~、*、:等)切开,再按位置或关键字提取字段。C#里没现成的XmlSerializer式方案,硬啃字符串或用专用库是唯二靠谱路径。
常见错误现象:IndexOutOfRangeException(字段数不对就崩)、FormatException(日期/数字格式错位)、把SE段误当数据内容——因为所有段都用~结尾,但SE是事务结尾,不参与业务字段映射。
- 先确认报文实际格式:医疗物流常用的是X12 856(发货通知)或837(索赔),开头
ISA段第107位是版本号(如00501),别拿837i的规则去解856 - 分隔符必须从报文头动态读取:
ISA段第4位是元素分隔符(默认*),第3位是子元素分隔符(默认:),第106位是段结束符(默认~),硬编码会挂 - 别用
String.Split('~')直接切全报文:某些字段含~但被引号包围(如"ABC~DEF"),得写状态机跳过引号内分隔符
用EdiFabric比手写解析器快十倍,但要注意License和X12版本支持
EdiFabric是C#生态最成熟的EDI库,能自动生成强类型类(比如X12_00501_837),调用EdiReader.Read就能转对象。但它不是“装了就能用”——医疗场景下,00501版837支持完整,00602版部分段缺失,00702版干脆没覆盖。
使用场景:你拿到的是医院发来的856发货单,要提取REF*BM*(批次号)、N1*SF*(发货方)这类带标识符的循环段,EdiFabric的Loop属性能自动聚合同类段,比手动for遍历安全得多。
- 安装时选对包:
EdiFabric.Core(核心)+EdiFabric.Templates.X12(X12模板),别装EdiFabric.Templates.EDIFACT——医疗物流基本不用EDIFACT - 解析失败时看
EdiValidationResult里的Errors集合,常见是SegmentLengthExceeded(某段超长)或InvalidDate(D8格式写成MMDDYY) - 性能影响:首次加载模板会JIT编译,耗时200ms+,务必复用
EdiReader实例,别每次new一个
医疗字段常含嵌套结构,别用DTO硬映射,改用Dictionary过渡
比如X12 837里的HI段(诊断信息)可能有3–12个子字段,每个又分主码/副码/版本(HI*BK:123456::ICD10),而EdiFabric生成的HI类只暴露HI01–HI12字符串属性,业务逻辑还得自己拆:。
容易踩的坑:为图省事建一个HiSegment DTO,结果发现不同保险商发的837里HI字段顺序不一致(有的HI*AB:123在前,有的HI*BF:456在前),DTO反序列化直接丢数据。
- 用
Dictionary存原始字段键值对,键名按X12标准来(如"HI01_Qualifier"、"HI01_Code"),解析后统一处理 - 对
REF这类多实例段,别依赖索引(REFs[0]),改用REFs.FirstOrDefault(x => x.RefQualifier == "BM"),医疗报文REF类型多达50+种 - 日期字段优先转
DateTime?:X12的D8是YYYYMMDD,但有些老系统发MMDDYY,DateTime.TryParseExact得试多种格式
测试必须用真实报文,mock数据会漏掉分隔符逃逸和空段问题
医疗EDI报文里,IEA段(功能组结尾)前面可能有几十行空格或\r\n,EdiReader默认跳过空白段,但若中间某段只有~(空段),某些版本会抛InvalidSegmentException。
真实报文还藏坑:HL段(层级)的HL03字段标0或1表示是否末级,但有的医院系统填O(字母O)代替0,字符串比较直接失效。
- 测试集至少含3类样本:正常报文、含引号转义字段(
"ABC*DEF")、含空段(REF**123~中第二个*为空) - 别信文档写的“标准分隔符”,抓包看真实报文头的
ISA段第3–4位,曾见过某三甲医院把段结束符设成\n(换行符) - 上线前用
File.ReadAllBytes检查BOM:UTF-8 BOM(EF BB BF)会导致ISA段首字符错位,解析全乱
医疗EDI的麻烦不在语法,而在同一标准下各实现千奇百怪。字段含义、顺序、空值处理、甚至分隔符,都得对着真实报文逐字对齐——文档写得再规范,也抵不过对方系统里一个随手改的配置项。











