Cómo Trabajar con Archivos .XML en FoxPro 9.0

10,634 views
Skip to first unread message

Rafael Morales

unread,
Apr 26, 2012, 9:45:43 PM4/26/12
to publice...@googlegroups.com
Hola a todos, estoy tratando de exportar datos desde un Cursor a un archivo XML respetando un Formato?, he logrado exportar los datos con el siguiente código:

CURSORTOXML("MyCursor", "C:\myXMLarchivo.xml", 1, 512, 0,  "mySchema.xsd")

El problema es que el Fox exporta los datos con un formato muy diferente al que necesito. El formato debe ser de la siguiente forma:

<?xml version = "1.0" encoding="Windows-1252" standalone="yes"?>
<individuo>
  <codigo id="123" Nombre="DANIEL ROBERTO" Apellido="GONZALEZ" Sexo="M">
    <Direccion domicilio="Alvarado 15" Provincia="Chubut" Cp="5454" />
    <Visitas>
      <hoy fecha="26-03-2012 00:00:00" kilos="54,1" altura="152,3" Nota="PRIMER CONTROL" />
    </Visitas>
  </codigo>
</individuo>


El cursor que utilizo tiene esta estructura

Create MyCursor(id c(9),Nombre c(30),Apellido c(20),Sexo c(1),domicilio c(40),provincia c(35),cp c(9),fecha d,kilos n(5,1),altura n(5,1),nota c(254))

Lo que me muestra el Fox en el archivo XML que genera es mas o menos asi:

<?xml version = "1.0" encoding="Windows-1252" standalone="yes"?>
<VFPData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="mySchema.xsd">
    <labels>
        <id>154</id>
        <nombre>JOSE AGUSTIN</nombre>
        <apellido>VILLAGRA</apellido>
        <sexo>M</sexo>
    </labels>
    <labels>
        <id>155</id>
        <nombre>VILMA</nombre>
        <apellido>MARTINEZ</apellido>
        <sexo>F</sexo>
    </labels>
    <labels>
        <id>156</id>
        <nombre>LUIS ALBERTO</nombre>
        <apellido>SANCHEZ</apellido>
        <sexo>M</sexo>
    </labels>
</VFPData>


Alguien sabe cómo puedo lograr resolver este problema?, Gracias.

Victor Espina

unread,
Apr 27, 2012, 9:11:10 AM4/27/12
to publice...@googlegroups.com
SI el formato es tan sencillo como lo muestras, creo que irias mejor con un diclo SCAN y un TEXT...ENDTEXT o incluso concatenando cadenas.

Saludos

Victor Espina

Rafael Morales

unread,
Apr 27, 2012, 9:44:25 AM4/27/12
to publice...@googlegroups.com
Hola Victo Gracias por responder. Asi es, el formato es sencillo y puedo hacerlo en un txt pero cómo lo transformo luego a XML y que el Fox mantenga ese formato sin agregarle ni quitarle nada. La verdad es que nunca he trabajado con este tipo de archivo XML.
Podrias darme un ejemplo para que pueda copiar?, gracias.

ArturoPC

unread,
Apr 27, 2012, 12:20:47 PM4/27/12
to publice...@googlegroups.com
He trabajo buena cantidad de XMLs y nunca me sirvió el CURSORTOXML()

Siempre, aun en estructuras complejas, he usado la combinación de concatenar cadenas y TEXT/ENDTEXT.

Así que al armar un XML es lo que siempre recomiendo es lo que indica Víctor. Definitivamente.

Lo transformas a XML con el STRTOFILE(). Siguiendo el ejemplo de Víctor luego del ENDTEXT escribe:
=STRTOFILE(cXML, "miArchivo.xml")

Slds,
Arturo PC.

Rafael Morales

unread,
Apr 27, 2012, 1:35:52 PM4/27/12
to publice...@googlegroups.com
Excelente!!!, Muchas Gracias Victor y Muchas Gracias Arturo, resolvi el problema utilizando lo que me dijeron los dos. Gracias por la Ayuda. Saludos

Marco Plaza

unread,
Apr 27, 2012, 3:22:39 PM4/27/12
to Comunidad de Visual Foxpro en Español
Hola Rafael, el problema es que tienes es que deseas obtener una
salida xml con elementos anidados a partir de una tabla
desnormalizada.
aqui mando el codigo completo que hace el archivo tal como lo
necesitas. ( requirió una trampita para envolver las visitas en un
elemento ) pero ahi ven que potente es fox con los cursores.

