In order for this site to work correctly we need to store a small file (called a cookie) on your computer. Most every site in the world does this, however since the 25th of May 2011, by law we have to get your permission first. Please abandon the forum if you disagree.

Para que este foro funcione correctamente es necesario guardar un pequeño fichero (llamado cookie) en su ordenador. La mayoría de los sitios de Internet lo hacen, no obstante desde el 25 de Marzo de 2011 y por ley, necesitamos de su permiso con antelación. Abandone este foro si no está conforme.

Leer archivo XML (Solucionado)

Foro público de Xailer en español
Responder
ryder1912
Mensajes: 29
Registrado: Jue Jul 09, 2015 8:17 pm

Leer archivo XML (Solucionado)

Mensaje por ryder1912 »

Buenas a todos, estoy tratando de leer un archivo xml (.rta) pero no me sale, ya q no sé como recorrer el archivo. La idea es obtener los registros, insertarlos en un array, y que quede de esta manera:
ID | Bandera
11 AXION
12 BLANCA
2 ESSO
10 OIL
9 PDV SUR
4 PETROBRAS

Este es el archivo xml (es un archivo.rta q se puede abrir con el bloc de notas), en la que cada tag <BanderasDTO> representa un registro con el id de la bandera y el nombre.

Código: Seleccionar todo

<?xml version="1.0" encoding="utf-16"?>
<ArrayOfBanderasDTO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <BanderasDTO>
    <IdBandera>11</IdBandera>
    <Nombre>AXION                                   </Nombre>
  </BanderasDTO>
  <BanderasDTO>
    <IdBandera>12</IdBandera>
    <Nombre>BLANCA                                  </Nombre>
  </BanderasDTO>
  <BanderasDTO>
    <IdBandera>2</IdBandera>
    <Nombre>ESSO                                    </Nombre>
  </BanderasDTO>
  <BanderasDTO>
    <IdBandera>10</IdBandera>
    <Nombre>OIL                                     </Nombre>
  </BanderasDTO>
  <BanderasDTO>
    <IdBandera>9</IdBandera>
    <Nombre>PDV SUR                                 </Nombre>
  </BanderasDTO>
  <BanderasDTO>
    <IdBandera>4</IdBandera>
    <Nombre>PETROBRAS                               </Nombre>
  </BanderasDTO>
</ArrayOfBanderasDTO>
Este es el código, q está basado en el ejemplo BTS de samples. Con el XMLReadArray puedo obtener primer registro pero no me sirve.
Con el XMLReadSection intente hacer algo parecido metiendo dos while y q recorra todo pero no me sale ya q se repite el primer el registro (o nodo), necesito una mano en ese método.

Código: Seleccionar todo

#include "Xailer.ch"
#include "ExStruct.ch"
#include "hbxml.ch"

CLASS TFormPpal FROM TForm

   COMPONENT oBevel1
   COMPONENT oBevel2
   COMPONENT btAbrirArch
   COMPONENT oFileOpenDlg1
   COMPONENT oLabel1
   COMPONENT oBrw

   DATA cIniFile, cXMLFile
   DATA aHeaders, oRecord

   METHOD CreateForm()
   METHOD FormInitialize( oSender )
   METHOD btAbrirArchClick( oSender )
   METHOD XMLRestore()
   METHOD XMLReadArray( oMIter, cSection )
   METHOD XMLReadSection( oMIter, cSection )

ENDCLASS

#include "FormpPpal.xfm"

//------------------------------------------------------------------------------

METHOD FormInitialize( oSender ) CLASS TFormPpal

   STRUC ::oRecord   // Registros de BanderasDTO
         MEMBER IdBandera   AS NUMBER INIT 0
         MEMBER Nombre      AS STRING INIT ""
   END STRUC

   ::aHeaders:={'ID', 'Banderas'}

RETURN Nil

//------------------------------------------------------------------------------

METHOD btAbrirArchClick( oSender ) CLASS TFormPpal
local x
   if ::oFileOpenDlg1:Execute() .and. File(::oFileOpenDlg1:cFullFileName)
      x:=0
      ::oLabel1:cText:=::oFileOpenDlg1:cFullFileName
      ::cXMLFile :=::oFileOpenDlg1:cFullFilename()
      ::XMLRestore()
   else
      ::oLabel1:cText:=''
   endif
RETURN Nil

//------------------------------------------------------------------------------

METHOD XMLRestore() CLASS TFormPpal

   LOCAL oDoc, oMIter, oNode, n
   LOCAL aData := {}, aBanderas:={} , aSeccion:={}
   LOCAL hFile

   hFile := FOpen( ::cXMLFile )

   IF hFile > -1
      oDoc   := TXMLDocument():New( hFile )
      oMIter := TXMLIteratorScan():New( oDoc:oRoot )


      //Aadd( aBanderas, ::XMLReadArray( oMIter, "BanderasDTO" ) )
      aBanderas := ::XMLReadSection( oMIter, "BanderasDTO" )
      n:=0
      FClose( hFile )
   Endif
   ::cText := Application:cTitle + "  -  " + FileShortName( ::cXMLFile )
   ::oBrw:SetArray( aBanderas, ::aHeaders, .T. )

RETURN NIL

//------------------------------------------------------------------------------

