obtener tag xml desde vfox

704 views
Skip to first unread message

Jorge

unread,
Apr 5, 2018, 3:17:28 PM4/5/18
to publicesvfoxpro
Hola: 


Tengo este xml de respuesta donde obtengo datos a partir de un cuit que envie 
a un servicio web: 

<?xml version='1.0' encoding='ISO-8859-1'?><COMPROBANTE>
  <numeroComprobante>104564151</numeroComprobante>
  <fechaDesde>20180401</fechaDesde>
  <fechaHasta>20180430</fechaHasta>
  <cantidadContribuyentes>1</cantidadContribuyentes>
  <contribuyentes class="list">
    <contribuyente>
      <cuitContribuyente>30172240333</cuitContribuyente>
      <alicuotaPercepcion>2,50</alicuotaPercepcion>
      <alicuotaRetencion>1,25</alicuotaRetencion>
      <grupoPercepcion>7</grupoPercepcion>
      <grupoRetencion>8</grupoRetencion>
    </contribuyente>
  </contribuyentes>
</COMPROBANTE>
Lo unico que necesito saber es como obtener los valores de cada tag por codigo .
Ejemplo :  Los valores de los tags 
<grupoPercepcion>
      <grupoRetencion>
gracias 

Fidel Charny

unread,
Apr 5, 2018, 3:29:45 PM4/5/18
to Comunidad de Visual Foxpro en Español
lcGrupoPercepcion = STREXTRACT(m.lcString_xml,"<grupoPercepcion>","</grupoPercepcion>")

Fernando D. Bozzo

unread,
Apr 5, 2018, 5:47:07 PM4/5/18
to Comunidad de Visual Foxpro en Español
...y mejorando un poco más el código de Fidel y encapsulándolo:

? get_TAG_Value( "grupoPercepcion" )
7

? get_TAG_Value( "fechaDesde" )
20180401

? get_TAG_Value( "cuitContribuyente" )
30172240333


FUNCTION get_TAG_Value(tcString, tcName)
   * Pasar tcString por referencia y tcName por valor
   RETURN STREXTRACT( tcString, '<' + tcName + '>', '</' + tcName + '>' )
ENDFUNC

Fidel Charny

unread,
Apr 6, 2018, 7:35:52 AM4/6/18
to Comunidad de Visual Foxpro en Español
Hola Fernando!
Parece que en el despacho de la función falta el envío del valor o referencia del parámetro tcString.
Pero me interesa hacerte una pregunta: por qué "pasar tcString por referencia" ?

Yo uso una función similar a la que le agrego (opcional) como tercer parámetro, el tipo de valor esperado. Si se pasa ese parámetro tratará de devolver un valor tipo "C,N,L,D,T", si no se pasa el valor devuelto es tipo "C". Pero no paso el string por referencia.

Fernando D. Bozzo

unread,
Apr 6, 2018, 8:54:45 AM4/6/18
to Comunidad de Visual Foxpro en Español
Fidel, tenés razón, en el apuro puse los ejemplos incompletos.

Lo del string XML por referencia es una simple pero efectiva optimización, ya que pasando un XML de 1 MB por valor implica crear una variable en el destino (tcString) y copiarle el valor (1 MB de datos), en cambio al pasar el valor por referencia, solo implica crear la variable en el destino (tcString) y copiarle la referencia (dirección de memoria) del contenido original, que solo ocupa 4 bytes (contra el MB de ejemplo), por lo que el contenido se lee directamente desde el origen.

Una función que pasa datos por referencia tiene un tiempo de ejecución lineal --sin contar procesamiento--, porque siempre pasa 4 bytes por referencia, en cambio una función que pasa datos por valor tiene un tiempo de ejecución proporcional al tamaño del dato que intenta pasar, porque se tiene que copiar su contenido entero.


Corrijo el ejemplo:

lcString = "el contenido del XML"

? get_TAG_Value( @lcString, "grupoPercepcion" )
7

? get_TAG_Value(
@lcString,"fechaDesde" )
20180401

? get_TAG_Value(
@lcString,"cuitContribuyente" )
30172240333


FUNCTION get_TAG_Value(tcString, tcName)
   * Pasar tcString por referencia y tcName por valor
   RETURN STREXTRACT( tcString, "<" + tcName + ">", "</" + tcName + ">" )
ENDFUNC




Fidel Charny

unread,
Apr 6, 2018, 9:41:06 AM4/6/18
to Comunidad de Visual Foxpro en Español
Gracias Fernando, muy buena observación.
También demuestra que no he meditado detenidamente sobre algunas cuestiones...

