基于HL7-V3医疗系统信息交换标准SOAP开发
HL7 卫生信息交换标准(Health Level 7)
标准化的卫生信息传输协议,是医疗领域不同应用之间电子传输的协议。HL7汇集了不同厂商用来设计应用软件之间接口的标准格式,它将允许各个医疗机构在异构系统之间,进行数据交互。
HL7的主要应用领域是HIS/RIS,主要是规范HIS/RIS系统及其设备之间的通信,它涉及到病房和病人信息管理、化验系统、药房系统、放射系统、收费系统等各个方面。HL7的宗旨是开发和研制医院数据信息传输协议和标准,规范临床医学和管理信息格式,降低医院信息系统互连的成本,提高医院信息系统之间数据信息共享的程度。
Health Level 7中的“Level 7”是指OSI的七层模型中的最高一层,第七层。但这并不是说它遵循OSI第七层的定义数据元素,它只是用来构成它自己的抽象数据类型和编码规则。它也没有规定规范说明如何支持OSI第一到第六层的数据。
HL7并没有提供一个完全的“即插即用”解决方案,因为在医疗机构的传输环境中有两个重要的影响因素:
⑴医疗机构的传输环境中缺乏处理的一致性;
⑵产生的结果需要在用户和厂商间进行协商。
因此,它提供的是一个可在较大范围内选择数据和处理流程的灵活系统,并尽可能的包括所有已知的程序(触发器Trigger)和数据(段Segment和域Field)要求。
在HL7通信协议中,消息(Message)是数据交换的基本单位。HL7的消息是自动生成的,它将HL7标准文档自动转化为一个HL7规则数据库和部分程序数据结构代码。实现一个通信标准的具体工作是生成数据结构,以及实现一个构造器(Builder)和一个解析器(Parser)。数据结构表现了标准中各个数据对象的相互关系。构造器将数据结构中的数据转化成能在电子数据交换媒介中传输的数据串。而解析器能够将数据串解析回原来的数据结构。HL7标准是一个文本结构的文档。首先,利用一些文字处理工具将文档中的各个数据定义抽取成数据结构,再将结构的形式存入预先定义的HL7规则数据库。然后,开发一种代码生成器,它根据规则数据库的内容,自动生成某一种计算机语言代码。最后,可将这些代码加入实际应用的程序框架。
图1说明的是用HL7标准实现各种医疗设备互连,其中的ADT指的是入院、出院和转移,通常简称为ADT(Ad-mission、Discharge、Transfer)。ADT主要是关于病人个人信息的生成和更新,以及病人来访等信息数据的交换。由于任何加入医疗系统网络的设备都需要病人的个人信息,ADT是HL7标准中应用最广泛的一个方面。通常,进入一个ADT系统的数据总是要传递给医院的各种系统。
HL7-V3消息格式
<PRPA_IN201311UV02 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ITSVersion="XML_1.0" xmlns="urn:hl7-org:v3">
<id root="2.16.156.10011.0" extension="22a0f9e0-4454-11dc-a6be-3603d6866807"/>
<creationTime value="20070803130624"/>
<interactionId root="2.16.840.1.113883.1.6" extension="PRPA_IN201311UV02"/>
<processingCode code="P"/>
<processingModeCode code="R"/>
<acceptAckCode code="AL"/>
<receiver>
<device>
<id root="2.16.156.10011.0.1.1" extension="2.16.156.10011.0.1.1"/>
</device>
</receiver>
<sender>
<device>
<id root="2.16.156.10011.0.1.2" extension="2.16.156.10011.0.1.2"/>
</device>
</sender>
<controlActProcess>
<subject>
<registrationRequest>
<statusCode/>
<subject1>
<patient>
<!--本地系统的患者ID -->
<id root="2.16.156.10011.0.2.2" extension="F9EE9DCE-6A18-4E98-8E68-FBCAAD379261"/>
<statusCode code="active"/>
<effectiveTime value="20111212141414"/>
<patientPerson>
<!--身份证号-->
<id root="2.16.156.10011.1.3" extension="3425456456666666"/>
<!--姓名-->
<name>ggboy</name>
<!--联系电话-->
<telecom value="028-2222444"/>
<!--手机号码 新增-->
<phone value="15111111111"/>
<!--死亡日期 新增-->
<deadDate value=""/>
<!--国家 新增-->
<country code="156" codeSystem="2.16.156.10011.2.3.3.1" displayName="国家"/>
<!--文化程度 新增-->
<educationalLevel code="10" codeSystem="2.16.156.10011.2.3.3.6" displayName="学历"/>
<!--ABO血型 新增-->
<abo code="2" codeSystem="2.16.156.10011.2.3.1.85" displayName="abo血型"/>
<!--RH血型 新增-->
<rh code="2" codeSystem="2.16.156.10011.2.3.1.250" displayName="rh血型"/>
<!--户口地址 新增-->
<accountAddr value="合肥市蜀山区"/>
<!--出生地址 新增-->
<bornAddr value="六安市霍山县"/>
<!--数据来源 新增-->
<domainId value="90572a5f73be4e35909822e861019073"/>
<!--性别-->
<administrativeGenderCode code="1" codeSystem="2.16.156.10011.2.3.3.4" displayName="性别"/>
<!--出生时间-->
<birthTime value="1993-09-14"/>
<!--联系地址-->
<addr>
<!--非结构化地址(完整地址描述) -->
<streetAddressLine>完整地址描述</streetAddressLine>
<!--地址-省(自治区、直辖市) -->
<state>省</state>
<!--地址-市(地区) -->
<city>市</city>
<!--地址-县(区) -->
<county>区</county>
<!-- 地址-乡(镇、街道办事处) -->
<streetNameBase>乡</streetNameBase>
<!-- 地址-村(街、路、弄等) -->
<streetName>村</streetName>
<!-- 地址-门牌号码 -->
<houseNumber>门牌号码 </houseNumber>
<!-- 邮政编码-->
<postalCode>邮政编码</postalCode>
</addr>
<!--婚姻状况-->
<maritalStatusCode code="20" codeSystem="2.16.156.10011.2.3.3.5" displayName="未婚"/>
<!--民族-->
<ethnicGroupCode code="1" codeSystem="2.16.156.10011.2.3.3.3" displayName="汉族"/>
<!--职业类别代码-->
<asEmployee>
<occupationCode code="13" codeSystem="2.16.156.10011.2.3.3.7" displayName="专业技术人员"/>
<employerOrganization>
<!--工作单位名称-->
<name>公司</name>
<contactParty>
<!--工作联系电话-->
<telecom value="xxx-xxxxxx"/>
<!--工作地址 新增-->
<unitAddr>工作地址</unitAddr>
</contactParty>
</employerOrganization>
</asEmployee>
<asOtherIDs>
<!--健康卡号-->
<id root="2.16.156.10011.1.19" extension="123456"/>
<scopingOrganization>
<!--健康卡发放机构代码-->
<id root="2.16.156.10011.1.5" extension="123456"/>
</scopingOrganization>
</asOtherIDs>
<asOtherIDs>
<!--城乡居民健康档案编号-->
<id root="2.16.156.10011.1.2" extension="38273N237"/>
<scopingOrganization>
<!--建档医疗机构组织机构代码-->
<id root="2.16.156.10011.1.5" extension=""/>
</scopingOrganization>
</asOtherIDs>
<!--联系人-->
<personalRelationship>
<code/>
<!--联系人电话-->
<telecom value=""/>
<relationshipHolder1>
<!--联系人姓名-->
<name></name>
<!--家庭关系 新增-->
<contactRelation code="" codeSystem="2.16.156.10011.2.3.3.8" displayName="家庭关系"/>
</relationshipHolder1>
</personalRelationship>
</patientPerson>
<providerOrganization>
<id root="2.16.156.10011.1.5" extension="123456"/>
<name>xxx医院</name>
<contactParty/>
</providerOrganization>
<!--医疗保险信息-->
<coveredPartyOf>
<coverageRecord>
<beneficiary>
<id root="" codeSystem="2.16.156.10011.2.3.1.248" displayName="城镇职工基本医疗保险"/>
</beneficiary>
</coverageRecord>
</coveredPartyOf>
</patient>
</subject1>
<author>
<assignedEntity>
<id root="2.16.156.10011.0.3.2" extension="12346"/>
<assignedPerson>
<name>测试</name>
</assignedPerson>
</assignedEntity>
</author>
</registrationRequest>
</subject>
</controlActProcess>
</PRPA_IN201311UV02>
- 这是一个患者注册标准报文(可以新增字段)
这段报文的结构还是相当复杂的我们如果通过xml去拼接很费力而且不好维护报文格式校验困难那如何把他泛泛解析成对象处理呢?答案是有的下载一个jar包 trang.jar提取码 wcqt - 使用方法
-
1.报文生成 xsd文件
- 执行命令生成xsd
java -jar trang.jar PRPA_IN201311UV02 .xml PRPA_IN201311UV02.xsd
- 执行命令生成xsd
-
2.根据xsd文件生成java对象
- 执行xjc命令生成javabean
xjc D:\PRPA_IN201311UV02.xsd -p com.xxx.PRPA_IN201311UV02
- -p 指定包路径
- 执行xjc命令生成javabean
-
这里xjc命令生成javabean的时候会出现的重复的对象名字如下图:
我们找到重复行的位置把名字改一下就好了把所有引用它的地方都改掉(这个最后在编辑器里操作你改完名字其他引用找不到会有提示你把相应的改掉就可以了)比如这个重复位置在376行
把这个<xs:complexType name="id">
id换个名字就好了
我们在这换成ids在生成一次
OTMK 生成成功了
xsd 和 javabean代码就不贴了需要的可以根据步骤自己操作一下很方便,至此xml报文就生成javaBean 和 xsd文件接下来就是对数据的提取,xml的校验了
- xml 报文校验
public static boolean validateXml(String xml,String file) {
try {
// 建立schema工厂
SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
// 建立验证文档文件对象,利用此文件对象所封装的文件进行schema验证
File schemaFile =new DefaultResourceLoader().getResource("/数据模板/"+file+".xsd").getFile();
// 利用schema工厂,接收验证文档文件对象生成Schema对象
Schema schema = schemaFactory.newSchema(schemaFile);
Validator validator = schema.newValidator();
// 得到验证的数据源
ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes("UTF-8"));
Source source = new StreamSource(bais);
validator.validate(source);
} catch (SAXException e) {
logger.error(e);
return false;
}catch (IOException e) {
logger.error(e);
return false;
}
return true;
}
file 这个是xml报文的名字(PRPA_IN201311UV02 )方便我找到对应的xsd文件进行校验
- xml 对象转换工具
import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
/**
* @ClassName: JaxbUtil
* @Description: TODO(xml和对象相互转换工具类)
* @author gangyu
* @date 2018年11月23日 上午10:41:08
*/
public class JaxbUtil {
/**
* JavaBean转换成xml 默认编码UTF-8
* @param obj
* @param writer
* @return
*/
public static String convertToXml(Object obj) {
return convertToXml(obj, "UTF-8");
}
/**
* JavaBean转换成xml
*
* @param obj
* @param encoding
* @return
*/
public static String convertToXml(Object obj, String encoding) {
String result = null;
try {
JAXBContext context = JAXBContext.newInstance(obj.getClass());
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);// 是否省略xml头信息
StringWriter writer = new StringWriter();
marshaller.marshal(obj, writer);
result = writer.toString();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* xml转换成JavaBean
* @param xml
* @param c
* @return
* @throws JAXBException
*/
@SuppressWarnings("unchecked")
public static <T> T converyToJavaBean(String xml, Class<T> c){
T t = null;
JAXBContext context;
try {
context = JAXBContext.newInstance(c);
Unmarshaller unmarshaller = context.createUnmarshaller();
t = (T) unmarshaller.unmarshal(new StringReader(xml));
} catch (JAXBException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return t;
}
}
对象都转换了数据提取封装不难吧?
希望对HL7报文开发的同学有帮助