Question
· Feb 18, 2020

How could we write ✍️ XML from a Response Message?

Hello,

We would like to get the XML which is being given by the requested system, directly to our Service output.

We have tried to just output directly the Message Response as follows:

Method findCandidatesXML(mensEntrada As %XML.GlobalCharacterStream(CONTENT="MIXED")) As Mensajes.Response.GestionPacientes.operacionResponse(XMLNAME="mensSalida") [ Final, ProcedureBlock = 1, SoapAction = "http://SCS.Servicios/GestionPacientes/findCandidatesXML", SoapBindingStyle = document, SoapBodyUse = literal, WebMethod ]
{
    set ^tipoMensaje="XML"
    $$$LOGINFO("El mensaje es de tipo: "_^tipoMensaje)
    
    
    #dim tSC as %Status
    if ('..IsServiceEnabled()){
        set tSC = $SYSTEM.Status.Error(60333,"Web Service Not Enabled")
        if $$$ISERR(tSC) do ..ReturnMethodStatusFault(tSC)
    }
    //----
    set p = ##class(%GlobalCharacterStream).%New()
    
    while (mensEntrada.AtEnd=0){
        //do p.Write(mensEntrada.Read())
        do p.Write($zcvt(mensEntrada.Read(),"O","UTF8"))
    }
    
    $$$LOGINFO("El mensaje en XML: "_p.Read())
    do p.Rewind()
    
    
    
    
    
    
    set msgER7 = ##class(EnsLib.HL7.Message).%New()
    set msgER7 = ##class(ITB.HL7.Util.Convert).XMLToER7(p,.tSC,"2.5")
    $$$LOGINFO(tSC)
    //Establece DocType
    if (msgER7.GetValueAt("1:9.3") '= "") {
        do msgER7.DocTypeSet("2.5"_":"_msgER7.GetValueAt("1:9.3"))

    } else {
        set tipo = msgER7.GetValueAt("1:9.1")
        set evento = msgER7.GetValueAt("1:9.2")
        do msgER7.DocTypeSet("2.5"_":"_tipo_"_"_evento)

    }

    set pPesponse = ##Class(Mensajes.Response.GestionPacientes.operacionResponse).%New()
    
    
    
    //proceso el mensaje
    set tSC = ..SendRequestSync("EnrutadorConsultaPaciente",msgER7, .pPesponse)
    //set tSC = ..SendRequestAsync("EnrutadorConsultaPaciente",p, .pPesponse)
    
    if $$$ISERR(tSC){ $$$TRACE("Error en la llamada al destino"_$system.Status.GetErrorText(tSC))}


    
    Quit pPesponse
}

 

So then we see in the SoapUI the correct output:

 

However this way is not correct because of when we try to get the WSDL definition, it outputs "There has been an error with the CSP application and it has been registered"

 

Besides we have tried to use the XML Writer. We have added in the Service:

 

$$$LOGINFO("In the service before calling Write: ")
set stream = ##class(%GlobalCharacterStream).%New()
set status = ##class(Mensajes.Response.GestionPacientes.operacionResponse).Write(.stream)
$$$LOGINFO("In the service after calling Write, status: "_status)
$$$LOGINFO("In the service after calling Write, stream "_stream)
set linea=""
while(stream.AtEnd=0){
set linea=stream.Read()
}
$$$LOGINFO("linea: "_linea)
Quit linea

 

Being the Write method the following:

ClassMethod Write(Output stream) As %Status
{
$$$LOGINFO("Write before create Writer")
set writer=##class(%XML.Writer).%New()
set writer.Indent=1
$$$LOGINFO("Write after create Writer") $$$LOGINFO("Write before outputtostream: ")
set stream = ##class(%GlobalCharacterStream).%New()
$$$LOGINFO("Before OutputToStream, stream: "_stream)
set status=writer.OutputToStream(stream)
$$$LOGINFO("stream: "_stream)
while(stream.AtEnd=0){
set linea=stream.Read()
}
$$$LOGINFO("linea: "_linea)
do stream.Rewind()     if $$$ISERR(status) {
        do $System.Status.DisplayError(status)
        quit $$$ERROR($$$GeneralError, "Output destination not valid")
    }
    $$$LOGINFO("Write after outputtostream, status: "_status)         
    quit status
}
 

As a result we get a stream, and when we try to read it, it shows as empty in the trace, both in the class Mensajes (Message)... and in the class Servicio (Service)

 

 

The previous result surprises us because of status being output from Write method inside Message class is 1, $$$OK:

 

How could we write XML from a Response Message?

 

We have also read 📗:

https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls...

https://docs.intersystems.com/irislatest/csp/documatic/%25CSP.Documatic....

https://cedocs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cl...

https://cedocs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cl...

https://cedocs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cl...

https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls...

Discussion (2)2
Log in or sign up to continue

Yone,

I think there's a problem with your Write() method. It is outputting data from the "stream" object, but "stream" is always set to a new (empty) stream and populated with data from "writer", which is also a new (empty) %XML.Writer object. So I don't see how this method could ever output any data.

Regarding the CSP error when requesting the WSDL, have you checked the application log to see what the actual error is?

-Marc

Yes Marc, you are right.

We have used the following code in the service:

set writer=##class(%XML.Writer).%New()
set status=writer.OutputToString()
If $$$ISERR(status)

Do $system.OBJ.DisplayError(status)
set status=writer.RootObject(pPesponse)
If $$$ISERR(status) Do $system.OBJ.DisplayError(status)

set response = writer.GetXMLString()

Quit response

Where we create a new empty XML writer, the we request the string, from the object's start, and finally we get it.