Saludos.

Marco

*---------------------------------------


CLOSE DATABASES

Create CURSOR MyCursor(id c(9),Nombre c(30),Apellido c(20),Sexo
c(1),domicilio c(40),provincia c(35),cp c(9),fecha d(8),kilos
n(5,1),altura n(5,1),nota c(254))

INSERT INTO mycursor ;
( id,NOMBRE,APELLIDO,SEXO,DOMICILIO,PROVINCIA,CP,FECHA,KILOS,ALTURA,NOTA ) ;
VALUES ;
( '123','DANIEL ROBERTO','GONZALES','M','alvarado 15','Chubut','5454',
{^2012/03/26},54.1,152.3,'primer control')

SELECT id,nombre,apellido,sexo FROM mycursor INTO TABLE codigo
INDEX on id TAG id
SELECT id,domicilio,provincia,cp FROM mycursor INTO TABLE direccion
INDEX on id TAG id
SELECT id,fecha,kilos,altura,nota FROM mycursor INTO TABLE hoy
INDEX on id TAG id

USE codigo IN 0 AGAIN ALIAS Visitas ORDER id

SET RELATION TO id INTO direccion IN codigo
SET RELATION TO id INTO Visitas IN codigo additive
SET RELATION TO id INTO hoy IN Visitas

SELECT codigo
SET FIELDS TO all

SELECT direccion
SET FIELDS TO domicilio,provincia,cp

SELECT hoy
SET FIELDS TO fecha,kilos,altura,nota


oXml = CREATEOBJECT('xmladapter')

WITH oXml

.RespectNesting= .T.
.xmlSchemalocation = ''
.AddTableSchema('codigo',.f.)
.AddTableSchema('direccion',.f.)
.AddTableSchema('Visitas',.f.)
.AddTableSchema('hoy',.f.)
.ToXML('test.xml',,.t.)

ENDWITH

MODIFY FILE test.xml


*---------------------------------------


On 27 abr, 13:35, Rafael Morales <rafamra2...@gmail.com> wrote:
> *Excelente!!!, Muchas Gracias Victor y Muchas Gracias Arturo, resolvi el
> problema utilizando lo que me dijeron los dos. Gracias por la Ayuda. Saludos
> *

Marco Plaza

unread,
Apr 27, 2012, 3:52:06 PM4/27/12
to Comunidad de Visual Foxpro en Español

Este código tiene el nivel que le falta para el individuo - observen
que para los archivos que no indicamos un set fields no se publican
los campos.


Saludos.

Marco



*-----------------------------------------------------------
CLOSE DATABASES

Create CURSOR MyCursor(id c(9),Nombre c(30),Apellido c(20),Sexo
c(1),domicilio c(40),provincia c(35),cp c(9),fecha d(8),kilos
n(5,1),altura n(5,1),nota c(254))

INSERT INTO mycursor ;
( id,NOMBRE,APELLIDO,SEXO,DOMICILIO,PROVINCIA,CP,FECHA,KILOS,ALTURA,NOTA ) ;
VALUES ;
( '123','DANIEL ROBERTO','GONZALES','M','alvarado 15','Chubut','5454',
{^2012/03/26},54.1,152.3,'primer control')

SELECT id,nombre,apellido,sexo FROM mycursor INTO TABLE individuo
INDEX on id TAG id
SELECT id,domicilio,provincia,cp FROM mycursor INTO TABLE direccion
INDEX on id TAG id
SELECT id,fecha,kilos,altura,nota FROM mycursor INTO TABLE hoy
INDEX on id TAG id

USE individuo IN 0 AGAIN ALIAS codigo ORDER id
USE individuo IN 0 AGAIN ALIAS visitas ORDER id

SET RELATION TO id INTO codigo IN individuo
SET RELATION TO id INTO direccion IN codigo
SET RELATION TO id INTO Visitas IN codigo additive
SET RELATION TO id INTO hoy IN Visitas

SELECT codigo
SET FIELDS TO all

SELECT direccion
SET FIELDS TO domicilio,provincia,cp

