Page 1 of 2

Leer nodo xml MSXML2.DomDocument

Posted: Thu Apr 07, 2022 2:00 pm
by jparada
Estoy intentando leer nodos de un xml (factura electrónica México), lo estoy intentando con DocumentoXML := Win_oleCreateObject( "MSXML2.DomDocument" )

pero no sé cómo manejar los namespace, he buscado ejemplos con vba pero no logro encontrar mucha información, alguna sugerencia?.

Saludos,
Javier

Re: Leer nodo xml MSXML2.DomDocument

Posted: Thu Apr 07, 2022 4:55 pm
by martingz
desarrolle un lector de xml de nominas, si te sirve te lo envio


saludos

Re: Leer nodo xml MSXML2.DomDocument

Posted: Thu Apr 07, 2022 6:49 pm
by jparada
Gracias Martín, creo que lo solucioné, eso sí, sin utilizar namespace en la declaración, porque no he sabido cómo implementar esa parte, tu visor incluye los namespace?, lo programaste con MSXML2.DomDocument o con alguna lib?.

Saludos,
Javier

Re: Leer nodo xml MSXML2.DomDocument

Posted: Fri Apr 08, 2022 12:08 am
by martingz
Utilizo la lib hbxml, me lee el xml completo de la nomina y con esta informacion genero los pdf's de la misma,



saludos

Re: Leer nodo xml MSXML2.DomDocument

Posted: Sat Apr 09, 2022 4:47 pm
by andyglezl
Hola Javier
EDK puso un excelente ejemplo general, tal vez te sirva.
*-----------------------------------------------------------------------------
Hello
EDK put an excellent general example, maybe it will help you.


https://hmgforum.com/viewtopic.php?f=5& ... edk#p67951

Re: Leer nodo xml MSXML2.DomDocument

Posted: Thu Apr 14, 2022 5:19 pm
by IMATECH

Re: Leer nodo xml MSXML2.DomDocument

Posted: Wed Jul 06, 2022 9:16 pm
by jparada
Regreso con este tema porque para un proceso requiero leer muchos archivos xml, el tema es el siguiente:

con COM MSXML2.DomDocument tarda en leer poco más de 8000 archivos 1hora 20minutos aproximado, esto es parte del código:

Code: Select all

  oCFDI := Win_OleCreateObject( "MSXML2.DomDocument" )
  
  FOR EACH archivo IN hb_vfDirectory( rutaBase + "*.xml" )
    i++
       
    IF hb_vfExists( archivoXML := rutaBase + archivo[ F_NAME ] )         
      oCFDI:Load( archivoXML )

      ? "Procesando archivo: " + archivoXML + "  " + hb_NtoS(i) + " de " + hb_NtoS( Len( hb_vfDirectory( rutaBase + "*.xml" ) ) )
   
      olNode := oCFDI:selectSingleNode("//cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital")
      IF hb_IsNil( olNode )
        ? hb_Utf8ToStr( "No se encontro el nodo TimbreFiscalDigital" )
      ELSE
        cUUID := olNode:getAttribute("UUID")

        hb_fNameSplit( archivoXML, NIL, @cName, @cExt )
        cXML  := cName + cExt        
      
        cQry := "INSERT INTO ArchivosXML (Archivo, UUID) " + ;
                "VALUES (" + ;                 
                convertToSQL( cXML ) + ", " + ;
                convertToSQL( cUUID ) + " )"

        BEGIN SEQUENCE WITH {|oError| BREAK( oError ) }
          oConnection:Execute( cQry )
        RECOVER USING oError
          ? "Error al actualizar datos en la tabla" +  E"\n" + oError:Description
          RETURN NIL
        END SEQUENCE

      ENDIF
        
    ENDIF
  
  NEXT  
Después de leer algunos artículos que mencionan que hay algunos problemas en el uso de memoria con createobject, pasé a la segunda opción que es utilizar la lib miniXML

Perooo para mi sorpresa utiliza más tiempo en leer la misma cantidad de archivos, el tiempo de lectura es de 2horas 20minutos :o, este es parte del código utilizando miniXML:

Code: Select all

