Question
· Aug 4, 2021

Convert a %String property with CDATA and XML content to Ensemble object

Hello, first of all thanks for your time reading this question ◀️

We would need to achieve the following task:

We have a Ens.Response message with this structure:

<?xml version="1.0" ?>
<!-- type: Mensajes.Response.Justicia.PLATINO.EnviarIniciadoresGeneralResponse  id: 10986665 -->
<EnviarIniciadoresGeneralResponse>
    <EnviarIniciadoresGeneralOut>
        <![CDATA[<?xml version="1.0" encoding="ISO-8859-1"?>
<mensajeWS xmlns="https://wslexnet.webservices.lexnet/3.22"><respuestaEnvioMensaje xmlns=""><idEnvio>1947625809</idEnvio><tamBloque>524288</tamBloque><bytesMIME>TFgDBA...</bytesMIME></respuestaEnvioMensaje></mensajeWS>]]>
    </EnviarIniciadoresGeneralOut>
</EnviarIniciadoresGeneralResponse>

The content inside the CDATA represent a XML message:

<?xml version="1.0" encoding="ISO-8859-1"?>
<mensajeWS xmlns="https://wslexnet.webservices.lexnet/3.22">
    <respuestaEnvioMensaje xmlns="">
        <idEnvio>1947625809</idEnvio>
        <tamBloque>524288</tamBloque>
        <bytesMIME>TFgDBA...</bytesMIME>
    </respuestaEnvioMensaje>
</mensajeWS>

 

We wonder how could we convert the %String property EnviarIniciadoresGeneralOut to an Ensemble object

 

We have developed the code as follows:

 

Class Operaciones.XML.Justicia.TransformacionesJusticia Extends Ens.BusinessOperation [ ProcedureBlock ]
{

Parameter INVOCATION = "Queue";

// ClassMethod generarEnviarIniciadoresGeneralJusticia(pRequest As Mensajes.Response.Justicia.PLATINO.EnviarIniciadoresGeneralResponse, Output pResponse As EsquemasDatos.Justicia.respuestaEnvioMensajeType) As %Status

/// Lo creamos el 04 08 21 para convertir String a EsquemasDatos en XML
ClassMethod generarEnviarIniciadoresGeneralJusticia(pRequest As Mensajes.Response.Justicia.PLATINO.EnviarIniciadoresGeneralResponse, Output pResponse As Mensajes.Response.Justicia.PLATINO.EnviarIniciadoresGeneralEstructuradoResponse) As %Status
{
    $$$LOGINFO("Entra en: Operaciones.XML.Justicia.TransformacionesJusticia.generarEnviarIniciadoresGeneralJusticia: ")
    // WRITE ##class(Operaciones.XML.Justicia.TransformacionesJusticia).generarEnviarIniciadoresGeneralJusticia("<?xml version="1.0" encoding="ISO-8859-1"?><mensajeWS xmlns="https://wslexnet.webservices.lexnet/3.22">    <respuestaEnvioMensaje xmlns="">        <idEnvio>1187808872</idEnvio>        <tamBloque>524288</tamBloque>        <bytesMIME>TFgDBA</bytesMIME>    </respuestaEnvioMensaje></mensajeWS>")
    
    //INICIALIZO LA RESPUESTA
    set pResponse = ##class(Mensajes.Response.Justicia.PLATINO.EnviarIniciadoresGeneralEstructuradoResponse).%New()
    #dim tDocument as %XML.XPATH.Document
    #dim tResultList as %ListOfObjects
    
    $$$LOGINFO("pRequest.EnviarIniciadoresGeneralOut: "_pRequest.EnviarIniciadoresGeneralOut)

    try{    
     Set tSC=##class(%XML.XPATH.Document).CreateFromStream(pRequest.EnviarIniciadoresGeneralOut,.tDocument)
     If $$$ISERR(tSC) Do $System.OBJ.DisplayError(tSC)
     //set expresion="respuestaEnvioMensaje"
     //set expresion="text()"
     set expresion="*"
     set contexto="/mensajeWS"
     set tSC = tDocument.EvaluateExpression(contexto,expresion,.tResultList)
    set contador= tResultList.Count()
    
    /// ¿Por qué sale contrador = 0?
    $$$LOGINFO("contador es: "_contador)

    if (contador>0){
         for index=1:1:tResultList.Count() {
             set element = tResultList.GetAt(index)
        
             while (element.Read()){
                 
                 if ((element.Name = "idEnvio") && (element.NodeType = "element")){
                    //guardamos
                    do element.Read()
                    set pResponse.EnviarIniciadoresGeneralOut.idEnvio = element.Value
                    
                }
                 if ((element.Name = "tamBloque") && (element.NodeType = "element")){
                    //guardamos
                    do element.Read()
                    set pResponse.EnviarIniciadoresGeneralOut.tamBloque = element.Value
                    
                }
                 if ((element.Name = "bytesMIME") && (element.NodeType = "element")){
                    //guardamos
                    do element.Read()
                    set pResponse.EnviarIniciadoresGeneralOut.bytesMIME = element.Value
                    
                }                                                     
             }             
         }         
     }
    }
    catch
    {
        $$$LOGINFO($ECODE)
        $$$LOGINFO($ZERROR)
    }
     Quit $$$OK
}

}

 

