1. Julian I.
  2. PowerBuilder
  3. Tuesday, 14 February 2023 08:38 AM UTC

Hi,

I have this question:

We are calling to a web service than returns a response with this format:



   
       
            <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:getBookmarkListsResponse xmlns:ns2="http://www.globalgap.org/">
    <responseheader>
        <generated>2019-11-21T15:45:07.251+01:00</generated>
        <resultstate>ok</resultstate>
    </responseheader>
    <bookmarkListList>
        <bookmarkList>
            <listId>121875</listId>
            <listName>GLOBALG.A.P. API Bookmarking List</listName>
            <listDescription>Testing the functionality of the SOAP API</listDescription>
            <editor>
                <companyName>Eurepgap</companyName>
                <companyOkey>OKEY-3bnxg-y9q0-h7l7</companyOkey>
            </editor>
            <follower>
                <companyName>Eurepgap</companyName>
                <companyOkey>OKEY-3bnxg-y9q0-h7l7</companyOkey>
            </follower>
        </bookmarkList>
    </bookmarkListList>
</ns2:getBookmarkListsResponse>

       
   

We save the reponse on a file and then we try to load it into a PBDOM using PBDOM_BUILDER.BuildFromFile(FILE), but for large files, the costs is elevated. (I think it could be because of the html format < ... >):

lpbdom_Builder = CREATE PBDOM_BUILDER
    
    TRY
        
        // Generamos el Documento a partir únicamente del XML de la Respuesta
        lpbdom_Doc = lpbdom_Builder.BuildFromFile(ls_fichero_xml)
       
    CATCH (PBDOM_Exception lpbdom_Except)
        ls_error_xml = "PBDOM_Exception : " + string(lpbdom_Except.GetExceptionCode())
        RETURN -1
    END TRY
    
    DESTROY(lpbdom_Builder)

 So, we found another solution:

/*************************************************************************************
* Funcion        : of_build_pbdom_respuesta
*
* Descripción    : Contruye el árbol DOM con la respuesta del servicio HYYP a partir
*                      del XML contenido en el fichero indicado.
*                      
*                      Creamos esta función para la carga puesto que la nativa de PB
*                      BuildFromFile, tardaba mucho tiempo en cargar el fichero, entiendo
*                      debido a que el XML de respuesta estaba en formato HTML con
*                      < en vez de < y > en vez de >
*                      
*                      
* Argumentos    : - as_ruta_fichero_xml: La ruta completa del fichero XML a carga
*                         - apbdom_doc (REF): El árbol DOM construido a partir del XML
*                      - as_xml_msj_error: Texto del error, si se produce.
*                        
* Devuelve        : 1 OK, -1 ERROR
*
* Evento            : AG6794
*
**************************************************************************************
*        Fecha               Autor       Comentarios
*    --------------        ----------        --------------------------------------------------
*    13/02/2023             JIR            Versión Inicial    
*************************************************************************************/
string        ls_xml
long            ll_ret

OleObject         lole_dom
PBDOM_BUILDER    lpbdom_Builder
PBDOM_DOCUMENT lpbdom_Doc

TRY
    
    // Cargamos el Fichero, sin utilizar la función nativa BuildFromFile porque tardaba mucho tiempo en crear el arbol.
    lole_dom = Create oleobject
    lole_dom.ConnectToNewObject ("Msxml2.DOMDocument")
    lole_dom.Load(as_ruta_fichero_xml)
    
    /* Obtenemos del Documento el XML de la Respuesta

                                childNodes.Item(1).
                                        childNodes.Item(0).
                            childNodes.Item(0).
                                            childNodes.Item(0).
                        ...
                        Texto XML RESPUESTA        childNodes.Item(0).nodevalue
                        ...
    */        
    
    ls_xml = string(lole_dom.childNodes.Item(1).childNodes.Item(0).childNodes.Item(0).childNodes.Item(0).childNodes.Item(0).nodevalue)
    
CATCH (OLERuntimeError oleError)
    as_xml_msj_error = "RUNTIME_ERROR : No se pudo cargar la respuesta del fichero XML" + CR + string(oleError.Description)

    RETURN -1
