Encontrar

記事
· 2025年5月22日 5m read

在IRIS中基于XSLT实现互联互通临床文档到 FHIR 资源的转换

基于 XSLT 互联互通临床文档到 FHIR 资源转换

国家卫健委互联互通成熟度评测中的临床共享文档,作为医疗信息交换的重要载体,采用了XML标准的文档格式。随着医疗信息化的发展,FHIRFast Healthcare Interoperability Resources)作为新一代医疗信息交换标准,因其简洁性、灵活性和RESTful架构,逐渐成为医疗数据交换的理想选择。将共享文档文档转换为FHIR资源,能够有效促进不同医疗系统间的数据互通,提升医疗信息的利用价值。

XSLT(可扩展样式表语言转换)是一种用于将XML文档转换为其他XML文档或文本格式的语言。在医疗数据转换场景中,XSLT凭借其强大的XML处理能力,成为共享文档FHIR转换的理想工具。

我们知道共享文档文档是一种结构化的XML文档,通常包含以下主要部分:

- 文档头(Document Header):包含文档元数据,如文档类型、创建时间、作者等

- 临床数据部分(Clinical Sections):按章节组织的临床信息,如问题列表、用药记录、检查报告等

- 数据条目(Entries):具体的临床数据项,如诊断、药物、检验结果等

 

FHIR则采用了资源导向的设计理念,每个临床概念都被建模为独立的资源,通过RESTful API进行访问。FHIR资源具有以下特点:

- 模块化设计:每个资源专注于特定的临床领域,如Patient(患者)、Condition(疾病)、MedicationRequest(用药申请)等

- 灵活的数据结构:支持复杂的数据类型和嵌套结构

- 丰富的语义表达:通过代码系统和扩展机制提供标准化的术语支持

互联互通共享文档FHIR的转换并非简单的格式转换,而是需要在保持临床语义的前提下,将共享文档的文档结构映射到FHIR的资源模型。这需要深入理解两种标准的数据模型和语义。

