4. HL7 v2.x 消息结构与解析
HL7 v2.x 是医疗信息系统之间最广泛使用的消息交换标准之一。它的核心思想并不复杂:一条消息由若干“段(Segment)”按顺序组成,每个段占一行,段内字段用分隔符切开,字段内还可以继续拆分为分量和子分量。理解 HL7 v2.x,本质上就是理解“段—字段—分量”这三层结构,以及不同业务场景下哪些段必须出现、字段如何映射到本地系统。
一、消息的物理结构:从分隔符开始
一条典型的 HL7 v2.x 消息以 MSH 段开头,段与段之间用回车换行分隔。MSH 段本身既是消息头,也是“分隔符声明段”。常见编码字符如下:
MSH|^~\&|HIS|HOSP_A|LIS|LAB_B|20240515103000||ADT^A01|MSG00001|P|2.4
PID|1||P123456^^^HOSP_A^MR||张三||19800101|M
PV1|1|I|WARD01^101^01||||DOC001^李医生
其中,| 是字段分隔符,^ 是分量分隔符,~ 是重复字段分隔符,\& 是子分量分隔符。MSH-1 固定为字段分隔符,MSH-2 固定为编码字符。解析时如果连这两个字段都读错,后续所有字段位置都会错位,因此解析器第一步必须从 MSH 段动态读取分隔符,而不是硬编码。
二、核心段的业务含义
MSH(Message Header):消息头,定义发送方、接收方、消息类型、触发事件、消息控制 ID、处理 ID、版本号等。例如 ADT^A01 表示患者入院,ORM^O01 表示通用医嘱,ORU^R01 表示检验结果。MSH-10 消息控制 ID 是消息唯一标识,用于去重和追踪。
PID(Patient Identification):患者基本信息段。PID-3 是患者标识列表,通常包含患者 ID、发证机构、ID 类型;PID-5 是姓名,按“姓^名”或“姓^名^中间名”组织;PID-7 是出生日期;PID-8 是性别。PID 段是患者主索引匹配的关键,HIS 与 LIS/RIS 对接时,PID-3 的映射规则必须双方约定一致。
PV1(Patient Visit):就诊信息段。PV1-2 表示患者类型,如 I 住院、O 门诊、E 急诊;PV1-3 是分配地点,通常为“病区^病房^床位”;PV1-7 是主治医生;PV1-19 是就诊号。PV1 把患者与一次具体就诊关联起来,是住院、门诊、急诊场景区分的关键。
ORC(Common Order):通用医嘱段,描述医嘱的公共属性,如 ORC-1 医嘱控制码(NW 新医嘱、CA 取消、XO 变更)、ORC-2 医嘱号、ORC-5 医嘱状态、ORC-9 医嘱时间。ORC 可以独立出现,也可以与 OBR 配合。
OBR(Observation Request):观察请求段,在检验场景中代表“检验申请/标本”,在检查场景中代表“检查申请”。OBR-2 是申请单号,OBR-4 是项目代码与名称,OBR-7 是申请时间,OBR-14 是标本采集时间,OBR-16 是开单医生。一个 OBR 下可以挂多个 OBX。
OBX(Observation Result):观察结果段,承载具体的检验结果或检查发现。OBX-2 是值类型(NM 数值、ST 字符串、CE 编码),OBX-3 是观察标识,OBX-5 是观察值,OBX-6 是单位,OBX-7 是参考范围,OBX-8 是异常标志(H 高、L 低、N 正常),OBX-11 是结果状态(F 最终、P 初步、C 更正)。
三、场景化字段映射
在患者入院场景中,HIS 发出 ADT^A01,PID 提供患者身份,PV1 提供床位和主治医生,接收方据此建立就诊档案。在检验场景中,HIS 发出 ORM^O01,ORC 描述医嘱控制,OBR 描述检验申请,LIS 接收后生成标本与检验任务;检验完成后 LIS 回发 ORU^R01,PID 标识患者,OBR 标识申请,OBX 逐项返回结果。在检查场景中,RIS 与 HIS 之间同样使用 ORM/ORU,但 OBR-4 映射为检查项目,OBX 可能承载影像所见或诊断结论。
四、解析实现要点
一个稳健的解析流程通常包括:读取 MSH-1/MSH-2 确定分隔符;按段分隔符拆行;对每行按字段分隔符拆分;对需要的字段再按分量、重复、子分量逐层展开;最后映射到本地数据模型。下面是一个简化的解析伪代码示例:
读取消息首行 MSH
fieldSep = MSH[3]
compSep = MSH[4]
repSep = MSH[5]
escSep = MSH[6]
subSep = MSH[7]
for each segmentLine in message.split(段分隔符):
segName = segmentLine[0:3]
fields = segmentLine.split(fieldSep)
switch segName:
case "PID":
patientId = fields[3].split(compSep)[0]
patientName = fields[5].split(compSep)[0]
case "OBX":
valueType = fields[2]
value = fields[5]
abnormalFlag = fields[8]
实际工程中还要处理转义字符、空字段、字段长度截断、编码字符集(MSH-18)等问题。例如 MSH-18 为 UNICODE UTF-8 时,中文姓名才能正确解析;若为 ASCII,则可能出现乱码。字段映射表应在接口设计阶段由双方确认,并形成可测试的样例消息集。
五、字段映射中的常见问题
第一,字段位置混淆。HL7 v2.x 不同版本字段位置略有差异,例如 PV1-19 在 2.3 与 2.4 中含义一致,但某些段在 2.5 中新增了字段。接口文档必须明确版本号,解析时以 MSH-12 为准。第二,编码字符集不一致。中文姓名、地址、诊断名称在 UTF-8 与 GBK 之间转换时容易乱码,建议在 MSH-18 明确声明,并在接口测试阶段用中文样例验证。第三,重复字段处理。PID-3 可能包含多个患者 ID,OBX 可能重复出现,解析器应保留全部重复项,由业务层决定取哪一个。第四,空字段与缺失字段。HL7 允许字段为空,解析时不能把空字符串误判为“无此字段”,而应结合段定义判断是可选还是必填。
六、接口测试样例建议
在联调阶段,建议准备一组覆盖典型场景的样例消息:ADT^A01 入院、ADT^A03 出院、ORM^O01 检验申请、ORU^R01 检验结果、ORM^O01 检查申请、ORU^R01 检查报告。每条样例应包含中文姓名、多个 OBX、异常标志 H/L、结果状态 F/P/C,以及一个重复 PID-3 字段。测试时重点观察:患者主索引是否匹配成功、医嘱号与申请单号是否回写正确、OBX 数值与单位是否一致、异常标志是否触发临床提醒。只有这些字段在真实消息中逐项验证通过,接口才算具备上线条件。
掌握 HL7 v2.x 的消息结构,关键不是背字段表,而是建立“段—字段—分量”的解析思维,并结合患者、医嘱、检验、检查四类场景理解每个段的业务角色。这样在遇到新接口时,才能快速定位字段、判断映射关系并排查解析异常。