SELECT hoy
SET FIELDS TO fecha,kilos,altura,nota


oXml = CREATEOBJECT('xmladapter')

WITH oXml

.RespectNesting= .T.
.xmlSchemalocation = ''
.AddTableSchema('individuo',.f.)
.AddTableSchema('codigo',.f.)
.AddTableSchema('direccion',.f.)
.AddTableSchema('Visitas',.f.)
.AddTableSchema('hoy',.f.)
.ToXML('test.xml',,.t.)

ENDWITH

MODIFY FILE test.xml


********************************************************************************

Victor Espina

unread,
Apr 27, 2012, 4:02:22 PM4/27/12
to publice...@googlegroups.com
Y de paso es mucho mas complicado de armar y controlar. Una cosa genial que tiene el TEXT-ENDTEXT es que controlas con exactitud la estructura del XML generado.

SAludos

Victor Espina

Marco Plaza

unread,
Apr 27, 2012, 4:52:01 PM4/27/12
to Comunidad de Visual Foxpro en Español
Bueno Víctor.. las herramientas xml de fox son muy poderosas... porqué
hacer xml a mano?

Ló unico fuera de lo común ( que espero puedan aprovechar ) es
utilizar la misma tabla padre dos veces con otro alias para poder
crear los elementos <individuo></individuo> y <visitas> </visitas>,
así como el uso de set fields para omitir el id en las tablas
relacionadas y todos los campos en idividuo y visitas.

Otros puntos:
al colocar schemaLocation en blanco se indica que no deseas crear el
esquema.
respectNesting hace que los elementos en el xml resultante salgan
anidados.
al añadir las tablas se indica el parámetro .f. para indicar que
deseas que la salida sea como atributos.

Igual espero pueda servir como guía para trabajar con el xmladapter.

Saludos

Marco

Rafael Morales

unread,
Apr 27, 2012, 5:32:05 PM4/27/12
to publice...@googlegroups.com
Esta bueno el Aporte de Marco, no está demás saber otra manera de llegar al mismo resultado. Buen aporte.

Antonio dijiste que lograste hacer un programa que hace la inversa es decir convertir un archivo XML a Texto. Eso es genial podrías contar mas o menos como lo hiciste?, si se puede.

Victor Espina

unread,
Apr 27, 2012, 6:03:48 PM4/27/12
to publice...@googlegroups.com
Por un tema de control Marco. El problema com XmlAdapter y CursorToXML() es que no tienes mucho control sobre lo que se genera. Entonces, lo que me sucedio muchas veces fue que despues de perder horas ingeniandomelas para que el XML saliera como yo lo queria usando XmlAdapter o CursorToXML(), terminaba haciendolo a mano en menos de media hora.

No digo que no sean utiles; lo que digo es que hay que estar muy claros en como funciona para poder identificar en que casos se pueden usar para resolver rapidamente y cuales es mejor generar el Xml manualmente.

Saludos

Victor Espina

Mario López

unread,
Apr 27, 2012, 7:00:02 PM4/27/12
to Comunidad de Visual Foxpro en Español
@Victor:

+100 a esto, tengo un programa VFP que exporta XML a otro programa
.NET WinCE usando XMLAdapter; luego vuelve a recibir dicho archivo
modificado: me perdí más de medio día tratando de que el
programa .NET
respetara el schema y no me agregara decimales en los datos numéricos
devueltos. Finalmente lo terminé arreglando con un par de líneas de
VFP
(lo que me llevó 5 minutos).

Saludos,
Mario

---

Victor Espina

unread,
Apr 27, 2012, 7:57:16 PM4/27/12
to publice...@googlegroups.com
I rest my case :)

Saludos y Feliz Fin De Semana

Victor Espina

Sharp User

unread,
Apr 27, 2012, 8:04:58 PM4/27/12
to publice...@googlegroups.com
That is all, Mr. Víctor :-)

Marco Plaza

unread,
Apr 27, 2012, 9:37:34 PM4/27/12
to Comunidad de Visual Foxpro en Español
Víctor, quien lea esos consejos de text-endtext podrá creer que vfp
no tiene forma de hacer buen trabajo con xml, y eso no sólo no es así,
sino que es todo lo contrario.