Intersystems IRIS中,我们内嵌了我司创建的SDA医疗数据模型,此模型也是以xml为结构,并且在IRIS中已经开箱即用地实现了SDA模型到FHIR资源的转化,所以在IRIS互联互通套件中把共享文档向FHIR资源转化的思路就变成了由互联互通共享文档->SDA文档->FHIR资源的转化流程。(关于我司SDA数据模型的介绍参见https://docs.intersystems.com/irisforhealth20251/csp/docbook/Doc.View.cl...

下面是一个使用XSLT互联互通文档中的信息转换为SDA再使用IRIS开箱即用功能转为FHIR资源的示例:

在互联互通套件中,我们已经实现了由互联互通文档向SDA转化的xslt,这些xslt在https://gitee.com/jspark/CCHDist 代码仓库的https://gitee.com/jspark/CCHDist/tree/master/image-iris/src/hccns/Setting/HCC 部分可以找到,文件名为HCC2SDA.xsl,其内引用的其他xlst模版也在相同文件夹下。

互联互通文档转化为SDA文档的示例代码:

Method HCCToSDA(pHCC As %Stream.Object, ByRef pSDA As %Stream.Object) As %Status
{
    Set tSC = $$$OK
    Try
    {
        If $ISOBJECT(pSDA) &&(pSDA.%IsA("%Stream.Object"))
        {           
        }
        Else
        {
            Set tSC = $$$ERROR(-10000,"Input parameter pSDA is not a stream")
            Quit
        }

        // transfter to SDA first
        Set tSlash = $Case($system.Version.GetOS(),"Windows":"\",:"/")
        Set tXSL="file:///"_$SYSTEM.Util.InstallDirectory()_"csp"_tSlash_"xslt"_tSlash_"HCC"_tSlash_"HCC2SDA.xsl"
        Set tSC = ..Transformer.Transform(pHCC,tXSL,.tSDA)
        Quit:($$$ISERR(tSC))
        D pSDA.CopyFrom(tSDA)
        
        // store SDA for debug purpose
        if (..Debug=1)
        {
            Set ..FileGUID = $Case($system.Version.GetOS(),"Windows":"\",:"/")_$SYSTEM.Util.CreateGUID()
            Set tSDAFile=##class(%Stream.FileCharacter).%New()
            Set tSC=tSDAFile.LinkToFile(..DebugPath_..FileGUID_".XML")
            Set tSDAFile.TranslateTable="UTF8"
            Do tSDAFile.Write(pSDA.Read())
            Do tSDAFile.%Save(),tSDAFile.%Close()
            Kill tSDAFile
        }
    }
    Catch ex 
    {
        Set tSC=ex.AsStatus()
    }   
    Quit tSC
}

 

SDA转化为FHIR资源的示例代码:

Method SDAToFHIR(pSDA As %Stream.Object, ByRef pFHIR As %Stream.Object) As %Status
{
    If ($ISOBJECT(pSDA) && pSDA.%IsA("%Stream.Object"))
    {}
    Else
    {
        Quit $$$ERROR(-10000,"Input parameter pSDA is not a stream")
    }
        
    Set tSC = $$$OK
    Try
    {
        // transfer SDA to FHIR
        Set tFHIR = ##class(HS.FHIR.DTL.Util.API.Transform.SDA3ToFHIR).TransformStream(pSDA,"HS.SDA3.Container","R4")
        If ('$ISOBJECT(tFHIR))
        {
            K tFHIR
            Set tSC = $$$ERROR(-10000,"SDA transfer to FHIR error!")
            Quit
        }
        Else
        {
            Set:($Get(pFHIR)="") pFHIR=##class(%Stream.TmpCharacter).%New()
            
            Do pFHIR.Write(tFHIR.bundle.%ToJSON())
            Do tFHIR.%Close()
            
            // store SDA for debug purpose
            if ..Debug=1
            {
                Set tFHIRFile=##class(%Stream.FileCharacter).%New()
                Set tSC=tFHIRFile.LinkToFile(..DebugPath_..FileGUID_".JSON")
                Set tFHIRFile.TranslateTable="UTF8"
                Do pFHIR.Rewind()
                Do tFHIRFile.Write(pFHIR.Read())
                D tFHIRFile.%Save(),tFHIRFile.%Close()
                K tFHIRFile
            }
        }
    }
    Catch ex 
    {
        Set tSC=ex.AsStatus()
    }
    
    Quit tSC
}

综合起来互联互通文档转化为FHIR资源的示例,这里pFHIR的输出就是得到的fhir资源:

Method HCCToFHIR(pHCC, ByRef pFHIR) As %Status
{
    If ($ISOBJECT(pHCC) && pHCC.%IsA("%Stream.Object"))
    {}
    Else
    {
        Quit $$$ERROR(-10000,"Input parameter pHCC is not a stream")
    }

    // transfter to SDA first
    Set tSDA = ##class(%Stream.GlobalCharacter).%New()
    Set tSC = ..HCCToSDA(pHCC,.tSDA)
    Quit:($$$ISERR(tSC)) tSC

    // store SDA for debug purpose
    Set tSC = ..SDAToFHIR(tSDA,.pFHIR)
    Quit tSC
}

 

在我们的IRIS互联互通套件里实现了由共享文档生成再到FHIR资源的转化的全部流程,https://gitee.com/jspark/CCHDist 可以在这个代码仓库中找到IRIS互联互通套件的代码实现以及相关介绍文档。

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
質問
· 2025年5月22日

Subscript indirection behaves differently in if statement

Hello Community,

When I run the following code with x undefined in terminal, it throws a syntax error and returns control to the program stack. After issuing a GO command, execution continues, and setting the global variable ^zz1.

code 1:

test.mac
if $Data(@x@(a,b,c)) {
    set ^zz1=1212
}
write !,1212,!
//
//or
if $Data(@x@(a,b,c)) set ^zz1=1212
write !,1212,!

 if I assign the result of $D(@x@(a,b,c)) to a local variable like d using set d=$D(@x@(a,b,c)), and then use if d { ... }, the code fails(global is not set) working as expected.

Code 2

test1.mac
set d=$D(@x@(a,b,c))
 if d {
     set ^zz1=1212
 }
 write !,1212,!
 ;
 if d set ^zz1=1212
 q

So, Why The body of the if statement is not tied to the success and it sets the global in the code 1.

Thanks!

7 Comments
ディスカッション (7)1
続けるにはログインするか新規登録を行ってください
記事
· 2025年5月22日 9m read

codemonitor.MonLBL - Line-by-Line ObjectScript Code Monitoring

Introduction

MonLBL is a tool for analyzing the performance of ObjectScript code execution line by line. codemonitor.MonLBL is a wrapper based on the %Monitor.System.LineByLine package from InterSystems IRIS, designed to collect precise metrics on the execution of routines, classes, or CSP pages.

The wrapper and all examples presented in this article are available in the following GitHub repository: iris-monlbl-example

1 Comment
ディスカッション (1)2
続けるにはログインするか新規登録を行ってください
記事
· 2025年5月22日 6m read

InterSystems IRIS Workflow Engine によるタスクのフロー - はじめに

しばらくの間、私はワークフロー機能について何らかの概念実証を行おうと計画していましたが、これは IRIS に存在する他の多くの機能と同様に、お客様にほとんど気付かれないまま終わってしまう傾向があります(その点については申し訳ありません)。 そこで数日前、この機能を構成して、Angular で開発したユーザーインターフェースに接続して使用するための例を作成することに決めました。

記事が非常に長くならなずに読みやすくするために、3 部に分けて説明しようと思います。 この最初の記事では、Workflow の機能とこれから解決する例について説明します。 2 つ目の記事では、Workflow の管理を担うプロファクションの構成と実装について詳しく説明します。 最後に、ウェブアプリケーションを通じて Workflow にある情報にアクセスする方法を説明します。

InterSystems IRIS Workflow Engine

この Workflow 機能を説明するには、IRIS ドキュメントに記載の説明をコピーするのが一番でしょう。

ディスカッション (0)0
続けるにはログインするか新規登録を行ってください
記事
· 2025年5月22日 7m read

InterSystems IRIS Workflow Engine によるタスクのフロー - 構成

前回の記事では、一般的な概念と、InterSystems IRIS に統合されたタスクエンジンを使用して解決する問題を紹介しました。今回の記事では、相互運用性プロダクションを構成してソリューションを提供する方法を確認します。

Workflow Engine の構成

First we are going to define the roles of the tasks that we are going to manage, in our example we are going to define two types:

  • AutomaticBloodPressureRole: ユーザーの介入が不要な自動タスクを作成します。
  • ManualBloodPressureRole: ユーザーが手動で検証する必要のあるタスクを作成します。

ディスカッション (0)0
続けるにはログインするか新規登録を行ってください