Written by

Question Yone Moreno · Mar 12, 2024

Best way to translate a XML String to an Ens.Response derived class?

Hello,
First of all thanks for your time and help with this question.

We wonder how could we convert a String which represents an XML, to a class which extends from Ens.Response

Our context is a REST Operation, where we currently split the String with $PIECE and set each propertie as follows:

set codigo = $PIECE($PIECE(httpResponse,"<error><codigo>",2),"</codigo><descripcion>",1)
        set descripcion = $PIECE($PIECE(httpResponse,"<descripcion>",2),"</descripcion>",1)
        set codigoSERAM = $PIECE($PIECE(httpResponse,"</error><codigo>",2),"</codigo></resultado>",1)
        
        set pResponse = ##class(Mensajes.Response.Radiologia.NumeroOrdenAcodigoSERAMResponse).%New()
        set pResponse.resultado =  ##class(EsquemasDatos.Radiologia.Resultado).%New()
        set pResponse.resultado.error =  ##class(EsquemasDatos.Seguridad.Error).%New()
        set pResponse.resultado.error.codigo = codigo
        set pResponse.resultado.error.descripcion = descripcion
        set pResponse.resultado.codigo = codigoSERAM


Is there any recommended way to convert the XML String which has the following look:

<resultado><error><codigo>0</codigo><descripcion>Proceso realizado correctamente</descripcion></error><codigo>06050301</codigo></resultado>


    
To the Ens.Response derived class which structure is:

