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 可能承载影像所见或诊断结论。

解析 HL7 v2.x 时,建议先按段名建立索引,再按字段位置取值;对重复字段(如 PID-3 多个患者 ID)要遍历所有重复项,而不是只取第一个。

四、解析实现要点

一个稳健的解析流程通常包括:读取 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 消息结构:段—字段—分量三层解析与场景映射 原始消息(按段拆行) MSH|^~\&|HIS|HOSP_A|LIS|LAB_B|20240515103000||ORM^O01|MSG00001|P|2.4 PID|1||P123456^^^HOSP_A^MR||张三||19800101|M PV1|1|I|WARD01^101^01||||DOC001^李医生 分隔符声明(MSH-1/MSH-2): | 字段 ^ 分量 ~ 重复 \& 子分量 解析器必须先读取 MSH-1/MSH-2,再按实际分隔符拆分,不能硬编码。 核心段及其业务角色 MSH 消息头 发送/接收/类型 控制ID/版本 PID 患者标识 姓名/生日/性别 主索引匹配 PV1 就诊信息 患者类型/床位 主治医生/就诊号 ORC 通用医嘱 控制码/医嘱号 状态/时间 OBR 观察请求 申请单/项目 标本/开单医生 OBX 观察结果 值/单位/参考 异常标志/状态 场景映射:患者 / 医嘱 / 检验 / 检查 患者入院 ADT^A01 PID 身份 + PV1 就诊 建立患者主索引与床位 医嘱下达 ORM^O01 ORC 控制 + OBR 申请 HIS 向 LIS/RIS 发单 检验结果 ORU^R01 OBR 申请 + OBX 结果 LIS 回传数值与异常标志 检查报告 ORU^R01 OBR 检查项目 + OBX 所见 RIS 回传影像结论 解析顺序: 读 MSH 分隔符 → 按段拆行 → 按字段拆分 → 分量/重复/子分量展开 → 映射本地模型 → 校验必填与编码 关键校验:MSH-10 去重、PID-3 主索引匹配、OBR-4 项目编码对照、OBX-11 结果状态判断。

五、字段映射中的常见问题

第一,字段位置混淆。HL7 v2.x 不同版本字段位置略有差异,例如 PV1-19 在 2.3 与 2.4 中含义一致,但某些段在 2.5 中新增了字段。接口文档必须明确版本号,解析时以 MSH-12 为准。第二,编码字符集不一致。中文姓名、地址、诊断名称在 UTF-8 与 GBK 之间转换时容易乱码,建议在 MSH-18 明确声明,并在接口测试阶段用中文样例验证。第三,重复字段处理。PID-3 可能包含多个患者 ID,OBX 可能重复出现,解析器应保留全部重复项,由业务层决定取哪一个。第四,空字段与缺失字段。HL7 允许字段为空,解析时不能把空字符串误判为“无此字段”,而应结合段定义判断是可选还是必填。

不要用固定下标直接取字段而不先解析 MSH-1/MSH-2。一旦发送方使用非标准分隔符,硬编码解析会整体错位,导致患者 ID、检验结果全部映射错误。

六、接口测试样例建议

在联调阶段,建议准备一组覆盖典型场景的样例消息:ADT^A01 入院、ADT^A03 出院、ORM^O01 检验申请、ORU^R01 检验结果、ORM^O01 检查申请、ORU^R01 检查报告。每条样例应包含中文姓名、多个 OBX、异常标志 H/L、结果状态 F/P/C,以及一个重复 PID-3 字段。测试时重点观察:患者主索引是否匹配成功、医嘱号与申请单号是否回写正确、OBX 数值与单位是否一致、异常标志是否触发临床提醒。只有这些字段在真实消息中逐项验证通过,接口才算具备上线条件。

掌握 HL7 v2.x 的消息结构,关键不是背字段表,而是建立“段—字段—分量”的解析思维,并结合患者、医嘱、检验、检查四类场景理解每个段的业务角色。这样在遇到新接口时,才能快速定位字段、判断映射关系并排查解析异常。