sábado, 26 de marzo de 2016

HbFormat. Formateador de código para Harbour


Acabo de descubrir una herramienta que trae Harbour, que creo que debería ser de uso obligatorio,
sobretodo a ese código 'antiguo' procedente de Clipper.

Lo tienes localizado en /contrib/hbformat/utils
Para construirlo simplemente  hbmk2 hbformat.hbp

Una vez construido, tenéis junto al ejecutable un fichero , hbformat.ini, el que indica como
queremos convertir nuestro código.

Funcionamiento ;
hbformat test.prg

O, si queremos procesar todos los ficheros , hbformat "*.prg" muy importante las comillas,
de lo contrario, solo procesará el primero.

Después , usamos hbmk2 -fixcase *.prg  y eso es todo.








martes, 22 de marzo de 2016

Convertir XML a Hash en Harbour ( Update III )


Durante estos días, he estado trabajando con diversos XML , con formatos distintos, y he tenido que adaptar la funcion NodeToHash(), que corrige 2 incidencias graves;

La primera, se debía a que los atributos eran sobreescritos , no creando nuevos.
Ejemplo;
<test tipo="1">
<test tipo="2">

Esto ocasionaba que el tipo con  "1" no estaba disponible.

La segunda, es un error de la funcion mxmlWalkNext( node, node, MXML_DESCEND ) 
Esta función , ante un elemento del tipo <tag> </tag> , es decir, un nodo tag con un valor de espacios
en blanco, ocasiona que devuelve que tiene un nodo, siendo esto incorrecto.

La solución parcial, es que si el nodo hijo devuelve un hash vacío , no se va a tener en cuenta a la hora de crear un array de hash.

He decir que esta poniendose a prueba con cientos de miles de peticiones, y la verdad es que va
fino, fino ;-)

STATIC FUNCTION NodeToHash( node  )
   Local hNext
   Local hHashChild := {=>}
   Local hHash := {=>}

   WHILE node != NIL
         
         IF mxmlGetType( node ) == MXML_ELEMENT

            if HB_HHASKEY( hHash, mxmlGetElement( node ) )
               if valtype( hHash[ mxmlGetElement( node ) ] ) <> "A"
                  hHash[ mxmlGetElement( node ) ] := mxmlGetOpaque( node )
               else
                 // Es un array, por lo tanto, no lo tocamos
               endif  
            else                  
               hHash[ mxmlGetElement( node ) ] :=  mxmlGetOpaque( node )
            endif  

            if empty( mxmlGetOpaque( node ) ) // Miramos dentro
               hNext := mxmlWalkNext( node, node, MXML_DESCEND )  
               if hNext != NIL
                  hHashChild :=  NodeToHash( hNext  )
        
                  // Correcion de Posible bug. Un elemento con espacios en blanco, deja descender un nivel!, cuando no debería!
                  // example  <element> </element>
                  if hHashChild != NIL .and. !empty( hHashChild )
                     if empty( hHash[ mxmlGetElement( node ) ] )
                        hHash[ mxmlGetElement( node ) ] := {}
                     endif  

                     if HB_MXMLGETATTRSCOUNT( node ) > 0
                        hHashChild[ mxmlGetElement( node ) + "@attr"] := HB_MXMLGETATTRS( node )
                      endif  
                      AADD( hHash[ mxmlGetElement( node ) ], hHashChild )
                  endif  

               endif  
            else  
               if HB_MXMLGETATTRSCOUNT( node ) > 0
                  hHash[ mxmlGetElement( node ) + "@attr"] := HB_MXMLGETATTRS( node )
               endif  
            endif
         ENDIF   

         node := mxmlGetNextSibling( node )
                    
   END WHILE

return hHash



GTXSII. Visual Basic .NET

Estamos trabajando muy duro en intentar en soportar más lenguajes de programación para nuestra librería GtxSII, para el Suministro Inmedi...