Sería interesante ver como generan ese archivo xml, no partiendo de la
tabla MyCursor, sino con la data normalizada Individuo->Direccion /
visitas ( que sería la estructura del sistema real ) y suponiendo
que tengan que manejar no 5 campos, sino 50 o 100, o aplicar
transformaciones al xml.

Vfp entrega un sinnúmero de herramientas para el trabajo con Xml y
vale la pena estudiarlas y usarlas, aunque el tiempo escaso a veces
nos lleve por 'el camino corto' del textmerge.

Usen el xmladapter, el resultado siempre será un código mas limpio ,
ajustado a la norma y fácil de mantener.

Saludos

Marco


On 27 abr, 20:04, Sharp User <sharp.use...@gmail.com> wrote:
> That is all, Mr. Víctor :-)
>
> >> > > > > *-----------------------------**------------------------------
> >> > > > > CLOSE DATABASES
>
> >> > > > > Create CURSOR MyCursor(id c(9),Nombre c(30),Apellido c(20),Sexo
> >> > > > > c(1),domicilio c(40),provincia c(35),cp c(9),fecha d(8),kilos
> >> > > > > n(5,1),altura n(5,1),nota c(254))
>
> >> > > > > INSERT INTO mycursor ;
> >> > > > > (
> >> > > id,NOMBRE,APELLIDO,SEXO,**DOMICILIO,PROVINCIA,CP,FECHA,**KILOS,ALTURA,NOTA
> >> )
> >> > > > > ;
> >> > > > > VALUES ;
> >> > > > > ( '123','DANIEL ROBERTO','GONZALES','M','**alvarado
> >> 15','Chubut','5454',
> >> > > > > {^2012/03/26},54.1,152.3,'**primer control')
>
> >> > > > > SELECT id,nombre,apellido,sexo FROM mycursor INTO TABLE individuo
> >> > > > > INDEX on id TAG id
> >> > > > > SELECT id,domicilio,provincia,cp FROM mycursor INTO TABLE
> >> direccion
> >> > > > > INDEX on id TAG id
> >> > > > > SELECT id,fecha,kilos,altura,nota FROM mycursor INTO TABLE hoy
> >> > > > > INDEX on id TAG id
>
> >> > > > > USE individuo IN 0 AGAIN ALIAS codigo ORDER id
> >> > > > > USE individuo IN 0 AGAIN ALIAS visitas ORDER id
>
> >> > > > > SET RELATION TO id INTO codigo IN individuo
> >> > > > > SET RELATION TO id INTO direccion IN codigo
> >> > > > > SET RELATION TO id INTO Visitas IN codigo additive
> >> > > > > SET RELATION TO id INTO hoy IN Visitas
>
> >> > > > > SELECT codigo
> >> > > > > SET FIELDS TO all
>
> >> > > > > SELECT direccion
> >> > > > > SET FIELDS TO domicilio,provincia,cp
>
> >> > > > > SELECT hoy
> >> > > > > SET FIELDS TO fecha,kilos,altura,nota
>
> >> > > > > oXml = CREATEOBJECT('xmladapter')
>
> >> > > > > WITH oXml
>
> >> > > > > .RespectNesting= .T.
> >> > > > > .xmlSchemalocation = ''
> >> > > > > .AddTableSchema('individuo',.**f.)
> >> > > > > .AddTableSchema('codigo',.f.)
> >> > > > > .AddTableSchema('direccion',.**f.)
> >> > > > > .AddTableSchema('Visitas',.f.)
> >> > > > > .AddTableSchema('hoy',.f.)
> >> > > > > .ToXML('test.xml',,.t.)
>
> >> > > > > ENDWITH
>
> >> > > > > MODIFY FILE test.xml
>
> >> > > ************************************************************************************
>
> >> > > > > On 27 abr, 15:22, Marco Plaza <stmapw...@gmail.com> wrote:
> >> > > > > > Hola Rafael, el problema es que tienes es que deseas obtener
> >> una
> >> > > > > > salida xml con elementos anidados a partir de una tabla
> >> > > > > > desnormalizada.
> >> > > > > > aqui mando el codigo completo que hace el archivo tal como lo
> >> > > > > > necesitas. ( requirió una trampita para envolver las visitas en
> >> un
> >> > > > > > elemento ) pero ahi ven que potente es fox con los cursores.
>
> >> > > > > > Saludos.
>
> >> > > > > > Marco
>
> >> > > > > > *-----------------------------**----------
>
> >> > > > > > CLOSE DATABASES
>
> >> > > > > > Create CURSOR MyCursor(id c(9),Nombre c(30),Apellido c(20),Sexo
> >> > > > > > c(1),domicilio c(40),provincia c(35),cp c(9),fecha d(8),kilos
> >> > > > > > n(5,1),altura n(5,1),nota c(254))
>
> >> > > > > > INSERT INTO mycursor ;
> >> > > > > > (
> >> > > id,NOMBRE,APELLIDO,SEXO,**DOMICILIO,PROVINCIA,CP,FECHA,**KILOS,ALTURA,NOTA
>
> >> > > > > ) ;
> >> > > > > > VALUES ;
> >> > > > > > ( '123','DANIEL ROBERTO','GONZALES','M','**alvarado
> >> > > 15','Chubut','5454',
> >> > > > > > {^2012/03/26},54.1,152.3,'**primer control')
>
> >> > > > > > SELECT id,nombre,apellido,sexo FROM mycursor INTO TABLE codigo
> >> > > > > > INDEX on id TAG id
> >> > > > > > SELECT id,domicilio,provincia,cp FROM mycursor INTO TABLE
> >> direccion
> >> > > > > > INDEX on id TAG id
> >> > > > > > SELECT id,fecha,kilos,altura,nota FROM mycursor INTO TABLE hoy
> >> > > > > > INDEX on id TAG id
>
> >> > > > > > USE codigo IN 0 AGAIN ALIAS Visitas ORDER id
>
> >> > > > > > SET RELATION TO id INTO direccion IN codigo
> >> > > > > > SET RELATION TO id INTO Visitas IN codigo additive
> >> > > > > > SET RELATION TO id INTO hoy IN Visitas
>
> >> > > > > > SELECT codigo
> >> > > > > > SET FIELDS TO all
>
> >> > > > > > SELECT direccion
> >> > > > > > SET FIELDS TO domicilio,provincia,cp
>
> >> > > > > > SELECT hoy
> >> > > > > > SET FIELDS TO fecha,kilos,altura,nota
>
> >> > > > > > oXml = CREATEOBJECT('xmladapter')
>
> >> > > > > > WITH oXml
>
> >> > > > > > .RespectNesting= .T.
> >> > > > > > .xmlSchemalocation = ''
> >> > > > > > .AddTableSchema('codigo',.f.)
> >> > > > > > .AddTableSchema('direccion',.**f.)
> >> > > > > > .AddTableSchema('Visitas',.f.)
> >> > > > > > .AddTableSchema('hoy',.f.)
> >> > > > > > .ToXML('test.xml',,.t.)
>
> >> > > > > > ENDWITH
>
> >> > > > > > MODIFY FILE test.xml
>
> >> > > > > > *-----------------------------**----------