We call it from a BPL as:

set tSC = ##class(Operaciones.XML.Justicia.TransformacionesJusticia).generarEnviarIniciadoresGeneralJusticia(context.enviarIniciadoresGeneralResponse, .respuesta)

 

However with the $$$LOGINFO, we observe: "contador es: 0"

Which means we are not collecting the contents inside the following XML Path: /mensajeWS/respuestaEnvioMensaje

 

We have tried with the 3 following ways:

     //set expresion="respuestaEnvioMensaje"
     //set expresion="text()"
     set expresion="*"

In all cases it shows:

     contador es: 0

Which means tResultList is empty and we do not iterate inside our for and while

 

➡️ How would you recommend us to convert a string with XML content to an Ensemble object💭

Thanks for your replies

 

We have read:

https://community.intersystems.com/post/string-xml

https://community.intersystems.com/post/how-get-value-xmltext-reader

https://community.intersystems.com/post/read-attribute-xdata-block

https://community.intersystems.com/post/how-return-xmlxpathdomresult-string

https://community.intersystems.com/post/get-xml-subtree-xpath-dom-result...

https://community.intersystems.com/post/replace-element-value-xmlxpathdo...

 

Thanks for your help  🙏

➡️➡️ How would you recommend us to convert a string with XML content to an Ensemble object? 💭

$ZV: Cache for UNIX (Red Hat Enterprise Linux for x86-64) 2017.2.1 (Build 801_3_18358U) Tue Jul 24 2018 16:36:10 EDT
Discussion (2)1
Log in or sign up to continue

First you need to create corresponding classed. You can do that by either importing the XSD or manually.

Here's a manual approach:

Class test.mensajeWS Extends (%RegisteredObject, %XML.Adaptor) {

Parameter NAMESPACE = "https://wslexnet.webservices.lexnet/3.22";

Property respuestaEnvioMensaje As respuestaEnvioMensaje;
}


Class test.respuestaEnvioMensaje Extends (%RegisteredObject, %XML.Adaptor) {

Property idEnvio As %Integer;

Property tamBloque As %Integer;

Property bytesMIME As %VarString;
}

After that in your BS convert incoming XML string like this:

set reader = ##class(%XML.Reader).%New()
set sc = reader.OpenString(pRequest.EnviarIniciadoresGeneralOut)
quit:$$$ISERR(sc) sc

do reader.Correlate("mensajeWS","test.mensajeWS")

do reader.Next(.mensajeWSObj,.sc)
quit:$$$ISERR(sc) sc

// Process mensajeWSObj