Fidel Charny

unread,
Apr 6, 2018, 11:09:48 AM4/6/18
to Comunidad de Visual Foxpro en Español
Hola Fernando
Al utilizar el pase por referencia, los desprevenidos debemos tomar una precaución (te imaginás que ya hice algunas pruebas )
En este ejemplo, al enviar el parámetro tcString por referencia, me producía una modificación en el string despachado, agregándole CHR(13)+CHR(10), por efecto de las lineas que ahora están comentadas.
Ese código lo desplacé al momento de asignarle valor al elemento correspondiente del array, sin cambiar el valor de tcString.

*<Method>logs_add_string</Method>
LPARAMETERS tcProgram
,tcString

TRY
    LOCAL LOEX AS EXCEPTION
,;
        lnAscan
   
    IF VARTYPE
(m.tcString)="C" AND !EMPTY(m.tcString)
       
*!*            Produce error, porque agrega CR_LF si tcString se pasa por referencia
*!*            IF RIGHT(TRIM(m.tcString),2) # CHR(13)+CHR(10)
*!*                tcString = m.tcString ;
*!*                    + CHR(13)+CHR(10)
*!*            ENDIF

        lnAscan
= ASCAN(this.afile_logs,m.tcProgram,1,0,0,7)
        IF
!EMPTY(m.lnAscan)
           
this.afile_logs[m.lnAscan + 2] = this.afile_logs[m.lnAscan+2] ;
               
+ m.tcString ;
               
+ IIF(RIGHT(TRIM(m.tcString),2) == CHR(13)+CHR(10),"",CHR(13)+CHR(10))  && Reemplazo para no afectar el pase por referencia
        ENDIF
    ENDIF
   
CATCH TO LOEX
    LOEX
.USERVALUE = PROGRAM() + CHR(13);
       
+ "tcProgram="+m.tcProgram + CHR(13);
       
+ "tcString ="+m.tcString + CHR(13);
       
+ "lnAscan  ="+TRANSFORM(m.lnAscan)
       
    SHOWERROR
(LOEX)
    THROW
FINALLY

ENDTRY

Jean Pierre Adonis De La Cruz Garcia

unread,
Apr 6, 2018, 12:14:40 PM4/6/18
to Comunidad de Visual Foxpro en Español
Hace tiempo usaba este proceso en VFP, claro que ya no lo uso ya que prefiero trabajar todo en PHP, me es mas rapido y factible a mi parecer.
aca esta de donde usaba para leer los Tags de XML distintos.

Marco Plaza

unread,
Apr 6, 2018, 12:44:21 PM4/6/18
to Comunidad de Visual Foxpro en Español


Puedes convertir cualquier XML en un objeto usando simplemente la función nfXMLread:

o = nfXMLRead( tuXML ) 





Nota: tu XML tiene una lista ( contribuyentes ) que si deseas sea convertida a array debes indicar usando un segundo parámetro:

o = nf Xxmlread(_cliptext,'/comprobante/contribuyentes[]')

( mira la documentación en nfXML acerca de arrays en XML y como indicarlos cuando la lista tiene un sólo elemento )


Saludos.

Fernando D. Bozzo

unread,
Apr 6, 2018, 2:33:37 PM4/6/18
to Comunidad de Visual Foxpro en Español
Sí, por supuesto, al pasar por referencia hay que tener cuidado de no alterar el valor original, salvo que eso sea lo que se quiere realmente.

Rodolfo Ortiz González

unread,
Apr 9, 2018, 10:35:26 AM4/9/18
to publice...@googlegroups.com
Hola Marco.

Bajé el ejemplo que mencionas, pero me da error la función  nfXMLRead, en manda: Variable ESCAPECOUNT no existe.

Ya la inicié incluso como variable pública  y nada, por dónde le puedo buscar?



Saludos y gracias!

Marco Plaza

unread,
Apr 9, 2018, 12:26:10 PM4/9/18
to Comunidad de Visual Foxpro en Español