Rafael Morales

unread,
Apr 27, 2012, 10:08:45 PM4/27/12
to publice...@googlegroups.com
Gracias a todos. Buen fin de semana.

Victor Espina

unread,
Apr 28, 2012, 12:21:53 PM4/28/12
to publice...@googlegroups.com
Acertado el comentario Marco. Creo que mi punto es como dije antes: XmlAdapter y CursorToXml son excelentes opciones, siempre y cuando estes claro de que es lo que pueden hacer y, sobre todo, lo que NO pueden hacer. De esta forma evitas perder tiempo tratando de lograr un resultado que nunca se podra lograr por esa via.

Creo que tambien comente antes que la tecnica del TEXT-ENDTEXT era muy util para el caso de Xmls SENCILLOS... obviamente generar un XML complejo con multiples niveles por esta via seria bastante mas complicado por la via del textmerge.

Finalmente, creo que estaba claro que el TEXT-ENDTEXT sirve SOLO para generar el XML; para transformaciones, validaciones, etc, obviamente tendrias que usar el XmlAdapter.

Recuerda que una de las cosas bellas de VFP es que te da muchas herramientas, pero tambien te da infinidad de formas de hacer las cosas por tu cuenta si asi lo quieres, obteniendo un mayor control sobre el proceso.

Saludos

Victor Espina

Victor Espina

