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?
Comments
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.
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
}
}
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?1A { set state=3,buffer=buffer_char continue } if state=3,uchar=char,char?1A { 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
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?
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?1A { set state=3,buffer=buffer_char continue } if state=3,uchar=char,char?1A { 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() }}}