Hola descarga el archivo nfXML.h ( https://github.com/VFPX/nfXML/blob/master/nfXml/NFXML.H )  que tiene las definiciones y recompila la función

también puedes descargar todo de una sola vez usando el enlace:


Saludos.

Miguel A.

unread,
Apr 9, 2018, 1:27:34 PM4/9/18
to Comunidad de Visual Foxpro en Español
También puedes utilizar MSXML2.DOMdocument, aquí tienes un ejemplo.
Saludos,
Miguel A.

SET EXACT On
LOCAL xdoc AS MSXML2.DOMDocument
PUBLIC mmoda, mnume, mpais, mpubl, mdeno, mclas, mopos, mprod, mgraf, mvigi
mgraf=''
mclas=''
mdeno=''
mmoda=''
mnume=''
mtitu=''
mpais=''
mpubl={}
mopos={}
mprod=''
mvigi=''

*!* Creamos un objeto basado en MSXML
xdoc=CREATEOBJECT('MSXML2.DOMdocument')
*!* Cargamos el archivo XML a procesar
xdoc.LOAD(mifichero)
*!* Llamamos a la función LeerXML pasándole el nodo raíz
LeerXML(xdoc.documentElement.childNodes)
insert into vigilancia (modalidad, numero, solicitant, pais, publicacio, denominaci, clases, productos, oposicion, imagen, vigilancia);
 values (mmoda, mnume, mtitu, mpais, mpubl, mdeno, mclas, mprod, mopos, mgraf, mvigi)
SET EXACT Off
*****************

FUNCTION LeerXML
LPARAMETERS root AS MSXML2.IXMLDOMNode
LOCAL CHILD AS MSXML2.IXMLDOMNode

*!* Aqui se procesan los nodos del XML
FOR EACH CHILD IN root
DO CASE 
CASE CHILD.nodeName="CodModalidad"
mmoda=CHILD.Text
CASE CHILD.nodeName="Numero"
mnume=CHILD.Text
CASE CHILD.nodeName="CodPais"
mpais=CHILD.Text
CASE CHILD.nodeName="Denominacion"
mdeno=CHILD.Text
CASE CHILD.nodeName="Titulares"
mtitu=CHILD.Text
CASE CHILD.nodeName="Fecha_Fin_Oposicion"
IF YEAR(mopos)=0
mopos=CTOD(CHRTRAN(LEFT(CHILD.Text,10), "/", "-"))
ENDIF 
CASE CHILD.nodeName="Fecha_Publicacion"
IF YEAR(mpubl)=0
mpubl=CTOD(CHRTRAN(LEFT(CHILD.Text,10), "/", "-"))
ENDIF 
CASE CHILD.nodeName="Clases"
mclas=CHILD.Text
CASE CHILD.nodeName="Grafico"
mgraf=CHILD.Text
CASE CHILD.nodeName="Productos_Servicios"
mprod=CHILD.Text
CASE CHILD.nodeName="Datos_Vigilancia"
mvigi=UPPER(ALLTRIM(STRTRAN(CHILD.Text,'-M','')))
CASE ALLTRIM(CHILD.nodeName)="G10Boletines_Expedientes"
insert into vigilancia (modalidad, numero, solicitant, pais, publicacio, denominaci, clases, productos, oposicion, imagen, vigilancia);
values (mmoda, mnume, mtitu, mpais, mpubl, mdeno, mclas, mprod, mopos, mgraf, mvigi)
mgraf=''
mclas=''
mdeno=''
mmoda=''
mnume=''
mtitu=''
mpais=''
mpubl={}
mopos={}
mprod=''
mvigi=''
ENDCASE 
    IF CHILD.hasChildNodes
LeerXML(CHILD.childNodes)
    ENDIF
ENDFOR
SET EXACT OFF 
ENDFUNC

Rodolfo Ortiz González

unread,
Apr 9, 2018, 2:21:23 PM4/9/18
to publice...@googlegroups.com
Mil gracias Miguel.

El punto es que así lo hago pero con lo que puso Marco creo que tengo mayor control , no sé que pasó que ahorita que lo probé ya no me dio error.

Le voy a dar una buena vista para ver de que manera lo puedo usar en mis aplicaciones, de cualquier forma te agradezco la información, un saludo!





Rodribezul

unread,
Jul 17, 2018, 4:32:58 PM7/17/18
to Comunidad de Visual Foxpro en Español
Hola Marco mirando dicha librería me genera un objeto VFP..  Pero en el ejemplo me generar un error Xmltocursor(oAirports.String._nodetext_,'airports'), medice que desconoce string 

Marco Plaza

unread,
Jul 18, 2018, 1:24:30 AM7/18/18
to Comunidad de Visual Foxpro en Español

Hola, ciertamente, el servicio que usé para las pruebas ya no opera. Removí ese programa  y aproveché de simplificar los ejemplos 
dejando sólo uno que usa un archivo xml ya suministrado.

Saludos.
Reply all
Reply to author
Forward
0 new messages