FOR EACH cFile IN aDir
      IF hb_fileExists( cFileName := cPath + cFile[ F_NAME ]  )
        ? "Procesando archivo: " + cFileName + "  " + hb_NtoS( nFile ) + " de " + hb_NtoS( nLenDir )
    
        xmlBuffer := hb_memoRead( cFileName )
        body := mxmlLoadString( NIL, xmlBuffer, MXML_OPAQUE_CALLBACK )
    
        IF Empty( hTimbreFiscal := mxmlFindElement( body, body, "tfd:TimbreFiscalDigital",,, MXML_DESCEND ) )
          ? "Unable to find <tfd:TimbreFiscalDigital> elment in XML!" + hb_eol()        
          crearLogArchivo( cArchivoLog, "Archivo XML sin complemento! " + cFileName + hb_Eol(), @lNuevo )

          mxmlDelete( body )
        ELSE
          mxmlGetElement( hTimbreFiscal )
          cUUID := mxmlElementGetAttr( hTimbreFiscal, "UUID" )

          IF hb_IsNIl( cUUID )
            mxmlDelete( body )
            ? "No existe el atributo UUID!!!" + hb_eol()
          ELSE
            ? "UUID: " + cUUID
            ?
            hb_fNameSplit( cFileName, NIL, @cName, @cExt )
            cXMLFile  := cName + cExt

            cQry := "INSERT INTO ArchivosXML (Archivo, UUID) " + ;
                    "VALUES (" + ;
                    convertToSQL( cXMLFile ) + ", " + ;
                    convertToSQL( cUUID ) + " )"

            BEGIN SEQUENCE WITH {|oError| BREAK( oError ) }
              oConn:Execute( cQry )
            RECOVER USING oError
              ? "Error al actualizar datos en la tabla" + E"\n" + oError:Description
              RETURN NIL
            END SEQUENCE

            mxmlDelete( body )
          ENDIF
        ENDIF
  
      ENDIF   
  
      ++nFile
NEXT
Así que no como no estoy conforme con los resultados obtenidos, realicé un pequeño programa en el lenguaje C# y mi SORPRESA es que con la misma cantidad de archivos tarda el proceso SÓLO 20 segundos :o :o :o ... y la locura es que corrí el proceso para que leyera más de 150mil archivos y SÓLO tardó 5 minutos.

Así que tengo algunas preguntas:
- En los fragmentos de códigos de mis soluciones con Harbour, hay forma de refactorizar para obtener mejores resultados.
- Es justo comparar la velocidad de los procesos entre los lenguajes Harbour y C#.

Agradezco sus comentarios.

Saludos,
Javier

Re: Leer nodo xml MSXML2.DomDocument

Posted: Mon Jul 18, 2022 3:17 pm
by jparada
martingz wrote: Fri Apr 08, 2022 12:08 am Utilizo la lib hbxml, me lee el xml completo de la nomina y con esta informacion genero los pdf's de la misma,
Hola Martín, puedes compartir el código que utilizas para generar el pdf en base a la lectura del xml.

Saludos,
Javier

Re: Leer nodo xml MSXML2.DomDocument

Posted: Mon Jul 18, 2022 7:58 pm
by martingz
Javier comparto el codigo, espero que te sea de utilidad


https://mega.nz/file/FoRG1IaY#sy6an4Sow ... hIFCk_G_nM


saludos
p.d. quedo pendiente ante cualquier comentario

Re: Leer nodo xml MSXML2.DomDocument

Posted: Tue Jul 19, 2022 1:37 am
by jparada
Te agradezco Martín, he editado tu programa simplemente para correrlo, pero en mi caso ni siquiera encuentra el nodo comprobante

Code: Select all

archiv:= "C:\LeerNominaXML\nomina.xml"
hFile:=FOpen(archiv)
nvoarch:=hb_memoread(archiv)
oDocXML := TXmlDocument():New( nvoarch, HBXML_STYLE_NOESCAPE )
	
nHandle := FCREATE(archiv)
oNodo := oDocXML:FindFirst( "cfdi:Comprobante" )
tipocfd:="cfdi:"			
if oNodo == NIL
  ? "Error: el tipo de XML no es CFDI"
  return
endif
Alguna idea por qué?, es un xml nómina timbrado esta quincena.

Saludos,
Javier