METHOD XMLReadArray( oMIter, cSection ) CLASS TFormPpal

   LOCAL aData := {}, oIter, oNode

   oNode  := oMIter:Find( cSection )
   IF oNode != NIL
      oIter := TXMLIterator():New( oNode )
      oNode := oIter:Next()
      DO WHILE oNode != NIL
         Aadd( aData, oNode:cData )
         oNode := oIter:Next()
      ENDDO
   ENDIF

RETURN aData

//------------------------------------------------------------------------------

METHOD XMLReadSection( oMIter, cSection ) CLASS TFormPpal
 LOCAL oXmlNode, oXmlIter1, oNode1, oXmlIter2, oNode2
 LOCAL aData := {}, aReg:={}
 
 	oXmlNode := oMIter:Find( cSection )
	oXmlIter1 := TXmlIterator():new( oXmlNode )
        oNode1    := oXmlIter1:getNode()
	
	While oNode1 != NIL
	       oXmlIter2 := TXmlIteratorScan():new( oNode1 )
	       oNode2    := oXmlIter2:Next()
               While  oNode2 != NIL
            		::oRecord:SetValue( oNode2:cName, oNode2:cData )
           		 Aadd( aReg, oNode2:cData)
            		oNode2 := oXmlIter2:Next()
 		EndDo
           Aadd( aData, ::oRecord:GetValues() )
           oNode1    := oXmlIter1:Next()
	   EndDo

RETURN aData
Bueno adjunto el ejemplo con el archivo .rta, por si alguien quiere probarlo, saludos.
Adjuntos
prueba XML.zip
(2.8 KiB) Descargado 157 veces
Última edición por ryder1912 el Mar Abr 17, 2018 7:32 pm, editado 1 vez en total.
ftwein
Mensajes: 50
Registrado: Lun Oct 22, 2007 5:17 pm

Re: Leer archivo XML

Mensaje por ftwein »

Buenas,

Por favor intente con el código abajo.

Note oDoc en lugar de oMIter.

Fausto Di Creddo Trautwein

Código: Seleccionar todo

METHOD XMLRestore() CLASS TFormPpal

   LOCAL oDoc, oMIter, oNode, n
   LOCAL aData := {}, aBanderas:={} , aSeccion:={}
   LOCAL hFile

   hFile := FOpen( ::cXMLFile )

   IF hFile > -1
      oDoc   := TXMLDocument():New( hFile )
      //oMIter := TXMLIteratorScan():New( oDoc:oRoot )

      //Aadd( aBanderas, ::XMLReadArray( oMIter, "BanderasDTO" ) )
      aBanderas := ::XMLReadSection( oDoc, "BanderasDTO" )
      n:=0
      FClose( hFile )
   Endif
   ::cText := Application:cTitle + "  -  " + FileShortName( ::cXMLFile )
   ::oBrw:SetArray( aBanderas, ::aHeaders, .T. )
RETURN NIL

METHOD XMLReadSection( oDoc, cSection ) CLASS TFormPpal

   LOCAL oXmlNode, oXmlIter1, oNode1
   LOCAL aData := {}, aReg:={}

	oXmlNode := oDoc:FindFirst( cSection )
      
      While oXmlNode != Nil
	
         oXmlIter1 := TXmlIterator():new( oXmlNode )
         oNode1    := oXmlIter1:Next()
	
         While oNode1 != NIL
	
            ::oRecord:SetValue( oNode1:cName, oNode1:cData )
            Aadd( aReg, oNode1:cData)
            oNode1 := oXmlIter1:Next()

         EndDo
      
         Aadd( aData, ::oRecord:GetValues() )
         oXmlNode    := oDoc:FindNext()
	   
      EndDo

RETURN aData
ryder1912
Mensajes: 29
Registrado: Jue Jul 09, 2015 8:17 pm

Re: Leer archivo XML (Solucionado)

Mensaje por ryder1912 »

Buenas, funcionó. Ya lo habia hecho funcionar pero con 3 whiles, sin modificar el metodo restoreXML, y era medio engorroso.
Por las dudas dejo el codigo abajo. La alternativa del amigo ftwein es mejor, gracias y saludos.

Código: Seleccionar todo

// Sin modificar el metodo RestoreXML
METHOD XMLReadSection( oMIter, cSection ) CLASS TFormPpal
LOCAL oXmlNode, oXmlIter1, oNode1, oXmlIter2, oNode2
LOCAL aData := {}, aReg:={}

   oXmlNode := oMIter:Find( cSection )

   While oXmlNode != NIL
      oXmlIter1 := TXmlIterator():new( oXmlNode )
      oNode1    := oXmlIter1:getNode()

      While oNode1 != NIL

         oXmlIter2 := TXmlIteratorScan():new( oNode1 )
         oNode2    := oXmlIter2:Next()
         While oNode2 != NIL
            ::oRecord:SetValue( oNode2:cName, oNode2:cData )
            Aadd( aReg, oNode2:cData)
            oNode2 := oXmlIter2:Next()
         EndDo
         Aadd( aData, ::oRecord:GetValues() )
         oNode1:=Nil

      EndDo
      oXmlNode:= oXmlNode:oNext()
    EndDo

RETURN aData
Responder