Class Mensajes.Response.Radiologia.NumeroOrdenAcodigoSERAMResponse Extends Ens.Response
{

Property resultado As EsquemasDatos.Radiologia.Resultado;
Class EsquemasDatos.Radiologia.Resultado Extends (%SerialObject, %XML.Adaptor) [ ProcedureBlock ]
{

Property error As EsquemasDatos.Seguridad.Error;Property codigo As%String(MAXLEN = "");
Class EsquemasDatos.Seguridad.Error Extends (%Persistent, %XML.Adaptor, %JSON.Adaptor) [ ClassType = persistent, ProcedureBlock ]
{

Property codigo As%Numeric;Property descripcion As%String(MAXLEN = "");

I

f the String written in the response would be a JSON we could do:

set tSC= claseAux.%ConvertJSONToObject(httpRequest.HttpResponse.Data,"Mensajes.Response.Radiologia.NumeroOrdenAcodigoSERAMResponse",.pResponse,1)    


Or we could use something like:

##class(%JSON.Adaptor).%JSONImport(input, %mappingNameAs%String = "")


    

But what is the recommended way to parse XML String to Ens.Response?

Thanks for your time, help and support.

Thank you.

Product version: IRIS 2020.1

Comments

Yone Moreno  Mar 13, 2024 to Lucas Cristofolini

Thanks @Lucas.Cristofolinibecause it looks helpful.

However I do not know how is related the code which shows Gevorg, and the need to convert a XML string to a Ensemble Class.

Thanks for your time and help @Lucas.Cristofolini.

0
Enrico Parisi · Mar 13, 2024

To export a XML enabled class use %XML.Writer class.

ClassMethod test()
{
	Set message=##class(Mensajes.Response.Radiologia.NumeroOrdenAcodigoSERAMResponse).%New()
	Set message.resultado.codigo="06050301"Set message.resultado.error=##class(EsquemasDatos.Seguridad.Error).%New()
	Set message.resultado.error.codigo=0Set message.resultado.error.descripcion="Proceso realizado correctamente"Set writer=##class(%XML.Writer).%New()
	Set writer.Indent=1Set sc=writer.OutputToString()
	; handle sc error hereSet sc=writer.RootObject(message.resultado)
	; handle sc error hereSet string=writer.GetXMLString()
	Write string,!
	Quit$$$OK
}

In your EsquemasDatos.Radiologia.Resultado class add XMLNAME parameter to obtain the correct (lowercase) tag name:

Class EsquemasDatos.Radiologia.Resultado Extends (%SerialObject, %XML.Adaptor)
{

Parameter XMLNAME = "resultado";Property error As EsquemasDatos.Seguridad.Error;Property codigo As%String(MAXLEN = "");

Result:

Do ##class(Mensajes.Response.Radiologia.NumeroOrdenAcodigoSERAMResponse).test()
<resultado>
  <error>
    <codigo>0</codigo>
    <descripcion>Proceso realizado correctamente</descripcion>
  </error>
  <codigo>06050301</codigo>
</resultado>
0
Enrico Parisi · Mar 13, 2024

OK, you asked XML string to object 😊

ClassMethod test()
{
	Set message=##class(Mensajes.Response.Radiologia.NumeroOrdenAcodigoSERAMResponse).%New()
	Set message.resultado.codigo="06050301"Set message.resultado.error=##class(EsquemasDatos.Seguridad.Error).%New()
	Set message.resultado.error.codigo=0Set message.resultado.error.descripcion="Proceso realizado correctamente"Set writer=##class(%XML.Writer).%New()
	Set writer.Indent=1Set sc=writer.OutputToString()
	; handle sc error hereSet sc=writer.RootObject(message.resultado)
	; handle sc error hereSet string=writer.GetXMLString()
	Write string,!
	
	; convert XML string back to objectSet reader = ##class(%XML.Reader).%New()
    Set sc=reader.OpenString(string)
    ; handle sc error hereDo reader.Correlate("resultado","EsquemasDatos.Radiologia.Resultado")
    Do reader.Next(.ReturnObject,.sc)
    ; handle sc error hereWrite"ReturnObject is of type ",ReturnObject.%ClassName(1),!
    do ReturnObject.XMLExport(,",indent")
	
	Quit
}

Result:

Do ##class(Mensajes.Response.Radiologia.NumeroOrdenAcodigoSERAMResponse).test()
<resultado>
  <error>
    <codigo>0</codigo>
    <descripcion>Proceso realizado correctamente</descripcion>
  </error>
  <codigo>06050301</codigo>
</resultado>
 
ReturnObject is of type EsquemasDatos.Radiologia.Resultado
<resultado>
  <error>
    <codigo>0</codigo>
    <descripcion>Proceso realizado correctamente</descripcion>
  </error>
  <codigo>06050301</codigo>
</resultado>
0
Enrico Parisi · Mar 13, 2024

In fact, for simple XML export (no namespace and other amenities) you can just use XMLExport*() methods.

ClassMethod test()
{
	Set message=##class(Mensajes.Response.Radiologia.NumeroOrdenAcodigoSERAMResponse).%New()
	Set message.resultado.codigo="06050301"Set message.resultado.error=##class(EsquemasDatos.Seguridad.Error).%New()
	Set message.resultado.error.codigo=0Set message.resultado.error.descripcion="Proceso realizado correctamente"Set sc=message.resultado.XMLExportToString(.string)
    ; handle sc error hereWrite string,!!
	
	; convert XML string back to objectSet reader = ##class(%XML.Reader).%New()
    Set sc=reader.OpenString(string)
    ; handle sc error hereDo reader.Correlate("resultado","EsquemasDatos.Radiologia.Resultado")
    Do reader.Next(.ReturnObject,.sc)
    ; handle sc error hereWrite"ReturnObject is of type ",ReturnObject.%ClassName(1),!
    do ReturnObject.XMLExport(,",indent")
	
	Quit
}

Result:

Do ##class(Mensajes.Response.Radiologia.NumeroOrdenAcodigoSERAMResponse).test()
<resultado><error><codigo>0</codigo><descripcion>Proceso realizado correctamente</descripcion></error><codigo>06050301</codigo></resultado>
 
ReturnObject is of type EsquemasDatos.Radiologia.Resultado
<resultado>
  <error>
    <codigo>0</codigo>
    <descripcion>Proceso realizado correctamente</descripcion>
  </error>
  <codigo>06050301</codigo>
</resultado>
0