Clipper On Line • Ver Tópico - Classe e função pra carregar XML

Classe e função pra carregar XML

Projeto hbNFe (Nota Fiscal Eletronica/Danfe) para [x]Harbour

Moderador: Moderadores

 

Classe e função pra carregar XML

Mensagempor JoséQuintas » 25 Jul 2016 18:14

Prefiro meu jeito de trabalhar com XML.
Está do jeito que eu uso, mas precisa melhorar algumas coisas, até mesmo os nomes usados.
Qualquer dia uso também pra gerar XML, e não só pra importar.
Dá até pra fazer assim:

oFileList := Directory( "*.xml" )
FOR EACH oFile IN oFileList
   oDoc := XmlToDoc( MemoRead( oFile[ 1 ] ) )
   ? oDoc:cNumDoc, oDoc:DataEmissao, oDoc:Emitente:Nome, oDoc:Destinatario:Nome, oDoc:Totais:ValNot
NEXT
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18013
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Classe e função pra carregar XML

Mensagempor JoséQuintas » 25 Jul 2016 18:17

A classe com o documento, que pode ser NFE, CTE, CCE. Só variáveis.

#include "hbclass.ch"

CREATE CLASS NfeCadastroClass

   VAR  Nome                INIT ""
   VAR  Cnpj                INIT ""
   VAR  InscricaoEstadual   INIT ""
   VAR  InscricaoMunicipal  INIT ""
   VAR  CNAE                INIT ""
   VAR  Endereco            INIT ""
   VAR  Numero              INIT ""
   VAR  Compl               INIT ""
   VAR  Bairro              INIT ""
   VAR  Cidade              INIT ""
   VAR  CidadeIbge          INIT ""
   VAR  Uf                  INIT ""
   VAR  Cep                 INIT ""
   VAR  Pais                INIT ""
   VAR  PaisBACEN           INIT ""
   VAR  Telefone            INIT ""

   END CLASS

CREATE CLASS NfeEnderecoEntregaClass

   VAR  Cnpj        INIT ""
   VAR  Endereco    INIT ""
   VAR  Numero      INIT ""
   VAR  Compl       INIT ""
   VAR  Bairro      INIT ""
   VAR  Cidade      INIT ""
   VAR  CidadeIbge  INIT ""
   VAR  Uf          INIT ""

   END CLASS

CREATE CLASS NfeVolumesClass // From NfeTransporteClass

   VAR  Qtde         INIT 0
   VAR  Especie      INIT ""
   VAR  Marca        INIT ""
   VAR  PesoLiquido  INIT 0
   VAR  PesoBruto    INIT 0
   VAR  Lacres       INIT ""

   END CLASS

CREATE CLASS NfeTransporteClass

   VAR  Nome              INIT ""
   VAR  Cnpj              INIT ""
   VAR  InscricaoEstadual INIT ""
   VAR  Endereco          INIT ""
   VAR  Cidade            INIT ""
   VAR  CidadeIbge        INIT ""
   VAR  Uf                INIT ""
   VAR  Placa             INIT ""
   VAR  PlacaUf           INIT ""
   VAR  Volumes
   METHOD Init()

   END CLASS

METHOD Init() CLASS NfeTransporteClass

   ::Volumes := NfeVolumesClass():New()

   RETURN SELF

CREATE CLASS NfeTotaisClass

   VAR  IcmBas INIT 0
   VAR  IcmVal INIT 0
   VAR  SubBas INIT 0
   VAR  SubVal INIT 0
   VAR  IpiVal INIT 0
   VAR  IIVal  INIT 0
   VAR  IssVal INIT 0
   VAR  PisVal INIT 0
   VAR  CofVal INIT 0
   VAR  ValPro INIT 0
   VAR  ValSeg INIT 0
   VAR  ValFre INIT 0
   VAR  ValOut INIT 0
   VAR  ValNot INIT 0

   END CLASS

CREATE CLASS NfeIIClass

   VAR  Base     INIT 0
   VAR  Aliquota INIT 0
   VAR  Valor    INIT 0

   END CLASS

CREATE CLASS NfeIpiClass

   VAR  Base     INIT 0
   VAR  Aliquota INIT 0
   VAR  Valor    INIT 0

   END CLASS

CREATE CLASS NfeIssClass

   VAR  Base     INIT 0
   VAR  Aliquota INIT 0
   VAR  Valor    INIT 0

   END CLASS

CREATE CLASS NfeIcmsClass

   VAR  Cst      INIT ""
   VAR  Base     INIT 0
   VAR  Reducao  INIT 0
   VAR  Aliquota INIT 0
   VAR  Valor    INIT 0

   END CLASS

CREATE CLASS NfeIcmsStClass

   VAR  Base      INIT 0
   VAR  IVA       INIT 0
   VAR  Reducao   INIT 0
   VAR  Aliquota  INIT 0
   VAR  Valor     INIT 0

   END CLASS

CREATE CLASS NfePisClass

   VAR  Cst      INIT ""
   VAR  Base     INIT 0
   VAR  Aliquota INIT 0
   VAR  Valor    INIT 0

   END CLASS

CREATE CLASS NfeCofinsClass

   VAR  Cst      INIT ""
   VAR  Base     INIT 0
   VAR  Aliquota INIT 0
   VAR  Valor    INIT 0

   END CLASS

