什么是 XML?
XML (可扩展标记语言)是一种灵活的、基于文本的、独立于平台的格式,用于以结构合理 、人机可读的方式存储和传输数据 。XML 允许用户定义自定义标签来描述数据的含义和组织结构。例如:<book><title>The Hitchhiker's Guide</title></book>.
XML 文档具有自描述性,其结构是一棵分层的元素树。每个文档都有一个封装所有其他内容的根元素。元素可以包含文本、子元素和属性(提供补充信息的名-值对)。这些文档通常用 .xml 文件存储
这种结构的完整性可以通过以下方式实现:
- DTD(文档类型定义):提供基本的验证规则。
- XSD(XML 模式定义):提供高级规则,包括数据类型和约束。
转换 XML 文档
这部分内容介绍如下:
- 解析一般 XML 并将其转换为 HL7 标准。
- 解析 CCDA(综合临床文档架构)文档(XML)并将其转换为 HL7 格式。
在这些实施过程中,两种格式都会首先转换为 InterSystems IRIS SDA(标准化数据架构)格式。这被认为是一种标准、高效、不易出错的方法,因为它有效地利用了平台的 预置类。数据采用 SDA 格式后,可无缝转换为任何目标标准,如 HL7 v2、 FHIR 或 CCDA。
解析通用 XML 文档
通用 XML 文档具有自描述功能,可与 <name>、<sex> 和 <address> 等自定义标记一起使用。本节将介绍如何解析此类文档,并利用它通过中间 SDA(标准化数据架构)格式构建 HL7 消息。
在开始转换之前,您需要选择适当的工作流程:
- 推荐方法:转换为 SDA。这是最有效的方法。它包括将 XML 文档作为数据流读取,并在互操作性生产(Interoperability Production)中将其直接转换为 SDA(标准化数据架构)格式。这种做法是标准的,但对大规模数据处理非常有效。
- 替代方法:手动转换。您可以将 XML 文件作为对象读取,然后以编程方式执行转换。这种方法可提供更精细的控制,但实施起来通常更为复杂,可扩展性也较差。
读取 XML 文档
InterSystems IRIS 为顺利解析 XML 流提供了一套完整的类。其中包括以下两种关键方法:
- %XML.Reader:通过 %XML.Adaptor,提供了一种读取 XML 流并将其内容加载到对象中的编程方法。
- EnsLib.EDI.XML.Document:在互操作性生产中用于动态表示和解析 XML 文档。
使用 %XML.Reader 和 %XML.Adaptor 类
通过将 %XML.Adaptor 和 %XML.Reader 类结合使用,这是一种将 XML 文件或数据流解析为内存对象的强大而直接的技术。
让我们以下面的 XML 文件为例进行说明:
<Patient>
<PatientID>12345</PatientID>
<PatientName>DOE^JOHN</PatientName>
<DateOfBirth>19900101</DateOfBirth>
<Sex>M</Sex>
<PatientClass>I</PatientClass>
<AssignedPatientLocation>GEN^A1</AssignedPatientLocation>
<AttendingDoctor>1234^DOCTOR^JOHN</AttendingDoctor>
</Patient>
首先,您必须创建一个表示 XML 文档结构的类定义。该类必须从 %XML.Adaptor扩展而来 。一旦加载了 XML,数据就可以作为对象的属性使用,从而方便访问和后续代码操作。
Class MyApp.Messages.PatientXML Extends (%Persistent, %XML.Adaptor)
{
Parameter XMLNAME = "Patient"
Property PatientID As %String
Property PatientName As %String
Property Age As %String
Property DateOfBirth As %String
Property Sex As %String
Property PatientClass As %String
Property AssignedPatientLocation As %String
Property AttendingDoctor As %String
ClassMethod XMLToObject(xmlStream As %Stream.Object = "", xmlString, filename = "C:\learn\hl7msg\test.xml")
{
Set reader = ##class(%XML.Reader).%New()
If filename'="" {
Set sc=reader.OpenFile(filename)
}
ElseIf $IsObject(xmlStream){
Set sc=reader.OpenStream(xmlStream)
}
ElseIf xmlString'="" {
Set sc=reader.OpenString(xmlString)
}
Else {
Return $$$ERROR("No file name,string or stream found")
}
If $$$ISERR(sc) Do $system.OBJ.DisplayError(sc) Quit
Do reader.CorrelateRoot($classname())
Do reader.Next(.patient,.sc)
If $$$ISERR(sc) Do $system.OBJ.DisplayError(sc) Quit
ZWrite patient
}
}
XMLToObject 方法可解析文件、流或字符串中的 XML 数据,创建一个类实例,随后可用于程序转换或在互操作性产品中使用。
利用 EnsLib.EDI.XML.Document
EnsLib.EDI.XML.Document类提供了对任何XML内容的运行时和基于XPath的访问,而无需预定义的模式或类。当您需要在运行时动态提取值时,该类是理想之选。只需将您的 XML 加载到该类中,然后使用其方法通过 XPath 表达式快速访问元素即可。
通过保存对象实例,该类还能将 XML 文档直接持久化到EnsLib_EDI_XML.Document表中。
ClassMethod ParseXML(xmlfile As %String="")
{
Set ediXMLDoc = ##class(EnsLib.EDI.XML.Document).ImportFromFile(xmlfile,,.sc)
If $$$ISERR(sc) {
Quit
}
Write ediXMLDoc.GetValueAt("/Patient/PatiendID")
}
然后,您可以在类中声明 GetValueAt() 方法的返回值、局部变量或 JSON 格式。
XML 文件业务服务(EnsLib.EDI.XML.Service.FileService)使用此虚拟文档类进行解析操作。
注意: 在 InterSystems IRIS 中 通过 GetValueAt("XPath")获取过大 字符串 (超过 3,641,144 个字符) 时,通常会收到 <MAXSTRING> 错误。您的代码应包括对这一限制的适当处理。
InterSystems IRIS 中的 XSD 模式加载
XSD(XML 模式定义)概述了 XML 文档的结构、元素、类型和验证规则,以确保数据的一致性和有效性。
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Patient">
<xs:complexType> <xs:sequence> <xs:sequence
<xs:sequence> <xs:element name="Patient
<xs:element name="PatientID" type="xs:string"/> <xs:element name="PatientID" type="xs:string"/>
<xs:element name="PatientName" type="xs:string"/> <xs:complexType
<xs:element name="DateOfBirth" type="xs:string"/> <xs:element name="DateOfBirth" type="xs:string"/>
<xs:element name="Sex" type="xs:string"/> <xs:sequence> </xs:sequence
</xs:sequence> </xs:complexType
</xs:complexType
</xs:element
</xs:schema
在 IRIS 中,加载 XSD 模式有几个主要目的:
- 验证: 它使传入的 XML 文档能够根据预定义的结构进行验证,确保数据的完整性。
- 生成 ObjectScript 类: 它能自动创建反映 XML 结构的 ObjectScript 类,从而简化程序访问。(您可以按照 Studio > Tools > AddIn > XMLSchema 向导加载 XSD 文件并生成类定义)。
- DTL 转换: 它有助于在数据转换语言(DTL)中进行基于模式的转换,从而实现不同格式之间的无缝数据映射。
导入 XML 模式
要将 XML 模式 (.xsd) 文件导入 InterSystems IRIS,请按以下步骤操作:
- 导航至 系统管理门户(System Management Portal)。
- 转到 互操作性 > 互操作 > XML > XML 模式结构(Interoperability > Interoperate > XML > XML Schema Structures)。
- 单击 导入(Import) 按钮。
- 在对话框中选择 schema.xsd 文件,然后单击 OK 完成导入。