END TRY

lpbdom_Builder = CREATE PBDOM_BUILDER

TRY
    // Generamos el Documento a partir únicamente del XML de la Respuesta
    lpbdom_Doc = lpbdom_Builder.BuildFromString(ls_xml)
    
CATCH (PBDOM_Exception lpbdom_Except)
    as_xml_msj_error = "PBDOM_Exception : " + string(lpbdom_Except.GetExceptionCode())
    RETURN -1
END TRY

apbdom_doc = lpbdom_Doc

DESTROY(lpbdom_Builder)
    
return 1

The question is: Were we doing something wrong with BuildFromFile? or it is a problem of this function?
24 seconds vs 0 seconds on load example attached file.

 

Regards,

Julian

Attachments (1)
Who is viewing this page
Andreas Mykonios Accepted Answer Pending Moderation
  1. Tuesday, 14 February 2023 10:22 AM UTC
  2. PowerBuilder
  3. # 1

By the way, if you are using PB 2019 R3 or later you could do this replacement using .net.

Here is an example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.IO;

namespace FixXMLClass
{
    public class FixXML
    {
        public static string loadAndFixXML(string xmlFile)
        {
            string xmlStr;
            
            if (!File.Exists(xmlFile))
            {
                return "";
            }
            
            StreamReader myReader = new StreamReader(xmlFile);
            
            xmlStr = myReader.ReadToEnd();
            myReader.Close();
            myReader.Dispose();
            
            xmlStr = fixXML(xmlStr);
            
            StreamWriter myWriter = new StreamWriter(xmlFile.ToLower().Replace(".xml", "_new.xml"), false);
            
            myWriter.Write(xmlStr);
            
            myWriter.Close();
            myWriter.Dispose();
            
            return xmlFile.ToLower().Replace(".xml", "_new.xml");
        }
        
        public static string fixXML(string xml2fix)
        {
            string fixedXML = "";
            
            fixedXML = xml2fix.Replace("&lt;", "<");
            fixedXML = fixedXML.Replace("&gt;", ">");
            fixedXML = fixedXML.Replace("&quot;", "\"");
            
            return fixedXML;
        }
    }
}

There are two methods (static).

  • fixXML: Takes a string & replaces string causing the issue. It will returned fixed xml in a string.
  • loadAndFixXML: Takes a file, reads its content, fix it using fixXML and finally creates a file like "<original_filename>_new.xml"

You could run those functions using .NET DLL Importer.

This will run very fast. After that buildfromfile will also run very fast.

Also, you don't really need to save the xml to the disk. You can directly build PBDOM using buildfromstring.

Andreas.

Comment
  1. Julian I.
  2. Tuesday, 14 February 2023 11:02 AM UTC
Hi Andreas !,



I tried to replace it by using Replace PB function after reading the file but for large files, the replace cost was high too. I will keep this solution in mind.

I need a copy of the XML file, because the information it contains is temporary and if the process fails I need to be able to relaunch it.



Thank for all !

Regards,

Julian
  1. Helpful
  1. Andreas Mykonios
  2. Tuesday, 14 February 2023 11:07 AM UTC
Replace pb function is too slow...

You will have to use something faster. C# example I sent you creates correct xml for the xml you attached in less than a second.

Andreas.
  1. Helpful 2
  1. Julian I.
  2. Tuesday, 14 February 2023 17:50 PM UTC
The solution we have implemented using "Msxml2.DOMDocument" has a low cost too, I think internally is doing somethig that you explains. I don't know if BuildFromFile function has been reviewed on new PB versions
  1. Helpful
There are no comments made yet.
Andreas Mykonios Accepted Answer Pending Moderation
  1. Tuesday, 14 February 2023 10:07 AM UTC
  2. PowerBuilder
  3. # 2

Hi.

You are not doing something wrong. The delay is because xml has &lt;, &gt; and &quot;...

If you replace:

  • &lt; to <
  • &gt; to >
  • &quot; to "

you will find it will load super fast.

I guess PBDOM is trying to do that replace but I can't be sure. Such a replace in a big file can have big time cost.

Andreas.

Comment
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.