Written by

Sr Application Development Analyst at The Ohio State University Wexner Medical Center
Question Scott Roth · 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

Comments

Robert Cemper · Jan 27, 2023

Just to understand your requirements correctly.
- a linebreak  $c(13,10)  would only be acceptable if it follows a segment terminator "|" 
- IF YES Is this just a pipe | or a double pipe || as in your example?
This could be a processing rule to check the last chars of the line
and ignoré the linebreak at a mismatch.   
 

0
Robert Cemper  Jan 27, 2023 to Robert Cemper

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)
    elseset sc=out.Write(line)
  }
  do in.%Close()
  set sc=out.%Save()
  quit sc
}
}
0
Alex Woodhead · Jan 29, 2023

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

0
Scott Roth · Jan 30, 2023

Thanks for the suggestions, so I would need to add this to a copy of EnsLib.HL7.Service.FileService to call as it reads in the message? Or would I call a service then send it another service to parse and remove the misc characters before it starts reading it in as HL7?

0
Alex Woodhead  Jan 30, 2023 to Scott Roth

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()  }}}
0