所有导入的 XSD 模式都保存在每个命名空间内的 ^EnsEDI.XML.Schema 全局中。全局的第一个下标是模式名称,与管理门户中显示的名称相同。
源 XSD 文件的路径存储 在 ^EnsEDI.XML.Schema(<schema name>, "src",1) 中。
重要提示:如果源文件从其原始位置删除,今后针对模式的任何验证尝试都将导致错误。
使用模式验证 XML
加载模式后,您可以使用下面的自定义代码根据模式验证 XML 文档。为此,您需要提供 XML 文件名称和模式名称作为参数:
ClassMethod XMLSchemaValidation(xmlFileName As %String,XMLSchema As %Stirng="")
{
Set xmlFileName="C:\test.xml"
Set ediXMLdoc1 = ##class(EnsLib.EDI.XML.Document).ImportFromFile(xmlFileName,,.sc)
If $$$ISERR(sc) Quit sc
Set ediXMLdoc1.DocType=XMLSchema
Return ediXMLdoc1.Validate()
}
嵌入式 Python 示例:
Class pySamples.XML Extends %RegisteredObject
{
ClassMethod GetError(er)
{
Return $SYSTEM.Status.GetErrorText(er)
}
ClassMethod pyXMLShcemaValidation(xmlFileName = "C:\\hl7msg\\test.xml", XMLSchema = "Patient") [ Language = python ]
{
import iris
xml_status = iris.ref()
ediXMLdoc = iris.cls("EnsLib.EDI.XML.Document").ImportFromFile(xmlFileName,1,xml_status)
if xml_status.value!=1:
print("XML Parsing error: ",iris.cls(__name__).GetError(xml_status))
else:
print(ediXMLdoc)
}
}
从对象获取模式:
Set object = ##class(MyApp.Messages.PatientXML).%New()
Set XMLSchema = object.XMLSchema()
在探索 SDA 和其他医疗保健信息标准之前,让我们简要了解一下 CDA。
临床文档架构(CDA)
临床文档架构(CDA) 是 HL7 为电子临床文档 制定的 医疗保健标准 ,它定义了这些文档的结构、编码和交换方式,以确保人类和机器的可读性。
CDA 是一种 基于 XML 的标准 ,用于表示以下临床文档:
CDA 文档一般由 <ClinicalDocument> 元素封装,有两个主要部分:页眉和正文。
1.页眉(必填): 它位于 <ClinicalDocument> 和 <structuredBody> 元素之间。它包含文档的元数据,说明文档的内容、创建者、时间、原因和地点。
页眉中的关键元素:
- 患者人口统计数据(recordTarget)、作者(医生、系统)、保管人(负责机构)、文档类型和模板 ID、相遇信息、法律验证器。
2.正文(必填): 它包含临床内容报告,由 <structuredBody> 元素封装,可以是非结构化的,也可以由结构化标记组成。它通常还分为递归嵌套的文档部分:
- 非结构化:可能附带附件(如 PDF)的自由格式文本。
结构化:XML 部分,包含过敏、药物、问题、程序、化验结果等编码条目。
<ClinicalDocument>
... CDA Header ...
<structuredBody>
<section>
<text>...</text>
<observation>...</observation>
<substanceAdministration>
<supply>...</supply>
</substanceAdministration>
<observation>
<externalObservation>...
</externalObservation>
</observation>
</section>
<section>
<section>...</section>
</section>
</structuredBody>
</ClinicalDocument>
CCDA 到 HL7 的转换
在 InterSystems IRIS 中,将 CCDA(综合临床文档架构)文档转换为 HL7 v2 消息是一种常见的互操作性用例。虽然您仍然可以直接使用单步 DTL(数据转换语言)映射,但我们建议您选择称为 SDA (标准化数据架构)的中间数据格式 作为最稳健的方法。
步骤 1:C-CDA 到 SDA(XSLT)
第一步是将输入的 C-CDA 文档转换为 SDA 对象。(SDA 是一种供应商中立的临床数据模型,可简化临床信息的表示)。
- 为什么要使用 SDA? C-CDA 是一种复杂的、分层的 XML 结构,有许多模板和部分。试图将其直接映射到 HL7 v2 信息的扁平、基于分段的配置极为困难,而且往往需要复杂而脆弱的逻辑。SDA 可作为简化的中间模型,从 C-CDA 中提取基本临床数据,避免了 XML 结构的复杂性。
- 它是如何工作的? InterSystems IRIS 提供了一个预建 XSLT 文件库(通常位于 install-dir\CSP\xslt\SDA3 目录中 ),用于将 C-CDA 转换为 SDA。这种转换通常需要使用业务流程或业务操作来调用正确的 XSLT。
所有 InterSystems 医疗保健产品都有一个 XSLT 库,用于将 CDA 文档转换为 SDA,反之亦然。您可以在 install-dir\CSP\xslt\ 查看可用的根级 XSLT 位置。
例如,CCDA-to-SDA 转换如下:
- Consolidated CDA 1.1 CCD 到 SDA、 CCDAv21 到 SDA 转换。
- 合并 CDA 2.1 CCD 到 SDA, SDA 到 C32v25 转换。
从 SDA 转换或转换为 SDA
XML 加载到类对象后,就可以进行转换了。此时,您应创建自定义 DTL,将数据结构映射到 HS.SDA3.Container 或 HS.SDA3.* 特定类中,以构建 SDA 文档。
FHIR
利用 IRIS 内置的数据转换器进行 SDA 转换。您可以参考有关 FHIR 转换的文章。
HL7 V2
- 您可以使用类方法 HS.Gateway.HL7.HL7ToSDA3.GetSDA(),以编程方式将 HL7 信息转换为 SDA。例如,执行 ##class(HS.Gateway.HL7.HL7ToSDA3).GetSDA(pRequest,.tSDA).
- 注意:目前还没有直接从 SDA 转换回 HL7 v2 的编程方法。
关键类、表、全局、链接
类
- %XML.*.cls:所有与 XML 相关的类都可以在此软件包中找到。
- Ens.Util.XML.Validator:该类包含验证 XML 的实用方法。
- EnsLib.EDI.XML.Service.FileService:它是一个业务服务主机。
- %XML.XSLT.Transformer:
- %XML.Writer:
- %XML.Reader:
- %XML.Adaptor:
- %XML.Document:
- %XML.Schema:
- %XML.String:它是 XML 的数据类型类。
- %XML.SAX.Parser:
- HS.SDA3.Container:它是一个主要的 SDA 容器类。
- HS.SDA3.*.cls:SDA 类。
表格
- EnsLib_EDI_XML.Document:该表用于存储 EDI XML 文档。
Globals
- ^EnsEDI.XML.Schema:该全局存储 XSD 模式。
- ^EnsLib.EDI.XML.DocumentD: 该全局保存 EnsLib_EDI_XML.Document 表的数据。
本文概述了 XML 的 基本原理。