Página 1 de 1

Leer archivo XML (Solucionado)

Publicado: Dom Abr 15, 2018 5:09 am
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.

Re: Leer archivo XML

Publicado: Mar Abr 17, 2018 3:24 pm
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

Re: Leer archivo XML (Solucionado)

Publicado: Mar Abr 17, 2018 7:30 pm
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