Hi Jeff;

all you have to do is to set the Stream location to a  Global in *TEMP Database.
Example:
 

Ok ... so this actually works:

ClassMethod GetHL7Msg(pId As %String) As %Stream.GlobalCharacter [ SqlName = GetMsg, SqlProc ]
{
    Set tHl7 = ##class(EnsLib.HL7.Message).%OpenId(pId,,.tSC)
    Throw:$$$ISERR(tSC) ..GetErr(-400, "HL7 Message with ID "_pId_" Not Found.")
    Set tMsg = ##class(%Stream.GlobalCharacter).%New()
           SET tMsg.%Location="^mtemp.JEFF"
    Set tSC = tHl7.OutputToLibraryStream(.tMsg)
    Do tHl7.%Close()
    If tSC Set tSC=tMsg.%Save()
    Throw:$$$ISERR(tSC) ..GetErr(-400, $system.Status.GetErrorText(tSC))
    Return tMsg."%%OID"
}

>>>>>

yes

StreamPrefetch looks related but it is totally related to the .NET end (googled SQL prefetch in .NET), 
while <INVALID OREF> is clearly an issue @Ensemble end.
I'm not too deep in the external ODBC  world but I assume that collecting the resultset and
transmitting it to .NET  [ %SYS.SQLStreamSRV ] could happen asynchronously in different processes.
So I doubted %Stream.TempCharacter which is bound to a process private Global  vs. a standard Global visible also to other processes. And only the final %Save nails it down.

I wonder if you experience the same problem if you run your query from
terminal prompt: do $system.SQL.Shell()  
This can signal if the ODBC connection plays a role at all.

%SYS.SQLStreamSRV.obj  is a deployed routine / class so we can't look into its details.
<INVALID OREF> expects a (stream) Object, but it doesn't exist.
So an additional check might be required.  Or you force some content for testing.
 

ClassMethod GetHL7Msg(pId As %String) As %Stream.TmpCharacter [ SqlName = GetMsg, SqlProc ]
{
    Set tHl7 = ##class(EnsLib.HL7.Message).%OpenId(pId,,.tSC)
    Throw:$$$ISERR(tSC) ..GetErr(-400, "HL7 Message with ID "_pId_" Not Found.")
    Set tMsg = ##class(%Stream.GlobalCharacter).%New()
    Set tSC = tHl7.OutputToLibraryStream(.tMsg)

     ;;  Throw:$$$ISERR(tSC) ..GetErr(-400, "HL7 Message with ID "_pId_" failed.") 
         IF 'tMsg.Size DO tMsg.Write("*** no message for ID:"-pId_" ***")
         SET tSC=tMsg.%Save()

    Do tHl7.%Close()
    Return tMsg
}

So you should have always a Stream Object

So my next try would be to add %Save  of the Stream Object before closing  tHl7

ClassMethod GetHL7Msg(pId As %String) As %Stream.TmpCharacter [ SqlName = GetMsg, SqlProc ]
{
    Set tHl7 = ##class(EnsLib.HL7.Message).%OpenId(pId,,.tSC)
    Throw:$$$ISERR(tSC) ..GetErr(-400, "HL7 Message with ID "_pId_" Not Found.")
    Set tMsg = ##class(%Stream.GlobalCharacter).%New()
    Set tSC = tHl7.OutputToLibraryStream(.tMsg)

        IF tSC SET tSC=tMsg.%Save()          

    Do tHl7.%Close()
    Return tMsg
}

this would be a typical exercise to use XSLT support

but for this simple case using $FIND Function in a loop may do it as well.

set a="<Name>ABC</Name><RollNo>45</RollNo><Name>XYZ</Name><RollNo>66</RollNo><Name>xyz</Name>RollNo>89</RollNo>"
set p=1
for  {
      set f=$find(a,"<RollNo>",p) quit:'f
      set t=$find(a,"<",f-1) quit:'t  set p=t-2
      set $e(a,f,p)="**"
     }

in IRIS you have to do it in 2 steps

  • CREATE GLOBAL TEMPORARY TABLE tempfemale (     Category,      CrewNumber,      MedicalCertificationDate,      Seat,      SeatbeltUsed,      Sex,      ShoulderHarnessUsed,      ToxicologyTestPerformed,      childsub ) see: https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.cls?KEY=RSQL_createtable#RSQL_createtable_temp  
  • and INSERT  INTO tempfemale       SELECT       Category, CrewNumber, MedicalCertificationDate,Seat,                    SeatbeltUsed, Sex, ShoulderHarnessUsed, ToxicologyTestPerformed,                                childsub               FROM Aviation.Crew               WHERE Sex = 'F'

see:  https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.cls?KEY=RSQL_insert#RSQL_insert_select 

Further elaborating on the suggestion of @Vic Sun 

set file="c:\whateverfilename.txt"   ;according to file system and access rights
if $data(^%SYS)    ; or whatever global
open file:("WNS")
use file zwrite @$ZR  ; send all output to file
close file

you can even verify it from terminal command line and the result looks like this:

^%SYS("tercap","vt320","bin","hon")=$c(3,155)_"1m"
^%SYS("tercap","vt320","bin","ich")=$c(0,0,155,129,0,0)_"@ÿ"
^%SYS("tercap","vt320","bin","il")=$c(0,0,155,129,0,0)_"Lÿ"
^%SYS("tercap","vt320","bin","il1")=$c(2,155)_"L"
^%SYS("tercap","vt320","bin","ind")=$c(2,27)_"D"
^%SYS("tercap","vt320","bin","init")=$c(18,155)_"!p"_$c(155)_"62""p"_$c(27)_"F"_$c(27)_")0"_$c(155)_"?7h"                                                      ^%SYS("tercap","vt320","bin","poff")=$c(3,155)_"4i"
^%SYS("tercap","vt320","bin","pon")=$c(3,155)_"5i"
^%SYS("tercap","vt320","bin","ri")=$c(2,27)_"M"
^%SYS("tercap","vt320","bin","ron")=$c(3,155)_"7m"
^%SYS("tercap","vt320","bin","uon")=$c(3,155)_"4m"
^%SYS("tercap","vt320","cols")=80
^%SYS("tercap","vt320","flags")=16
^%SYS("tercap","vt320","lins")=24
^%SYS("tercap","vt320","names")="vt320|VT320|DEC-vt320"
^%SYS("tercap","vt320","src","aoff")="$c(155),""0m"""
^%SYS("tercap","vt320","src","bell")="$c(7)"
^%SYS("tercap","vt320","src","bon")="$c(155),""5m"""
^%SYS("tercap","vt320","src","bormap")="1,108,1,108,1,107,1,107,1,109,1,109,1,106,1,106,1,113,1,113,1,120,1,120,1,113,1,113,1,120,1,120,1,108,1,107,1,109,1,106,1,113,1,113,1,120,1,120,1,97,1,97,1,97,1,97,0,42,1,126,1,97"
^%SYS("tercap","vt320","src","clr")="$c(155),""H"",$c(155),""J"""
^%SYS("tercap","vt320","src","coff")="$c(155),""?25l"""

pure COS solution, split into  steps to allow comments (you may condense it of course)

read  arg    ; get something to work on
"Not  Working Example":"x, y, z, a, b, c",

set name=$piece(arg,":",1)   ; split name from content
set content=$piece(arg,":",2)
if $extract(content,1)=""""  {    ; we got a quuted list
           set value=$piece(content,"""",2)    ;extract first quoted
           set value=$piece(value,",",first,last)  ; pick the relevant pieces
          }
else  {  
       set value=content            ;  no quotes, no pieces
}