CREATE CLASS NfeProdutoClass

   VAR  Codigo        INIT ""
   VAR  Nome          INIT ""
   VAR  CfOp          INIT ""
   VAR  NCM           INIT ""
   VAR  GTIN          INIT ""
   VAR  Anp           INIT ""
   VAR  Unidade       INIT ""
   VAR  Qtde          INIT 0
   VAR  ValorUnitario INIT 0
   VAR  ValorTotal    INIT 0
   VAR  Icms
   VAR  IcmsSt
   VAR  Iss
   VAR  Ipi
   VAR  Pis
   VAR  Cofins
   VAR  II
   METHOD Init()

   END CLASS

METHOD Init() CLASS NfeProdutoClass

   ::Icms   := NfeIcmsClass():New()
   ::IcmsSt := NfeIcmsStClass():New()
   ::Iss    := NfeIssClass():New()
   ::II     := NfeIIClass():New()
   ::Ipi    := NfeIpiClass():New()
   ::Pis    := NfePisClass():New()
   ::Cofins := NfeCofinsClass():New()

   RETURN SELF

CREATE CLASS NfeDuplicataClass

   VAR  Vencimento INIT Ctod("" )
   VAR  Valor      INIT 0

   END CLASS

CREATE CLASS DocSpedClass

   VAR  ChaveAcesso             INIT ""
   VAR  cTipoDoc                INIT "" // 2014.11.20
   VAR  cEvento                 INIT "" // 2014.11.20
   VAR  Protocolo               INIT ""
   VAR  cNumDoc                 INIT ""
   VAR  DataEmissao             INIT Ctod( "" )
   VAR  DataSaida               INIT Ctod( "" )
   VAR  cAmbiente               INIT ""
   VAR  NaturezaOperacao        INIT ""
   VAR  Emitente             // --- init
   VAR  Destinatario         // --- init
   VAR  Remetente            // --- init // CTE
   VAR  EnderecoEntrega      // --- init
   VAR  Produto                 INIT {}
   VAR  Transporte           // --- init
   VAR  Duplicata               INIT {}
   VAR  Totais               // --- init
   VAR  ExportacaoUfEmbarque    INIT ""
   VAR  ExportacaoLocalEmbarque INIT ""
   VAR  InfAdicionais           INIT ""
   VAR  cAssinatura             INIT ""
   VAR  cSequencia              INIT "01" // Carta Correção
   VAR  Valor                   INIT 0  // CTE
   VAR  cERRO                   INIT "" // Texto do erro
   VAR  PesoCarga               INIT 0  // Cte
   VAR  ValorCarga              INIT 0  // Cte
   VAR  Status                  INIT ""
   METHOD Init()

   END CLASS

METHOD Init() CLASS DocSpedClass

   ::Emitente        := NfeCadastroClass():New()
   ::Destinatario    := NfeCadastroClass():New()
   ::Remetente       := NfeCadastroClass():New()
   ::EnderecoEntrega := NfeEnderecoEntregaClass():New()
   ::Transporte      := NfeTransporteClass():New()
   ::Totais          := NfeTotaisClass():New()

   RETURN SELF
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18013
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Classe e função pra carregar XML

Mensagempor JoséQuintas » 25 Jul 2016 18:21

É tudo usando a XmlNode() que já postei por aqui, e tem na SefazClass.

XmlToDoc() decide como pegar os dados, conforme o tipo de xml, e desvia pra função correspondente.