unread,
Apr 27, 2012, 11:58:24 AM4/27/12
to publice...@googlegroups.com
Create CURSOR MyCursor (id c(9),Nombre c(30),Apellido c(20),Sexo c(1),domicilio c(40),provincia c(35),cp c(9),fecha d,kilos n(5,1),altura n(5,1),nota c(254))
INSERT INTO myCursor VALUES ("123","DANIEL ROBERTO","GONZALEZ","M","Alvarado 15","Chubut","5454",{^2012-03-26},54.1,152.3,"PRIMER CONTROL")
LOCAL cXml
SET DATE ITALIAN
TEXT TO cXML TEXTMERGE NOSHOW
<?xml version = "1.0" encoding="Windows-1252" standalone="yes"?>
<individuo>
  <codigo id="<<RTRIM(id)>>" Nombre="<<RTRIM(nombre)>>" Apellido="<<RTRIM(apellido)>>" Sexo="<<sexo>>">
    <Direccion domicilio="<<RTRIM(domicilio)>>" Provincia="<<RTRIM(provincia)>>" Cp="<<RTRIM(cp)>>" />
    <Visitas>
      <hoy fecha="<<TTOC(fecha)>>" kilos="<<ALLTRIM(STR(kilos,5,1))>>" altura="<<ALLTRIM(STR(altura,5,1))>>" Nota="<<RTRIM(nota)>>" />
    </Visitas>
  </codigo>
</individuo>
ENDTEXT
?cXML

Antonio.xt

unread,
Apr 27, 2012, 5:05:18 PM4/27/12
to publice...@googlegroups.com

Es correcto, tal como dice Victor, con las funciones XML de Fox se complica el manejo de documentos XML. Yo igual estoy generando archivos XML con TEXT-ENDTEXT y tenes control total sobre el documento final, ahora necesite crear un programa para la inversa, es decir, pasar a un cursor los datos de un XML y la funcion XMLTOCURSOR() no me daba la respuesta que necesitaba. Sera que no la se usar, pero se me hizo mas facir TEXT-ENDTEXT para armarla y un procedimiento sencillo para obtener los datos.

Saludos...

Charles A. Moreno

Antonio.xt

unread,
Apr 27, 2012, 6:36:36 PM4/27/12
to publice...@googlegroups.com

Claro Rafamra2008, cuando creo un XML para enviar cierta informacion uso TEXT-ENDTEXT, obviamente ya tienes una estructura definida, aunque no necesariamente tienes que cumplir fríamente esa estructura, puede haber datos que a veces se incluyen y otras veces no, para eso hice una funcion para ir agregando datos al XML, y esa funcion usa la instrucción  TEXT TO {variable del objeto XML} ADDITIVE TEXTMERGE NOSHOW, muy importante en este caso agregar la clausula  ADDITIVE.

Y para recuperar los datos del XML hice otra funcion en donde hago uso de la funcion STREXTRACT. Independientemente de la estructura que tenga el XML, lo bueno es que los datos tienen que estar en grupos, y cada dato tiene su etiqueta.

No se si sea el proceso mas optimo, pero funciona muy bien y me da los resultados exactos.

Saludos...

Charles A. Moreno

Ecos Tamaulipas

unread,
Feb 25, 2014, 2:51:22 PM2/25/14
to publice...@googlegroups.com
   Antonio, buenas tardes
   Se que este post ya tiene mucho tiempo pero en este momento requiero hacer algo por lo que tu ya pasaste, tengo un xml timbrado y necesito agregarle addenda, una forma seria leer el xml y pasarlo a texto, ahi agregar la addenda y despues volverlo a convertir a xml, podrias ayudarme tu o alguien del foro enviandome un ejemplo sencillo de como pasar el xml a texto para empezar :) y ya despues veo como pegarle la addenda y regresarlo a formato xml
   Gracias!

Mauricio Gonzalez

unread,
Sep 5, 2018, 7:24:30 PM9/5/18
to Comunidad de Visual Foxpro en Español

Carlillus

unread,
Jan 8, 2020, 11:35:11 AM1/8/20
to Comunidad de Visual Foxpro en Español
Alguien podria enviarme una prueba de codigo probada y corriendo correctamente para generar una factura electronica por favor:

Mi email es: Carlos...@GMail.com

De antemano, gracias por la ayuda
Reply all
Reply to author
Forward
0 new messages