发明内容
针对现有技术中的上述不足,本发明提供的一种实现HL7、FHIR标准、自定义XML消息的解析生成方法解决了医疗信息系统之间信息交互难的问题。
为了达到上述发明目的,本发明采用的技术方案为:
提供一种实现HL7、FHIR标准、自定义XML消息的解析生成方法,其包括以下步骤:
S1、构建元素注释信息,得到注释模型;
S2、对待处理消息进行类型识别及预处理,得到待解析消息;
S3、判断注释模型中是否存在与待解析消息对应的元素注释信息,若是则进入步骤S4;否则输出消息解析异常信息,结束解析;
S4、根据元素注释信息解析当前待解析消息,将从待解析消息的同一个根元素中解析得到的信息组装成一个JSON数据组,得到格式为JSON的解析内容;
S5、判断注释模型中是否存在格式为JSON的解析内容所要生成的消息类型的元素注释信息,若是则进入步骤S6;否则输出生成异常信息,结束生成;
S6、对格式为JSON的解析内容的数据组进行遍历,判断注释模型是否存在与解析内容的数据组所对应的元素注释信息,若是则进入步骤S7;否则将解析内容转成XML格式输出;
S7、基于元素注释信息对解析内容的数据组及数据组的数据元生成对应的属性信息和元素信息,完成消息生成,实现HL7、FHIR标准、自定义XML消息之间的相互转换。
进一步地,步骤S2的具体方法为:
获取待处理消息的类型,若类型为HL7V3版本格式、FHIR标准或自定义XML消息则保持其类型不变;若类型为HL7V2版本格式,则将其转换为XML格式;得到待解析消息。
进一步地,步骤S4的具体方法包括以下子步骤:
S4-1、遍历当前待解析消息的根元素,判断根元素能否在注释模型中找到映射信息,对于能找到映射信息的根元素,进入步骤S4-2;对于不能找到映射信息的根元素,输出消息解析异常信息,结束该根元素的解析生成;
S4-2、遍历当前根元素的子元素,判断是否存在同名重复元素,若是则进入步骤S4-3,否则进入步骤S4-4;
S4-3、将同名重复元素在注释模型中进行条件匹配,对于条件匹配成功的同名重复元素,进入步骤S4-5;对于条件匹配失败的同名重复元素,提示警告信息;
S4-4、直接获取并根据该子元素在注释模型中的元素注释信息解析该子元素的信息,将同一个根元素中解析得到的信息组装成一个JSON数据组,得到格式为JSON的解析内容,完成消息解析;
S4-5、根据同名重复元素在注释模型中匹配得到的元素注释信息解析其信息,将同一个根元素中解析得到的信息组装成一个JSON数据组,得到格式为JSON的解析内容,完成消息解析。
进一步地,步骤S4-3中在注释模型中进行条件匹配的具体方法为:
分别获取各同名重复元素的子元素的属性,判断该属性是否在注释模型中存在元素注释信息,若是则为成功匹配到元素注释信息的同名重复元素;否则为未匹配到元素注释信息的同名重复元素。
进一步地,步骤S4-5中根据各子元素在注释模型中记录的元素注释信息解析子元素的信息的具体方法为:
将同名重复元素的子元素的属性所对应的元素注释信息作为该同名重复元素的元素注释信息的限定内容,将同名重复元素的子元素的内容作为该同名重复元素的内容。
进一步地,步骤S7的具体方法包括以下子步骤:
S7-1、从元素注释信息中获取每个数据组的属性,为每个数据组的属性构建一个路径;
S7-2、在对应路径下为数据组中每个数据元构建一个子元素,从元素注释信息中获取数据组中数据元的属性;
S7-3、判断数据元的属性是否存在限定内容,若是则在该数据元对应的子元素中建立一个与该限定内容对应的子元素,即数据元对应的孙元素;
S7-4、从元素注释信息中获取每个数据元的内容对应的数据,若数据元仅有子元素,则将该数据的内容对应的数据作为该子元素的内容;若数据元有孙元素,则将该数据的内容对应的数据作为该孙元素的内容,完成消息填充;
S7-5、对填充完成的消息进行代码转换和格式转换,完成消息生成。
本发明的有益效果为:本方法不需要通过编写代码的方式实现,所以在项目上线过程中可以根据实际情况进行调整,并且现场可以根据需求进行定制化开发,增加了项目对接灵活度,降低了开发人员学习不同标准的成本和开发难度,可以实现可视化的方式统一管理项目现场的标准版本,方便后期维护。
具体实施方式
下面对本发明的具体实施方式进行描述,以便于本技术领域的技术人员理解本发明,但应该清楚,本发明不限于具体实施方式的范围,对本技术领域的普通技术人员来讲,只要各种变化在所附的权利要求限定和确定的本发明的精神和范围内,这些变化是显而易见的,一切利用本发明构思的发明创造均在保护之列。
如图1所示,该实现HL7、FHIR标准、自定义XML消息的解析生成方法包括以下步骤:
S1、构建元素注释信息,得到注释模型;
S2、对待处理消息进行类型识别及预处理,得到待解析消息;
S3、判断注释模型中是否存在与待解析消息对应的元素注释信息,若是则进入步骤S4;否则输出消息解析异常信息,结束解析;
S4、根据元素注释信息解析当前待解析消息,将从待解析消息的同一个根元素中解析得到的信息组装成一个JSON数据组,得到格式为JSON的解析内容;
S5、判断注释模型中是否存在格式为JSON的解析内容所要生成的消息类型的元素注释信息,若是则进入步骤S6;否则输出生成异常信息,结束生成;
S6、对格式为JSON的解析内容的数据组进行遍历,判断注释模型是否存在与解析内容的数据组所对应的元素注释信息,若是则进入步骤S7;否则将解析内容转成XML格式输出;
S7、基于元素注释信息对解析内容的数据组及数据组的数据元生成对应的属性信息和元素信息,完成消息生成,实现HL7、FHIR标准、自定义XML消息之间的相互转换。
如图2所示,本方法所要实现的是HL7V2.x版本、HL7V3版本、自定义XML和FHIR格式的医疗信息之间的解析和生成,例如将HL7V2.x版本的医疗信息通过解析,生成FHIR格式的医疗信息,打通不同格式医疗信息之间的交互,实现数据互调。
在具体实施过程中,注释模型在XML中通过<!- -->进行元素的注释说明,在注释内部通过统一JSON模型表达映射关系。具体注解格式如下:
<!--${
"bindClass": "所属数据组",
"fatherBindClass": "所属父数据组",
"dependent": "是否独立解析",
"card":"标签基数",
"attribute": [
{
"tag": "XML属性标签名",
"bindCode": "数据元",
"defaultValue": "默认值",
"use": "属性是否必填",
"datatype": "数据类型"
}
],
"content": {
"bindCode": "数据元",
"defaultValue": "默认值",
"datatype": "数据类型"
}
}-->
具体元素说明如表1:
表1:元素说明
在映射配置时,可以不需要每次指定数据元所属的数据组即bianClass,可以在XML局部根元素指定,则该根元素下所有解析出的属性值都属于该类。当需要特别指定时可以明确定义bianClass与fatherBindClass。这样有利于提升元素注解的效率和可读性,同时提高注解的灵活性。
在具体实施过程中,由于HL7V3、CDA和FHIR本身都是采用XML表达消息内容,所以对于结构的分析按照XML格式进行统一分析。HL7V2.x标准虽然采用的是特殊分隔符表达交互消息,但是采用开源的技术可以将其变为XML格式。步骤S2的具体方法为:
获取待处理消息的类型,若类型为HL7V3版本格式、FHIR标准或自定义XML消息则保持其类型不变;若类型为HL7V2版本格式,则将其转换为XML格式;得到待解析消息。XML格式自身包含有元素、属性、内容、注释四大部分,元素中还可能包含子元素,而子元素作为一个元素,其通常也包含了属性和内容,此外,属于客户(病人)的信息都可以称作数据元。注释是XML本身支持的机制,通过注释可以进行人为标记和解释。以对HL7V2.x消息进行预处理为例,HL7V2.x格式的原始消息如下:
MSH|^~\&|HIS||||20160426110931||ADT^A01|32440385||2.3.1
EVN|A01|20160426110931
PID||42556118|2085317||张三||19511104000000|F||01|黑龙江省宁安市XXXX镇|||1391162XXXX||M|||23108419511104XXXX
PV1||I|1290030^血管外科病房|A||||||血管外科|||||||||14380123|||||||||||||||||||||||||20160426110923
采用开源技术将该消息转换成XML格式并且基于注释模型进行注释,得到如下待解析消息:
<ADT_A01 xmlns="urn:hl7-org:v2xml">
<!--${"bindClass":"t_adt_a01","fatherBindClass":""}-->
<MSH>
<MSH.1>|</MSH.1>
<MSH.2>^~\&</MSH.2>
<MSH.3>
<HD.1>HIS</HD.1>
</MSH.3>
<MSH.7>
<TS.1>20160426110931
<!--${"content":{"bindCode":"adt_time"}}-->
</TS.1>
</MSH.7>
<MSH.9>
<MSG.1>ADT</MSG.1>
<MSG.2>A01</MSG.2>
</MSH.9>
<MSH.10>32440385
<!--${"content":{"bindCode":"msgId"}}-->
</MSH.10>
<MSH.12>
<VID.1>2.3.1</VID.1>
</MSH.12>
</MSH>
<EVN>
<EVN.1>A01</EVN.1>
<EVN.2>
<TS.1>20160426110931</TS.1>
</EVN.2>
</EVN>
<PID>
<PID.2>
<CX.1>42556118</CX.1>
</PID.2>
<PID.3>
<CX.1>2085317</CX.1>
</PID.3>
<PID.5>
<XPN.1>
<FN.1>张三
<!--${"content":{"bindCode":"patient_name"}}-->
</FN.1>
</XPN.1>
</PID.5>
<PID.7>
<TS.1>19511104000000</TS.1>
</PID.7>
<PID.8>F</PID.8>
<PID.10>
<CE.1>01</CE.1>
</PID.10>
<PID.11>
<XAD.1>黑龙江省宁安市XXXX镇
<!--${"content":{"bindCode":"patient_addr"}}-->
</XAD.1>
</PID.11>
<PID.14>
<XTN.1>1391162XXXX
<!--${"content":{"bindCode":"telephone"}}-->
</XTN.1>
</PID.14>
<PID.16>
<CE.1>M
<!--${"content":{"bindCode":"gender"}}-->
</CE.1>
</PID.16>
<PID.19>23108419511104XXXX</PID.19>
</PID>
<PV1>
<PV1.2>I</PV1.2>
<PV1.3>
<PL.1>1290030
<!--${"content":{"bindCode":"pid"}}-->
</PL.1>
<PL.2>血管外科病房
<!--${"content":{"bindCode":"area"}}-->
</PL.2>
</PV1.3>
<PV1.4>A</PV1.4>
<PV1.10>血管外科
<!--${"content":{"bindCode":"dept"}}-->
</PV1.10>
<PV1.19>
<CX.1>14380123</CX.1>
</PV1.19>
<PV1.44>
<TS.1>20160426110923</TS.1>
</PV1.44>
</PV1>
</ADT_A01>。
步骤S4的具体方法包括以下子步骤:
S4-1、遍历当前待解析消息的根元素,判断根元素能否在注释模型中找到映射信息,对于能找到映射信息的根元素,进入步骤S4-2;对于不能找到映射信息的根元素,输出消息解析异常信息,结束该根元素的解析生成;映射信息即为注释信息;
S4-2、遍历当前根元素的子元素,判断是否存在同名重复元素,若是则进入步骤S4-3,否则进入步骤S4-4;
S4-3、将同名重复元素在注释模型中进行条件匹配,对于条件匹配成功的同名重复元素,进入步骤S4-5;对于条件匹配失败的同名重复元素,提示警告信息;
S4-4、直接获取并根据该子元素在注释模型中的元素注释信息解析该子元素的信息,将同一个根元素中解析得到的信息组装成一个JSON数据组,得到格式为JSON的解析内容,完成消息解析;
S4-5、根据同名重复元素在注释模型中匹配得到的元素注释信息解析其信息,将同一个根元素中解析得到的信息组装成一个JSON数据组,得到格式为JSON的解析内容,完成消息解析。
在步骤S4中,根据消息内容与数据组、数据元的映射关系通过XML注释的方式进行关联后,注释模型对整个消息进行分析,上述例子经过注释模型的分析后会产生如下信息:
a. 路径ADT_A01映射数据组t_adt_a01;
b. 路径ADT_A01/MSH/MSH.7/TS.1映射了急诊时间,数据元标识是adt_time,该数据元属于数据组t_adt_a01;
c. 路径ADT_A01/MSH/MSH.10映射了消息ID,数据元标识是msgId,该数据元属于数据组t_adt_a01。
步骤S4-3中在注释模型中进行条件匹配的具体方法为:
分别获取各同名重复元素的子元素的属性,判断该属性是否在注释模型中存在元素注释信息,若是则为成功匹配到元素注释信息的同名重复元素;否则为未匹配到元素注释信息的同名重复元素。
步骤S4-5中根据各子元素在注释模型中记录的元素注释信息解析子元素的信息的具体方法为:
将同名重复元素的子元素的属性所对应的元素注释信息作为该同名重复元素的元素注释信息的限定内容,将同名重复元素的子元素的内容作为该同名重复元素的内容。
步骤S4-5的目的是针对XML中存在同名重复元素,分别遍历每个重名元素的子元素,通过子元素属性固定值的唯一性作为不同数据元的提取依据。例如一个人有多个姓名,具体的示例如下:
<name>
<use value="official"/>
<family value="Chalmers"/>
<given value="Peter"/>
<given value="James"/>
</name>
<name>
<use value="usual"/>
<given value="Jim"/>
</name>
上述例子中出现了同名重复元素“name”,此时通过name元素的子元素use的value属性进行区分,注释模型分析出如下结果:
name/use[@value="official"]路径下解析出的数据是官方姓名信息;
name/use[@value="usual"]路径下解析出的数据是常用名信息。
上述提及的例子已经转换成了XML格式的消息,并且在根元素位置注释了一个数据组为"t_adt_a01",在不同子元素位置注释了该数据数据组的数据元包括就诊时间(adt_time)、消息ID(msgId)、患者姓名(patient_name)、患者家庭住址(patient_addr)、患者电话号码(telephone)、患者性别(gender)、患者唯一号(pid)、患者住院病区(area)、患者住院科室(dept)。
从根元素ADT_A01开始遍历XML消息,查询到注释模型中绑定有对象"t_adt_a01",所以初始化一个空的"t_adt_a01"数据组。在MSH标签及其子元素遍历时发现ADT_A01/MSH/MSH.7/TS.1路径在注释模型中映射了急诊时间,将该时间值提取出来,按照<key,value>形式将<adt_time, 20160426110931>存入数据组t_adt_a01中;发现ADT_A01/MSH/MSH.10路径在模板中映射了消息ID,提取值将<msgId, 32440385>存入数据组t_adt_a01中;遍历EVN由于没有映射信息所以遍历下个同级节点PID标签;遍历PID标签在遍历到ADT_A01/PID/PID.5/XPN.1/FN.1路径时由于映射了患者姓名,提取患者姓名,将< patient_name, 张三>放入数据组t_adt_a01中;继续遍历其他子节点时发现ADT_A01/PID/PID.11路径映射了患者住址,提取该值,将< patient_addr, 黑龙江省宁安市XXXX镇>存入数据组t_adt_a01中。依次遍历类推将所有数据提取存入到数据组中。当所有的路径遍历完毕时,t_adt_a01数据组中以<key,value>形式存放了所有的提取值,将该数据组转换成JSON格式并输出:
{
"t_adt_a01" : {
"adt_time" : "20160426110931",
"msgId" : "32440385",
"patient_name" : "张三",
"patient_addr" : "黑龙江省宁安市XXXX镇",
"telephone" : "1391162XXXX",
"gender" : "M",
"pid" : "1290030",
"area" : "血管外科病房",
"dept" : "血管外科"
}
}
至此便完成了HL7、FHIR标准、自定义XML消息的解析。
步骤S7的具体方法包括以下子步骤:
S7-1、从元素注释信息中获取每个数据组的属性,为每个数据组的属性构建一个路径;
S7-2、在对应路径下为数据组中每个数据元构建一个子元素,从元素注释信息中获取数据组中数据元的属性;
S7-3、判断数据元的属性是否存在限定内容,若是则在该数据元对应的子元素中建立一个与该限定内容对应的子元素,即数据元对应的孙元素;
S7-4、从元素注释信息中获取每个数据元的内容对应的数据,若数据元仅有子元素,则将该数据的内容对应的数据作为该子元素的内容;若数据元有孙元素,则将该数据的内容对应的数据作为该孙元素的内容,完成消息填充;
S7-5、对填充完成的消息进行代码转换和格式转换,完成消息生成。
在消息生成过程中,以解析得到的JSON格式数据组需要转换为HL7V2.x格式为例,从注释模型根元素ADT_A01开始遍历,得出注释模型关联了对象t_adt_a01,此时为该数据组的属性构建一个路径ADT_A01。继续ADT_A01的子元素遍历,在MSH标签及其子元素遍历时发现ADT_A01/MSH/MSH.7/TS.1元素在注释模型中映射了急诊时间,将adt_time值20160426110931从JSON数据组获取,并将TS.1标签中的值更新为“20160426110931”,当元素节点处理完毕执行,由于没有子元素,进行其他节点遍历。
当遍历到节点ADT_A01/PID/PID.5/XPN.1/FN.1时,由于映射了患者姓名,将<patient_name, 张三>从JSON数据组获取,将FN.1标签值更新为“张三”。当注释模型所有节点遍历完毕时就会产生具体的XML消息内容:
<ADT_A01 xmlns="urn:hl7-org:v2xml">
<MSH>
<MSH.1>|</MSH.1>
<MSH.2>^~\&</MSH.2>
<MSH.3>
<HD.1>HIS</HD.1>
</MSH.3>
<MSH.7>
<TS.1>20160426110931</TS.1>
</MSH.7>
<MSH.9>
<MSG.1>ADT</MSG.1>
<MSG.2>A01</MSG.2>
</MSH.9>
<MSH.10>32440385</MSH.10>
<MSH.12>
<VID.1>2.3.1</VID.1>
</MSH.12>
</MSH>
<EVN>
<EVN.1>A01</EVN.1>
<EVN.2>
<TS.1>20160426110931</TS.1>
</EVN.2>
</EVN>
<PID>
<PID.2>
<CX.1>42556118</CX.1>
</PID.2>
<PID.3>
<CX.1>2085317</CX.1>
</PID.3>
<PID.5>
<XPN.1>
<FN.1>张三</FN.1>
</XPN.1>
</PID.5>
<PID.7>
<TS.1>19511104000000</TS.1>
</PID.7>
<PID.8>F</PID.8>
<PID.10>
<CE.1>01</CE.1>
</PID.10>
<PID.11>
<XAD.1>黑龙江省宁安市XXXX镇</XAD.1>
</PID.11>
<PID.14>
<XTN.1>1391162XXXX</XTN.1>
</PID.14>
<PID.16>
<CE.1>M</CE.1>
</PID.16>
<PID.19>23108419511104XXXX</PID.19>
</PID>
<PV1>
<PV1.2>I</PV1.2>
<PV1.3>
<PL.1>1290030</PL.1>
<PL.2>血管外科病房</PL.2>
</PV1.3>
<PV1.4>A</PV1.4>
<PV1.10>血管外科</PV1.10>
<PV1.19>
<CX.1>14380123</CX.1>
</PV1.19>
<PV1.44>
<TS.1>20160426110923</TS.1>
</PV1.44>
</PV1>
</ADT_A01>
采用开源技术将产生的XML消息内容进行转换,即可得到:
MSH|^~\&|HIS||||20160426110931||ADT^A01|32440385||2.3.1
EVN|A01|20160426110931
PID||42556118|2085317||张三||19511104000000|F||01|黑龙江省宁安市XXXX镇|||1391162XXXX||M|||23108419511104XXXX
PV1||I|1290030^血管外科病房|A||||||血管外科|||||||||14380123|||||||||||||||||||||||||20160426110923
当解析得到的JSON格式数据组需要转换为其他格式类型时,只需要按照其他格式对数据元的插入操作进行相应的操作,即可实现其他格式消息生成。
在本发明的一个实施例中,HL7V2.x、HL7V3、CDA、FHIR都只是将医疗业务数据通过不同的标签进行分隔或包裹,实现交互。将医疗业务数据从这些标准中抽离出来就变成了共性内容,这些业务数据都是由一个个数据项组成,每个数据项都是数据元。数据元包含如表2所示的一些基本属性:
表2:数据元基本属性
序号 |
数据元属性名称 |
约束 |
1 |
数据元标识符 |
必选 |
2 |
数据元名称 |
必选 |
3 |
定义 |
必选 |
4 |
数据元值的数据类型 |
必选 |
5 |
表示格式 |
必选 |
6 |
数据元允许值 |
必选 |
7 |
重复次数 |
必选 |
8 |
分类模式 |
必选 |
数据元根据分类模式归入到不同数据组,如表3所示,根据卫健委2009发布的《电子病历数据组与数据元》标准,基本数据组一共有76个,一级数据组有26个,二级数据组有50个。在实际的使用过程也可以基于基本数据组进行扩展。
表3:基本数据组
其中,数据组与数据元的关系如表4:
表4:数据组与数据元的关系
一条实际的医疗业务数据应该是由多个不同的数据组组成。例如表5所示的病历概要基础模板。
表5:病历概要基础模板
从上述实施例可以看出,本方法主要有以下要求:
1、必须存在唯一根元素,这也是XML的基本要求;
2、在一个元素中,不允许出现同名的属性,这也是XML的基本要求;
3、如果在同层中出现同名的元素,那么这些同名元素肯定被同一个父标签进行包裹,父元素所在层也可以出现同名元素;
4、同层同名元素之间通过多个不同的属性联合进行同名元素区分,属性定义可以有多个,每个属性的值可以是默认值也可以是动态变化的;
5、同层同名元素之间通过各自元素的子元素进行区分,通过子元素名称和属性进行区分;
6、一条医疗数据通过XML表达时,属于相同的分类属性的数据元采用相同的元素和属性进行表达;
7、一条医疗数据当出现多条数据组时,对应的XML标签元素按照数据组的数量进行多次展示,且必须满足第4条或第5条。例如一个人有多个姓名时分为常用名和正式名,name元素通过其子元素use的value属性进行区分。
综上所述,本发明要进行消息解析时根据当前遍历路径信息从注释模型中查询XML元素绑定的数据组和数据元信息,从而提取数据元并组装成数据组。同理在进行消息生成时根据注释模型定义的绑定信息、数据组、数据元信息进行数据动态填充、元素结构动态增加或减少,生成对应的XML消息实例。本方法不需要通过编写代码的方式实现,所以在项目上线过程中可以根据实际情况进行调整,并且现场可以根据需求进行定制化开发,增加了项目对接灵活度,降低了开发人员学习不同标准的成本和开发难度,可以实现可视化的方式统一管理项目现场的标准版本,方便后期维护。