FUNCTION XmlToDoc( cXmlInput )

   LOCAL oDoc

   IF .NOT. ["] $ cXmlInput  // Petrobras usa aspas simples
      cXmlInput := StrTran( cXmlInput, ['], ["] )
   ENDIF
   oDoc := DocSpedClass():New()
   DO CASE
   CASE "<nfeProc"      $ cXmlInput
      oDoc:cTipoDoc := "55"
      oDoc:cEvento  := "110100"
      XmlToDocNfeEmi( cXmlInput, @oDoc )
   CASE "<cteProc" $ cXmlInput
      oDoc:cTipoDoc := "57"
      oDoc:cEvento  := "110100"
      XmlToDocCteEmi( cXmlInput, @oDoc )
   CASE "<mdfeProc" $ cXmlInput
      oDoc:cTipoDoc := "58"
      oDoc:cEvento  := "110100"
      XmlToDocMDFEEmi( cXmlInput, @oDoc )
   CASE "<procEventoNFe" $ cXmlInput .AND. "<descEvento>Cancelamento" $ cXmlInput
      oDoc:cTipoDoc := "55"
      oDoc:cEvento  := "110111"
      XmlToDocNfeCancel( cXmlInput, @oDoc )
   CASE "<procCancNFe" $ cXmlInput .AND. "<xServ>CANCELAR" $ cXmlInput
      oDoc:cTipoDoc := "55"
      oDoc:cEvento  := "110111"
      XmlToDocNFECancel( cXmlInput, @oDoc )
   CASE "<procEventoCTe" $ cXmlInput .AND. "<descEvento>Cancelamento" $ cXmlInput
      oDoc:cTipoDoc := "57"
      oDoc:cEvento  := "110111"
      XmlToDocCTeCancel( cXmlInput, @oDoc )
   CASE "<procEventoNFe" $ cXmlInput .AND. "<descEvento>Carta de Correcao" $ cXmlInput
      oDoc:cTipoDoc := "55"
      oDoc:cEvento  := "110110"
      XmlToDocNfeCCe( cXmlInput, @oDoc )
   CASE "<procEventoMDFe" $ cXmlInput .AND. "<descEvento>Cancelamento" $ cXmlInput
      oDoc:cTipoDoc := "58"
      oDoc:cEvento  := "110111"
      XmlToDocMDFECancel( cXmlInput, @oDoc )
   CASE "<procEventoMDFe" $ cXmlInput .AND. "<descEvento>Encerramento" $ cXmlInput
      oDoc:cTipoDoc := "58"
      oDoc:cEvento  := "110112"
      XmlToDocMDFEEnc( cXmlInput, @oDoc )
   CASE "<infMDFe" $ cXmlInput
      oDoc:cTipoDoc := "58"
      oDoc:cEvento  := "000000"
      XmlToDocMDFEEmi( cXmlInput, @oDoc )
   CASE "<infCte" $ cXmlInput
      oDoc:cTipoDoc := "57"
      oDoc:cEvento  := "000000"
      XmlToDocCteEmi( cXmlInput, @oDoc )
   CASE "<infNFe" $ cXmlInput
      oDoc:cTipoDoc := "55"
      oDoc:cEvento  := "000000"
      XmlToDocNfeEmi( cXmlInput, @oDoc )
   //CASE "<infEvento" $ cXmlInput
   //   // pode ser pra qualquer documento
   //   oDoc:cTipoDoc := "XX"
   //   oDoc:cEvento  := "XX"
   OTHERWISE
      oDoc:cErro := "Documento não identificado"
   ENDCASE
   IF Empty( oDoc:Destinatario:Cnpj ) .AND. Empty( oDoc:Destinatario:Nome )
      oDoc:Destinatario := oDoc:Emitente
   ENDIF
   oDoc:ChaveAcesso := SoNumeros( oDoc:ChaveAcesso )
   DO CASE
   CASE Len( oDoc:cErro ) != 0
   CASE Len( oDoc:ChaveAcesso ) != 44
      oDoc:cErro := "Tamanho da chave de acesso inválido"
   CASE Right( oDoc:ChaveAcesso, 1 ) != CalculaDigito( Substr( oDoc:ChaveAcesso, 1, 43 ), "11" )
      oDoc:cErro := "Dígito da chave de acesso inválido"
   CASE Substr( oDoc:ChaveAcesso, 5, 2 ) < "01" .OR. Substr( oDoc:ChaveAcesso, 5, 2 ) > "12"
      oDoc:cErro := "Mes da chave inválido"
   CASE .NOT. ValidCnpjCpf( Substr( oDoc:ChaveAcesso, 7, 14 ) )
      oDoc:cErro := "CNPJ inválido na chave de acesso"
   CASE Val( oDoc:Protocolo ) == 0
      oDoc:cErro := "Sem protocolo"
   CASE Empty( oDoc:cAssinatura )
      oDoc:cErro := "Sem assinatura"
   CASE oDoc:cAmbiente != "1"
      oDoc:cErro := "Não é ambiente de produção"
   CASE oDoc:cTipoDoc != Substr( oDoc:ChaveAcesso, 21, 2 )
      oDoc:cErro := "Tipo de documento " + Substr( oDoc:ChaveAcesso, 21, 2 )
   CASE oDoc:cEvento = "110100" .AND. Empty( oDoc:cNumDoc )
      oDoc:cErro := "Número de documento vazio"
   ENDCASE
   IF Len( oDoc:cErro ) != 0
      oDoc:cTipoDoc := "XX"
      oDoc:cEvento  := "XXXXXX"
   ENDIF

   RETURN oDoc
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18013
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Classe e função pra carregar XML

Mensagempor JoséQuintas » 25 Jul 2016 18:24

E a que lê o XML de nota emitida.
Dá-lhe ler um "node" de cada vez, com XmlNode()
O resultado é a nota inteira numa variável, que pode ser usada pra importar o XML, cadastrar cliente, cadastrar produtos, etc.

FUNCTION XmlToDocNfeEmi( cXmlInput, oNfe )

   LOCAL nCont
   LOCAL cBlocoInfNfeComTag, cBlocoChave, cBlocoIde, cBlocoInfAdic
   LOCAL cBlocoEmit, cBlocoEndereco, cBlocoDest, cBlocoTransporte, cBlocoTransp, cBlocoVeiculo, cBlocoVol, cBlocoTotal
   LOCAL cBlocoDetalhe, cBlocoItem, cBlocoProd,  cBlocoIpi, cBlocoIcms, cBlocoPis, cBlocoCofins
   LOCAL cBlocoComb, cBlocoCobranca, cBlocoDup

   cBlocoInfNfeComTag := XmlNode( cXmlInput, "infNFe", .T. )

   cBlocoChave := XmlElement( cBlocoInfNfeComTag, "Id" )
   cBlocoChave := Substr( cBlocoChave, 4 )
   cBlocoChave := AllTrim( cBlocoChave )
   IF Len( cBlocoChave ) <> 44
      oNfe:cErro := "Chave de Acesso Inválida"
      RETURN NIL
   ENDIF
   oNfe:ChaveAcesso := cBlocoChave
   oNfe:cAssinatura := XmlNode( cXmlInput, "Signature" )
   cBlocoIde := XmlNode( cXmlInput, "ide" )
      oNfe:cNumDoc := XmlNode( cBlocoIde, "nNF" )
      IF Len( Trim( oNfe:cNumDoc ) ) = 0
         oNfe:cErro := "Sem número de documento"
         RETURN NIL
      ENDIF
      oNfe:cNumDoc := StrZero( Val( oNfe:cNumDoc ), 9 )
      IF .NOT. Empty( XmlDate( XmlNode( cBlocoIde, "dhEmi" ) ) )
         oNfe:DataEmissao := XmlDate( XmlNode( cBlocoIde, "dhEmi" ) )
         oNfe:DataSaida   := XmlDate( XmlNode( cBlocoIde, "dhSaiEnt" ) )
      ELSE
         oNfe:DataEmissao := XmlDate( XmlNode( cBlocoIde, "dEmi" ) )
         oNfe:DataSaida   := XmlDate( XmlNode( cBlocoIde, "dSaiEnt" ) )
      ENDIF
      IF Empty( oNfe:DataSaida )
         oNfe:DataSaida := oNfe:DataEmissao
      ENDIF
      oNfe:cAmbiente := XmlNode( cBlocoIde, "tpAmb" )

   cBlocoInfAdic := XmlNode( cXmlInput, "InfAdic" )
      oNfe:InfAdicionais := XmlNode( cBlocoInfAdic, "InfCpl" )

   cBlocoEmit := XmlNode( cXmlInput, "emit" )
      oNfe:Emitente:Cnpj              := Transform( Substr( oNfe:ChaveAcesso, 7, 14 ), "@R 99.999.999/9999-99" )
      oNfe:Emitente:Nome              := Upper( XmlNode( cBlocoEmit, "xNome" ) )
      oNfe:Emitente:InscricaoEstadual := XmlNode( cBlocoEmit, "IE" )
      cBlocoEndereco := XmlNode( cBlocoEmit, "enderEmit" )
         oNfe:Emitente:Endereco   := Upper( XmlNode( cBlocoEndereco, "xLgr" ) )
         oNfe:Emitente:Numero     := XmlNode( cBlocoEndereco, "nro" )
         oNfe:Emitente:Compl      := XmlNode( cBlocoEndereco, "xCpl" )
         oNfe:Emitente:Bairro     := Upper( XmlNode( cBlocoEndereco, "xBairro" ) )
         oNfe:Emitente:CidadeIbge := XmlNode( cBlocoEndereco, "cMun" )
         oNfe:Emitente:Cidade     := Upper( XmlNode( cBlocoEndereco, "xMun" ) )
         oNfe:Emitente:Uf         := Upper( XmlNode( cBlocoEndereco, "UF" ) )
         oNfe:Emitente:Cep        := Transform( XmlNode( cBlocoEndereco, "CEP" ), "@R 99999-999" )
         oNfe:Emitente:Telefone   := XmlNode( cBlocoEndereco, "fone" )

      cBlocoDest := XmlNode( cXmlInput, "dest" )
      oNfe:Destinatario:Cnpj := Trim( XmlNode( cBlocoDest, "CNPJ" ) )
      IF Len( Trim( oNfe:Destinatario:Cnpj ) ) = 0
         oNfe:Destinatario:Cnpj := XmlNode( cBlocoDest, "CPF" )
         oNfe:Destinatario:Cnpj := Transform( oNfe:Destinatario:Cnpj, "@R 999.999.999-99" )
      ELSE
         oNfe:Destinatario:Cnpj := Transform( oNfe:Destinatario:Cnpj, "@R 99.999.999/9999-99" )
      ENDIF
      oNfe:Destinatario:Nome := Upper( XmlNode( cBlocoDest, "xNome" ) )
      oNfe:Destinatario:InscricaoEstadual := XmlNode( cBlocoDest, "IE" )
      cBlocoEndereco := XmlNode( cBlocoDest, "enderDest" )
         oNfe:Destinatario:Endereco   := Upper( XmlNode( cBlocoEndereco, "xLgr" ) )
         oNfe:Destinatario:Numero     := XmlNode( cBlocoEndereco, "nro" )
         oNfe:Destinatario:Compl      := XmlNode( cBlocoEndereco, "xCpl" )
         oNfe:Destinatario:Bairro     := Upper( XmlNode( cBlocoEndereco, "xBairro" ) )
         oNfe:Destinatario:CidadeIbge := XmlNode( cBlocoEndereco, "cMun" )
         oNfe:Destinatario:Cidade     := Upper( XmlNode( cBlocoEndereco, "xMun" ) )
         oNfe:Destinatario:Uf         := Upper( XmlNode( cBlocoEndereco, "UF" ) )
         oNfe:Destinatario:Cep        := Transform( XmlNode( cBlocoEndereco, "CEP" ), "@R 99999-999" )
         oNfe:Destinatario:Telefone   := XmlNode( cBlocoEndereco, "fone" )

   cBlocoTransporte := XmlNode( cXmlInput, "transp" )
      cBlocoTransp := XmlNode( cBlocoTransporte, "transporta" )
         oNfe:Transporte:Cnpj              := Transform( XmlNode( cBlocoTransp, "CNPJ" ), "@R 99.999.999/9999-99" )
         oNfe:Transporte:Nome              := Upper( XmlNode( cBlocoTransp, "xNome" ) )
         oNfe:Transporte:InscricaoEstadual := XmlNode( cBlocoTransp, "IE" )
         oNfe:Transporte:Endereco          := Upper( XmlNode( cBlocoTransp, "xEnder" ) )
         oNfe:Transporte:Cidade            := Upper( XmlNode( cBlocoTransp, "xMun" ) )
         oNfe:Transporte:Uf                := Upper( XmlNode( cBlocoTransp, "UF" ) )
      cBlocoVol := XmlNode( cBlocoTransporte, "vol" )
         oNfe:Transporte:Volumes:Qtde        := Val( XmlNode( cBlocoVol, "qVol" ) )
         oNfe:Transporte:Volumes:Especie     := Upper( XmlNode( cBlocoVol, "esp" ) )
         oNfe:Transporte:Volumes:Marca       := Upper( XmlNode( cBlocoVol, "marca" ) )
         oNfe:Transporte:Volumes:PesoLiquido := Val( XmlNode( cBlocoVol, "pesoL" ) )
         oNfe:Transporte:Volumes:PesoBruto   := Val( XmlNode( cBlocoVol, "pesoB" ) )
      cBlocoVeiculo := XmlNode( cBlocoTransporte, "veicTransp" )
      oNfe:Transporte:PlacaUf := Upper( XmlNode( cBlocoVeiculo, "UF" ) )
      oNfe:Transporte:Placa   := Upper( XmlNode( cBlocoVeiculo, "placa" ) )

   cBlocoTotal := XmlNode( cXmlInput, "total" )
      oNfe:Totais:IpiVal := Val( XmlNode( cBlocoTotal, "vIPI" ) )
      oNfe:Totais:IIVal  := Val( XmlNode( cBlocoTotal, "vII" ) )
      oNfe:Totais:IcmBas := Val( XmlNode( cBlocoTotal, "vBC" ) )
      oNfe:Totais:IcmVal := Val( XmlNode( cBlocoTotal, "vICMS" ) )
      oNfe:Totais:SubBas := Val( XmlNode( cBlocoTotal, "vBCST" ) )
      oNfe:Totais:SubVal := Val( XmlNode( cBlocoTotal, "vST" ) )
      oNfe:Totais:PisVal := Val( XmlNode( cBlocoTotal, "vPIS" ) )
      oNfe:Totais:CofVal := Val( XmlNode( cBlocoTotal, "vCOFINS" ) )
      oNfe:Totais:ValPro := Val( XmlNode( cBlocoTotal, "vProd" ) )
      oNfe:Totais:ValSeg := Val( XmlNode( cBlocoTotal, "vSeg" ) )
      oNfe:Totais:ValFre := Val( XmlNode( cBlocoTotal, "vFrete" ) )
      oNfe:Totais:ValOut := Val( XmlNode( cBlocoTotal, "vOutro" ) )
      oNfe:Totais:ValNot := Val( XmlNode( cBlocoTotal, "vNF" ) )

   cBlocoDetalhe := ""
   IF "<det" $ cXmlInput
      cBlocoDetalhe := Substr( cXmlInput, At( "<det", cXmlInput ) - 1 )
   ENDIF
   FOR nCont = 1 TO 1000
      cBlocoItem := XmlNode( cBlocoDetalhe, [det nItem="] + LTrim( Str( nCont ) ) + ["])
      IF Len( Trim( cBlocoItem ) ) = 0 // Se acabaram os itens
         EXIT
      ENDIF
      AAdd( oNFE:Produto, NFEProdutoClass():New() )
      cBlocoProd := XmlNode( cBlocoItem, "prod" )
         oNfe:Produto[ nCont ]:Codigo          := XmlNode( cBlocoProd, "cProd" )
         oNfe:Produto[ nCont ]:Nome            := Upper( XmlNode( cBlocoProd, "xProd" ) )
         oNfe:Produto[ nCont ]:CFOP            := Transform( XmlNode( cBlocoProd, "CFOP" ), "@R 9.9999" )
         oNfe:Produto[ nCont ]:NCM             := XmlNode( cBlocoProd, "NCM" )
         oNfe:Produto[ nCont ]:GTIN            := XmlNode( cBlocoProd, "cEAN" )
         oNfe:Produto[ nCont ]:Unidade         := Upper( XmlNode( cBlocoProd, "uCom" ) )
         oNfe:Produto[ nCont ]:Qtde            := Val( XmlNode( cBlocoProd, "qCom" ) )
         oNfe:Produto[ nCont ]:ValorUnitario   := Val( XmlNode( cBlocoProd, "vUnCom" ) )
         oNfe:Produto[ nCont ]:ValorTotal      := Val( XmlNode( cBlocoProd, "vProd" ) )
      cBlocoIpi := XmlNode( cBlocoItem, "IPI" )
         oNfe:Produto[ nCont ]:Ipi:Base        := Val( XmlNode( cBlocoIpi, "vBC" ) )
         oNfe:Produto[ nCont ]:Ipi:Aliquota    := Val( XmlNode( cBlocoIpi, "pIPI" ) )
         oNfe:Produto[ nCont ]:Ipi:Valor       := Val( XmlNode( cBlocoIpi, "vIPI" ) )
      cBlocoIcms := XmlNode( cBlocoItem, "ICMS" )
         oNfe:Produto[ nCont ]:Icms:Cst        := XmlNode( cBlocoIcms, "orig" ) + XmlNode( cBlocoIcms, "CST" )
         oNfe:Produto[ nCont ]:Icms:Base       := Val( XmlNode( cBlocoIcms, "vBC" ) )
         oNfe:Produto[ nCont ]:Icms:Reducao    := Val( XmlNode( cBlocoIcms, "vRedBC" ) )
         oNfe:Produto[ nCont ]:Icms:Aliquota   := Val( XmlNode( cBlocoIcms, "pICMS" ) )
         oNfe:Produto[ nCont ]:Icms:Valor      := Val( XmlNode( cBlocoIcms, "vICMS" ) )
         oNfe:Produto[ nCont ]:IcmsSt:Base     := Val( XmlNode( cBlocoIcms, "vBCST" ) )
         oNfe:Produto[ nCont ]:IcmsSt:Iva      := Val( XmlNode( cBlocoIcms, "pMVAST" ) )
         oNfe:Produto[ nCont ]:IcmsSt:Reducao  := Val( XmlNode( cBlocoIcms, "pRedBCST" ) )
         oNfe:Produto[ nCont ]:IcmsSt:Aliquota := Val( XmlNode( cBlocoIcms, "pICMSST" ) )
         oNfe:Produto[ nCont ]:IcmsSt:Valor    := Val( XmlNode( cBlocoIcms, "vICMSST" ) )
      cBlocoPis := XmlNode( cBlocoItem, "PIS" )
         oNfe:Produto[ nCont ]:Pis:Cst         := XmlNode( cBlocoPis, "CST" )
         oNfe:Produto[ nCont ]:Pis:Base        := Val( XmlNode( cBlocoPis, "vBC" ) )
         oNfe:Produto[ nCont ]:Pis:Aliquota    := Val( XmlNode( cBlocoPis, "pPIS" ) )
         oNfe:Produto[ nCont ]:Pis:Valor       := Val( XmlNode( cBlocoPis, "vPIS" ) )
      cBlocoCofins := XmlNode( cBlocoItem, "COFINS" )
         oNfe:Produto[ nCont ]:Cofins:Cst      := XmlNode( cBlocoCofins, "CST" )
         oNfe:Produto[ nCont ]:Cofins:Base     := Val( XmlNode( cBlocoCofins, "vBC" ) )
         oNfe:Produto[ nCont ]:Cofins:Aliquota := Val( XmlNode( cBlocoCofins, "pCOFINS" ) )
         oNfe:Produto[ nCont ]:Cofins:Valor    := Val( XmlNode( cBlocoCofins, "vCOFINS" ) )
      cBlocoComb := XmlNode( cBlocoItem, "comb" )
         oNfe:Produto[ nCont ]:Anp             := XmlNode( cBlocoComb, "cProdANP" )
      cBlocoDetalhe := Substr( cBlocoDetalhe, At( "</det", cBlocoDetalhe ) + 4 )
   NEXT

   cBlocoCobranca := XmlNode( cXmlInput, "cobr" )
   FOR nCont = 1 TO 500
      cBlocoDup := XmlNode( cBlocoCobranca, "dup" )
      IF Len( Trim( cBlocoDup ) ) = 0
         EXIT
      ENDIF
      AAdd( oNfe:Duplicata, NFEDuplicataClass():New() )
      oNfe:Duplicata[ nCont ]:Vencimento := XmlDate( XmlNode( cBlocoDup, "dVenc" ) )
      oNfe:Duplicata[ nCont ]:Valor      := Val( XmlNode( cBlocoDup, "vDup" ) )
      cBlocoCobranca := Substr( cBlocoCobranca, At( "</dup>", cBlocoCobranca ) + 3 )
   NEXT
   oNfe:Protocolo := XmlNode( cXmlInput, "nProt" )
   oNFE:Status    := XmlNode( cXmlInput, "cStat" )

   RETURN NIL
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18013
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Classe e função pra carregar XML

Mensagempor JoséQuintas » 25 Jul 2016 18:33

Depois é só acessar a variável.

? oDoc:Emitente:Nome
IF .NOT. Encontra( oDoc:Destinatario:Cnpj, "clientes", "porcnpj" )
   SELECT clientes
   APPEND BLANK
   REPLACE ;
      clientes->Nome WITH oDoc:Destinatario:Nome, ;
      clientes->Cnpj  WITH oDoc:Destinatario:Cnpj
ENDIF
 
FOR EACH oProduto IN ( oDoc:Produto )
   IF .NOT. Encontra( oProduto:Codigo, "produtos", "porcodigo" )
      SELECT produtos
      APPEND BLANK
      REPLACE ;
      produtos->Codigo WITH oProduto:Codigo, ;
      produtos->Nome WITH oProduto:Nome
   ENDIF
   IF .NOT. Encontra( oProduto:cNumDoc + oProduto:Codigo, "estoque", "docprod" )
      SELECT estoque
      APPEND BLANK
      REPLACE ;
         estoque->Produto WITH oProduto:Codigo, ;
        estoque->Qtde WITH oProduto:Qtde, ;
      estoque->ValorUnitario WITH oProduto:ValorUnitario, ;
   estoque->ValorTotal WITH oProduto:ValorTotal
NEXT

IF .NOT. Encontra( oDoc:cNumDoc, "notas", "numnf" )
   SELECT notas
   APPEND BLANK
   REPLACE ;
      notas->Numero WITH oDoc:cNumDoc, ;
      notas->DatEmi WITH oDoc:DataEmissao, ;
      notas->Valor  WITH oDoc:ValNot
ENDIF
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18013
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Classe e função pra carregar XML

Mensagempor JoséQuintas » 25 Jul 2016 18:42

Tudo no bom e tradicional modo Clipper, exceto que depois alterei pros dados da nota ficarem numa classe.
Uso desde os tempos do Clipper a leitura do XML assim.

Pensei em utilizar a classe pro caminho inverso:
O aplicativo alimentar as variáveis, e gerar o XML a partir dessa nota.
Também poderia acrescentar validações extras, pra confirmar se tem preenchimento inválido.

Comentário:
<produto>sssss</produto>

Sö usar At() pra encontrar aonde tem <produto> e </produto> e pegar o que está entre eles, usando Substr().
Nada extraordinário, ou classes de XML que só complicam.

E com o tempo, ir melhorando conforme o que for acontecendo.
Qualquer um consegue fazer.
Mas a mania de achar que XML é de coisa outro planeta, acabam recorrendo a classes complicadas pra trabalhar com XML, geralmente classes que são muito mais complicadas que o próprio XML.
XML é um texto, e todo mundo sabe trabalhar com textos.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18013
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Classe e função pra carregar XML

Mensagempor gilbertosilverio » 30 Jul 2016 14:30

Ola Jose Quintas,

Baseado neste teu exemplo, tentei ler um arquivo de retorno em xml, mais o retorno e nulo.

Por favor, o que estou fazendo errado ao tentar ler este xml.

<retConsCad versao="2.00">
<infCons>
<verAplic>SP_NFE_PL_008i2</verAplic>
<cStat>111</cStat>
<xMotivo>Consulta cadastro com uma ocorrência</xMotivo>
<UF>SP</UF>
<CNPJ>47160031000173</CNPJ>
<dhCons>2016-07-30T10:36:04-03:00</dhCons>
<cUF>35</cUF>
<infCad>
<IE>635063157119</IE>
<CNPJ>47160031000173</CNPJ>
<UF>SP</UF>
<cSit>1</cSit>
<indCredNFe>1</indCredNFe>
<indCredCTe>4</indCredCTe>
<xNome>DROGARIA TEM LTDA - EPP</xNome>
<xRegApur>NORMAL - REGIME PERIÓDICO DE APURAÇÃO</xRegApur>
<CNAE>4771701</CNAE>
<dIniAtiv>1975-07-01</dIniAtiv>
<dUltSit>1975-07-01</dUltSit>
<ender>
<xLgr>RUA CRISTIANO ANGELI</xLgr>
<nro>30</nro>
<xBairro>ASSUNCAO</xBairro>
<cMun>3548708</cMun>
<xMun>SAO BERNARDO DO CAMPO</xMun>
<CEP>09810555</CEP>
</ender>
</infCad>
</infCons>
</retConsCad>



FUNCTION LER_CONSULTA_CADASTRO()
   LOCAL aIE, aCnpj, aUF, acSit, aNome, aRegime, aEndereco, aNumero, aBairro, aCidadeIbge, aCidade, aCep
   PRIVATE cBloco_infCad, cBlocoEndere, cBloco_infCons
   PRIVATE cXmlInput:=[D:\Cnpj_47160031000173-ret-cons-cad.xml]

   cBloco_infCons := XmlNode( cXmlInput, "infCons", .t. )

   cBloco_infCad  := XmlNode( cBloco_infCons , "infCad", .t. )
      aIE         := Upper( XmlNode( cBloco_infCad,     "IE"   ) )
      aCnpj       := Transform( XmlNode( cBloco_infCad, "CNPJ" ), "@R 99.999.999/9999-99" )
      aUF         := Upper( XmlNode( cBloco_infCad,     "UF"   ) )
      acSit       := Upper( XmlNode( cBloco_infCad,     "cSit" ) )
      aNome       := Upper( XmlNode( cBloco_infCad,     "xNome" ) )
      aRegime     := Upper( XmlNode( cBloco_infCad,     "xRegApur" ) )

      cBlocoEndereco   := XmlNode( cBloco_infCad,         "ender"   ) // pesquisa o

         aEndereco     := Upper( XmlNode( cBlocoEndereco, "xLgr"    ) )
         aNumero       := XmlNode( cBlocoEndereco,        "nro"     )
         aBairro       := Upper( XmlNode( cBlocoEndereco, "xBairro" ) )
         aCidadeIbge   := XmlNode( cBlocoEndereco,        "cMun"    )
         aCidade       := Upper( XmlNode( cBlocoEndereco, "xMun"    ) )
         aCep          := Transform( XmlNode( cBlocoEndereco, "CEP" ), "@R 99999-999" )

   HWG_MSGINFO( aIE+CRLF+aCNPJ+CRLF+ aUF+CRLF+ aNOME+CRLF+ aENDERECO+CRLF+ aCEP ,[Olha o que voltou])

RETURN NIL



Grato.
gilbertosilverio
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 332
Data de registro: 18 Jan 2009 09:39
Cidade/Estado: Ribeirao Pires - SP
Curtiu: 1 vez
Mens.Curtidas: 23 vezes

Classe e função pra carregar XML

Mensagempor gilbertosilverio » 30 Jul 2016 16:22

Ola Jose,

Esquece, ja achei meu erro, esqueci de abrir o arquivo como MEMOREAD()...

Muito pratico este teu exemplo.

Grato.
gilbertosilverio
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 332
Data de registro: 18 Jan 2009 09:39
Cidade/Estado: Ribeirao Pires - SP
Curtiu: 1 vez
Mens.Curtidas: 23 vezes

Classe e função pra carregar XML

Mensagempor JoséQuintas » 30 Jul 2016 17:36

Deixei como parte do projeto.
Fazem anos que penso em mexer nesses nomes internos, mas sempre deixo pra depois... rs

https://github.com/JoseQuintas/sefazclass

Isso que postei está em ze_SpedXmlClass.prg

Uso pra importar XMLs de fornecedores.

Em um determinado cliente, uso pra importar TODOS os XMLs, até os próprios.
O dono não quer abrir mão do aplicativo de notas que fez, então importo toda informação dos XMLs pra gerar arquivos pro governo.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18013
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Classe e função pra carregar XML

Mensagempor fladimir » 30 Jul 2016 19:58

Legal José, parabéns... Talvez essa ideia pode ser usada pelo Toledo ou outros colegas q estão trabalhando em baixar o XML sem o certificado e ler o HTML e montar o XML correto?
Sun Tzu há mais de três mil anos cita nas epígrafes de seu livro “A Arte da Guerra“:

“Concentre-se nos pontos fortes, reconheça as fraquezas, agarre as oportunidades e proteja-se contra as ameaças”.
“Se não é vantajoso, nunca envie suas tropas; se não lhe rende ganhos, nunca utilize seus homens; se não é uma situação perigosa, nunca lute uma batalha precipitada”
.


Até 2017    Desktop Console [ Legado ] Harbour | MinGW | DBF | CDX | FastReport | MySQL


Novos Projetos:

   Desktop Visual           Windev Desktop
   Celular Android/iOS   Windev Mobile
   WEB                            Windev Web


Sejamos gratos a Deus.
Avatar de usuário

fladimir
Colaborador

Colaborador
 
Mensagens: 2434
Data de registro: 15 Nov 2006 19:21
Curtiu: 28 vezes
Mens.Curtidas: 157 vezes

Classe e função pra carregar XML

Mensagempor JoséQuintas » 30 Jul 2016 22:42

Há pouco tempo vi na hbnfe que a impressão da Danfe usa algo assim, mas usando variáveis HASH.

E tem um componente de NFE, acho que é o flexdocs, que tem uma classe nesse estilo pra gerar o XML, que alguns usam por acharem mais fácil desse jeito. (a classe com as informações da NFE).

O que comentei em outro tópico foi sobre isso: pegar essa classe, ou uma nova, e utilizá-la pra tudo.
É apenas uma classe com variáves da NFE, com toda informação, então:
- Daria pra preencher o conteúdo, e gerar TXT ou XML ou ACBR ou outro
- Daria pra usar pra emitir o Danfe
- Daria pra juntar todas as validações que nós temos, e aplicar na informação da classe: validar NCM, CFOP, CST, regras fiscais, regras da NFE, regras do governo, etc. etc. etc. ficando padrão pra todo mundo, e pra qualquer aplicativo, o que permitirá mais colaboração nessas checagens.
- Daria pra usar ANTES de emitir a nota, pra toda validação

Seria facilidade pra todos, porque não dependeria de formato de base de dados, ou outra coisa.
E muitas vezes a gente não tem tempo de conferir tudo isso, então mais gente usando acabaria nos ajudando, de uma forma ou de outra.
É só uma idéia, pelo menos por enquanto.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18013
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Classe e função pra carregar XML

Mensagempor NiltonGM » 06 Set 2016 19:47

José,

Na linha 70 do XmlToDoc() não poderia ficar assim?
CASE Len( oDoc:cErro ) != 0
oDoc:cTipoDoc := "XX"
oDoc:cEvento := "XXXXXX"
CASE Len( oDoc:ChaveAcesso ) != 44
...
e eliminar o if após o END CASE na linha 90
IF Len( oDoc:cErro ) != 0
oDoc:cTipoDoc := "XX"
oDoc:cEvento := "XXXXXX"
ENDIF
Ou tem algum problema q não estou enxergando?
Tentei adaptar suas funções mas estavam faltando as funções:
XMLNODE(), XMLELEMENT() e XMLDATE(), a xmlNode achei num post seu no forum mas ademais não achei, onde vc postou pois elas não fazem parte de alguma biblioteca do Harbour.
Por favor aguardo sua ajuda pois estou no meio de uma aplicação e preciso ler XML de NFes e achei suas rotinas muito boas.
Obrigado.
Nilton Medeiros
nilton@sistrom.com.br
Avatar de usuário

NiltonGM
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 393
Data de registro: 05 Jun 2014 23:47
Cidade/Estado: Caieiras/SP
Curtiu: 249 vezes
Mens.Curtidas: 24 vezes

Classe e função pra carregar XML

Mensagempor JoséQuintas » 06 Set 2016 23:10

As outras rotinas podem preencher o oDoc:cErro com outro erro específico.
Se remover a linha em questão, o texto pode acabar sendo removido e trocado por outro.

A rotina atualizada, com as outras funções, está em SefazClass.

https://github.com/JoseQuintas/sefazclass
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18013
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Classe e função pra carregar XML

Mensagempor lugab » 07 Set 2016 21:29

Pessoal, help.

Aproveito o tema desse tópico do Quintas, pra tirar essa dúvida:

Que programa externo (ou até mesmo um fonte interno) eu devo usar para exibir um arquivo XML (uma nfe)
na tela do meu programa clipper compilado com xHarbour + Hwgui + Gtwvw ?

Tenho visto aqui no forum só contribuições para recuperar os campos dos XML

Grato
lugab
lugab
Colaborador

Colaborador
 
Mensagens: 843
Data de registro: 19 Mai 2009 15:58
Curtiu: 126 vezes
Mens.Curtidas: 38 vezes

Classe e função pra carregar XML

Mensagempor NiltonGM » 08 Set 2016 11:07

Obrigado Zeh, valeu mesmo, vou adaptar as minhas rotinas.
Nilton Medeiros
nilton@sistrom.com.br
Avatar de usuário

NiltonGM
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 393
Data de registro: 05 Jun 2014 23:47
Cidade/Estado: Caieiras/SP
Curtiu: 249 vezes
Mens.Curtidas: 24 vezes

Próximo



Retornar para Projeto hbNFe

Quem está online

Usuários vendo este fórum: Google Adsense [Bot] e 6 visitantes


Ola Amigo, espero que meu site e forum tem lhe beneficiado, com exemplos e dicas de programacao.
Entao divulgue o link da Doacao abaixo para seus amigos e redes sociais ou faça uma doacao para o site forum...
MUITO OBRIGADO PELA SUA DOACAO!
Faça uma doação para o forum
cron
v
Olá visitante, seja bem-vindo ao Fórum Clipper On Line!
Efetue o seu login ou faça o seu Registro