Question
· Jan 27, 2023

Account for different parsing technique in EnsLib.HL7.Service.FileService??

I have a system that is sending Line Breaks\Carriage Returns within the text of a field that is breaking the parsing of the message. Does anyone have a way to get around this?

here is what I receive... 

ZPR|29|937952|UH|Physician Assistant - Certified|Primary Privileges:  Physician Assistant|Care of simple fractures including extremity, rib and clavicle; including skeletal
immobilization||

as EnsLib.HL7.Service.FileService parses the message it puts immobilization on a new line because of the hidden line break, and the rest of the message is lost.

I tried using tr, sed, perl from a unix command line to reformat the message before it gets to Ensemble but I can't get the right combination to make sure the Line Feed is not in that field. The users of the system don't understand what I am asking of them and the vendor of the system has been no help either.

Does anyone have a way to create a custom parser that only looks for SEGMENTS to parse the message apart?

Product version: Caché 2018.1
$ZV: Cache for UNIX (IBM AIX for System Power System-64) 2018.1.3 (Build 414U) Mon Oct 28 2019 11:24:02 EDT
Discussion (5)1
Log in or sign up to continue

this might do it:

Class User.Scott 
{
ClassMethod Clean(infile, outfile) As %Status
{
  set in=##class(%Stream.FileCharacter).%New()
  do in.LinkToFile(infile)
  set out=##class(%Stream.FileCharacter).%New()
  set out.Filename=outfile
  do in.Rewind()
  while 'in.AtEnd {
    set line=in.ReadLine()
    set last=($e(line,*)="|")
    if last set sc=out.WriteLine(line)
    else  set sc=out.Write(line)
  }
  do in.%Close()
  set sc=out.%Save()
  quit sc
}
}
ObjectScript
ObjectScript

Hi Scott,

Have created an example state machine to walk three character segment names "AAA" or "AAN".

You can change the hl7 seperator via the parameter as annotated.

Class Test.ReframeHL7 [ Abstract ]
{
/// Broken line HL7 seperator replcaement.
/// Alternatively could use "\.br\""
Parameter hl7newline = "~";
ClassMethod Process(inStream As %Stream.FileCharacter, outStream As %Stream.TmpCharacter)
{
  do inStream.Rewind()
  set:'$IsObject(outStream) outStream=##class(%Stream.TmpCharacter).%New()
  set buffer="",state=0,step=0
  for {
    quit:inStream.AtEnd
    set char=inStream.Read(1)
    set uchar=$ZCVT(char,"U")
    if state=0,char=$C(13) {
      set state=1,buffer=char,step=1
      continue
    }
    if "01"[state,char=$C(10) {
      set state=2,buffer=buffer_char
      continue
    }
    if state=2,uchar=char,char?1{
      set state=3,buffer=buffer_char
      continue
    }
    if state=3,uchar=char,char?1{
      set state=4,buffer=buffer_char
      continue
    }
    if state=4,(((char?1A)&&(uchar=char))||(char?1N)) {
      set state=5,buffer=buffer_char
      continue
    }
    if state=5,char="|" {
      set state=0
      do outStream.Write(buffer_char)
      set buffer="",step=0
      continue
    }
    if state {
      set state=0
      do outStream.Write(..#hl7newline_$E(buffer,step+2,*)_char)
      set buffer=""
      continue
    } 
    if $L(buffer) {
        do outStream.Write(buffer)
        set buffer=""
    }
    set state=0,step=0
    do outStream.Write(char)
  }
  do:$L(buffer) outStream.Write(buffer)
}
 
/// set tSC=##class(Test.ReframeHL7).Test(inFilename,outFilename)
ClassMethod Test(inFilename, outFilename) As %Status
{
  #dim inFile as %IO.FileStream=##class(%IO.FileStream).%New()
  set tSC=inFile.Open(inFilename,"RS")
  quit:$$$ISERR(tSC) tSC
  #dim outFile as %IO.FileStream=##class(%IO.FileStream).%New()
  set tSC=outFile.Open(outFilename,"NWS")
  quit:$$$ISERR(tSC) tSC
  Do ..Process(inFile,outFile)
  Do outFile.Flush()
  Do outFile.Close()
  Do inFile.Close()
  quit $$$OK
}

}

Cheers,

Alex

Hi Scott,

Minimal sub-classing could be like the following:

Note: If there is no modification, it simply presents the original unmodified filestream.

 Class Test.ReframeService Extends EnsLib.HL7.Service.FileService
{
/// Broken line HL7 seperator replcaement.
/// Alternatively could use "\.br\""
Parameter hl7newline = "~";

Method OnProcessInput(pFileStream As %CharacterStream, Output pOutput As %RegisteredObject) As %Status
{
  do ##class(Test.ReframeService).Reframe(pFileStream)
  Quit ##super(.pFileStream,.pOutput)
}

ClassMethod Reframe(inStream As %Stream.FileCharacter)
{
  do inStream.Rewind()
  set outStream=##class(%Stream.TmpCharacter).%New()
  set buffer="",state=0,step=0,modified=0
  for {
    quit:inStream.AtEnd
    set char=inStream.Read(1)
    set uchar=$ZCVT(char,"U")
    if state=0,char=$C(13) {
      set state=1,buffer=char,step=1
      continue
    }
    if "01"[state,char=$C(10) {
      set state=2,buffer=buffer_char
      continue
    }
    if state=2,uchar=char,char?1{
      set state=3,buffer=buffer_char
      continue
    }
    if state=3,uchar=char,char?1{
      set state=4,buffer=buffer_char
      continue
    }
    if state=4,(((char?1A)&&(uchar=char))||(char?1N)) {
      set state=5,buffer=buffer_char
      continue
    }
    if state=5,char="|" {
      set state=0
      do outStream.Write(buffer_char)
      set buffer="",step=0
      continue
    }
    if state {
      set state=0,modified=1
      do outStream.Write(..#hl7newline_$E(buffer,step+2,*)_char)
      set buffer=""
      continue
    } 
    if $L(buffer) {
      do outStream.Write(buffer)
      set buffer=""
    }
    set state=0,step=0
    do outStream.Write(char)
  }
  do:$L(buffer) outStream.Write(buffer)
  do inStream.Rewind()
  if modified {
    do outStream.Rewind()
    do inStream.CopyFromAndSave(outStream)
    do inStream.Rewind()
  }
}

}