Página 2 de 2

Percorrer um XML

Enviado: 23 Nov 2016 09:26
por janio
Jairo disse:
Jânio, acho que o link que você postou não tem nada a ver com o que está sendo discutido aqui não. Aqui está sendo discutido a leitura e extração de informação do XML, por exemplo: ler o XML de compra, e verificar se houve alteração no valor de custo do item, atualizar estoque pegando a quantidade, se o produto não está cadastrado cadastrar e já com os dados fiscais com base no CFOP e CST/CSOSN, etc...
Tem sim, Jairo! O tópico se refere a mesma função que o Quintas já mencionou neste tópico aqui!
JoseQuintas disse:
XmlNode() é apenas uma função.

Tem uma classe na sefazclass pra ajudar no que quer fazer.

Importante:
pra entender um pouco o uso de XmlNode(), vá direto na FUNCTION XmlToDocNfeEmi().
Ela faz bastante uso de XmlNode()

https://github.com/JoseQuintas/sefazcla ... lClass.prg

De uma forma geral, essa classe na SefazClass é com tudo pronto, pra fazer algo assim:

Expandir visualizacaoVer codigo
1 oDoc := XmlToDoc( MemoRead( "arquivo.xml" ) )
2 ? oDoc:Emitente:Nome
3 ? oDoc:Emitente:CNPJ
4
Mim refiro a FUNCTION XmlToDocNfeEmi da Classe do Quintas! NUNCA VI ALGO MAIS FACIL PRA EXTRAÇÃO DE INFORMAÇÕES DE XML DE NFE!

Eh so baixar a Classe do Quintas e fazer pequenos ajustes de dependências, e pronto!

Janio

Percorrer um XML

Enviado: 23 Nov 2016 09:32
por janio
Exemplo de uso da Classe do Quintas:

Código: Selecionar todos

	oNfe := XmlToDoc( MemoRead( cArq ) ) 

   vCHVNFE     := oNfe:ChaveAcesso
   vVLRNOT     := oNfe:Totais:ValNot
   vVLRMER     := oNfe:Totais:ValPro
   vVLRFRT     := oNfe:Totais:ValFre     
   vBASICM     := oNfe:Totais:IcmBas    
   vVLRICM     := oNfe:Totais:IcmVal     
   vBSICST     := oNfe:Totais:SubBas     
   vVRICST     := oNfe:Totais:SubVal     
   vVLRIPI     := oNfe:Totais:IpiVal     
   vVLROUT     := oNfe:Totais:ValOut     
   vVLRDES     := oNfe:Totais:ValDes     
   vVLRSEG     := oNfe:Totais:ValSeg
Pegando os produtos:

Código: Selecionar todos

FOR EACH oProduto IN ( oNfe:Produto ) 

	vNomPrd := oProduto:Nome
	nCodPrd := oProduto:Codigo
   vCodBar := oProduto:GTIN
   xCodBar := oProduto:GTINt
   vQTDPRD := oProduto:Qtde
   vVLRUNI := oProduto:ValorUnitario
   vVLRITM := oProduto:ValorTotal
   dCodNCM := oProduto:NCM
   dCdCest := oProduto:CEST
   dVLRDES := oProduto:ValorDesconto
   dCFOPSD := oProduto:CFOP

	dBAICST := oProduto:IcmsSt:Base
	dALICST := oProduto:IcmsSt:Aliquota
	dVRICST := oProduto:IcmsSt:Valor                               
   dCODCST := oProduto:Icms:Cst

   dVLRIPI := oProduto:Ipi:Valor
   dALQIPI := oProduto:Ipi:Aliquota
		
NEXT 
Tem algo mais fácil que isso?
:)) :))

Percorrer um XML

Enviado: 23 Nov 2016 09:39
por Mario Mesquita
Bom dia a todos.

Estranho, montei o post mas não enviou. Tentando de novo.

Código: Selecionar todos


FUNCTION Importa_Pedidos()
LOCAL xArq    := ALLTRIM(Frm_ImpPed.Txt_ArqPed.Value), ;
      oXMLPed := TXmlDocument():new(),                 ;
		oXMLNode,                                        ;
		xVal    := "",                                   ;
		vLin    := {},                                   ;
		vItems  := {}

vItems := { "cd_origem",                ;
            "ds_bairro",                ;
            "ds_complemento_A",         ;
            "ds_complemento_B",         ;
            "ds_logradouro",            ;
            "ds_obs_ato",               ;
            "ds_pd_ds_tipo_doc_ext",    ;
            "ds_pd_ds_tipo_pedido_ext", ;
            "ds_pd_finalidade_ext",     ;
            "ds_pd_status_pedido_ext",  ;
            "ds_pd_tipo_ato_ext",       ;
            "ds_requerente",            ;
            "dt_ato",                   ;
            "dt_nascimento",            ;
            "dt_pagamento",             ;
            "dt_pedido",                ;
            "dt_repasse",               ;
            "dt_sla",                   ;
            "dt_status",                ;
            "id_CERP",                  ;
            "id_CERP_original",         ;
            "id_pd_tipo_ato",           ;
            "id_requisicao",            ;
            "id_servico",               ;
            "nm_busca",                 ;
            "nm_livro",                 ;
            "nm_mae",                   ;
            "nm_natureza_ato",          ;
            "nm_pai",                   ;
            "nu_RGI",                   ;
            "nu_aleatorio_Original",    ; 
            "nu_ato",                   ;
            "nu_cpf_cnpj",              ;
            "nu_cpf_cnpj_busca",        ;
            "nu_folha",                 ;
            "nu_logradouro",            ;
            "nu_numero_A",              ; 
            "nu_numero_B",              ;
            "nu_pedido",                ;
            "nu_requisicao",            ;
            "nu_selo_Original",         ;
            "nu_valor_total",           ;
            "tp_logradouro"             }
		
vPed := {}  // Zera / inicializa o vetor que vai encher o grid.		
//msginfo('arq: '+xarq)
oXMLPed:read( MemoRead(xArq) )  // Careega o XML selecionado.

oXMLNode := oXMLPed:findFirst() // Vai ao início do XML.
//msginfo('first: '+oXMLNode:cName)
Frm_ImpPed.Lbl_Lendo.Value := oXMLNode:cName

oXMLNode := oXMLPed:findFirst("listarPedidos")  // Vai ao inicio dos pedidos, indicados pela tag.
//msginfo('listar: '+oXMLNode:cName)
Frm_ImpPed.Lbl_Lendo.Value := oXMLNode:cName

// Monta vetor de pedidos //
oXMLNode := oXMLPed:findFirst("Pedido")  // Posiciona no primeiro pedido.
msginfo('pedido: '+oXMLNode:cName)
Frm_ImpPed.Lbl_Lendo.Value := oXMLNode:cName

// Se ecnontrou pedidos, prepara o vetor para o grid e posterior gravação.
IF oXMLNode # NIL
   WHILE oXMLNode # NIL
     vLin := ARRAY(LEN(vItems)) // Para criar uma linha com todos os elementos.
     AFILL(vLin, " ")
     //AADD( vPed, vLin )         // Carrega o vetor de pedidos com uma nova linha.
     Frm_ImpPed.Grid_1.AddItem( vLin )  // Carrega o vetor de pedidos com uma nova linha.
     oXMLNode := oXMLPed:findNext()
   END
ELSE
   MSGINFO("SEM PEDIDOS A IMPORTAR NESSE XML.")  // Se não encontrou a tag "pedido", indica não haver pedidos no XML.
	RETURN NIL
ENDIF   

//oXMLNode := oXMLPed:findFirst(cd_origem")
//oXMLNode := oXMLPed:findFirst("ds_pd_ds_tipo_pedido_ext")
//oXMLNode := oXMLPed:findFirst("ds_pd_status_pedido_ext")
//msginfo('nome campo: '+oXMLNode:cName)

// Varredura do XML, buscando cada elemento do pedido para gravar no vetor de pedidos.

FOR w = 1 TO LEN(vItems)
    FOR k = 1 TO Frm_ImpPed.Grid_1.ItemCount  //LEN(vPed)
        oXMLNode := oXMLPed:findFirst(vItems[w])  // Primeira ocorrência do elemento.
        WHILE oXMLNode # NIL
          xVal := Pega_Tag(@oXMLNode,vItems[w])
          //msginfo('Linha '+str(k,3,0)+': Valor item posição '+str(w,2,0)+' => '+vItems[w]+': '+xVal)
          //Frm_ImpPed.Lbl_Lendo.Value := 'Linha '+str(k,3,0)+': Valor item posição '+str(w,2,0)+' => '+vItems[w]+': '+xVal

          //vPed[k,w] := xVal  // Coloca o valor do elemento no grid.
          Frm_ImpPed.Grid_1.Cell(k,w) := xVal // Carrega o vetor de pedidos com uma nova linha.
          
      	 oXMLNode := oXMLPed:findNext()
        END
    NEXT    
NEXT
Frm_ImpPed.Grid_1.Refresh

RETURN NIL

Vamos ver se vai. Aí comento o que fiz.

Percorrer um XML

Enviado: 23 Nov 2016 09:44
por Mario Mesquita
Foi.

Não reparem a bagunça do código. Coloquei a estrutura do XML que quero ler no vetor vItems, pois não consegui pegar o nome pelos atributos da Classe. Talvez por não estudar e testar o suficiente. Como isso é meio uma emergência, funcionou e isso me resolve por hora.

Curioso que a varredura do XML não é "horizontal", por "linha" como um registro de tabela de dados. Então fiz daquele jeito. Primeiro montado o vetor do Grid com os elementos em branco e depois preenchendo.

Deve ter uma forma mais elegante de fazer mas funcionou e posso ira adiante. Esse trabalho está cheio de coisas que não domino como WebService, por exemplo. Então se funcionar, tô soltando foguete, rs

Espero que ajude a vcs.

Abraço,
Mario.

Percorrer um XML

Enviado: 23 Nov 2016 09:50
por Mario Mesquita
Melhor colocar o XML pra ilustrar os testes.

Código: Selecionar todos

<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<listarPedidos>
<Pedido>
<cd_origem/>
<ds_bairro>                    </ds_bairro>
<ds_complemento_A/>
<ds_complemento_B/>
<ds_logradouro/>
<ds_obs_ato/>
<ds_pd_ds_tipo_doc_ext>Eletrônico</ds_pd_ds_tipo_doc_ext>
<ds_pd_ds_tipo_pedido_ext>Certidão Criminal 20 anos</ds_pd_ds_tipo_pedido_ext>
<ds_pd_finalidade_ext/>
<ds_pd_status_pedido_ext>EM EXECUÇÃO CARTÓRIO</ds_pd_status_pedido_ext>
<ds_pd_tipo_ato_ext>Busca Pessoal</ds_pd_tipo_ato_ext>
<ds_requerente>Priscila Roberta da Silva</ds_requerente>
<dt_ato>1900-01-01T00:00:00</dt_ato>
<dt_nascimento/>
<dt_pagamento>2016-11-17T00:00:00</dt_pagamento>
<dt_pedido>2016-11-17T10:34:52.76</dt_pedido>
<dt_repasse/>
<dt_sla>2016-11-22T00:00:00</dt_sla>
<dt_status>2016-11-17T15:24:48.633</dt_status>
<id_CERP>baf08186-af2b-4658-9e4e-ca2054db7060</id_CERP>
<id_CERP_original/>
<id_pd_tipo_ato>114</id_pd_tipo_ato>
<id_requisicao>538</id_requisicao>
<id_servico>728</id_servico>
<nm_busca>PRISCILA</nm_busca>
<nm_livro/>
<nm_mae>Não Informado</nm_mae>
<nm_natureza_ato/>
<nm_pai>Não Informado</nm_pai>
<nu_RGI/>
<nu_aleatorio_Original/>
<nu_ato/>
<nu_cpf_cnpj>05760556703</nu_cpf_cnpj>
<nu_cpf_cnpj_busca>88834382803</nu_cpf_cnpj_busca>
<nu_folha/>
<nu_logradouro/>
<nu_numero_A/>
<nu_numero_B/>
<nu_pedido>201611172</nu_pedido>
<nu_requisicao>201611171</nu_requisicao>
<nu_selo_Original/>
<nu_valor_total>99.5400</nu_valor_total>
<tp_logradouro/>
</Pedido>
<Pedido>
<cd_origem/>
<ds_bairro>                    </ds_bairro>
<ds_complemento_A/>
<ds_complemento_B/>
<ds_logradouro/>
<ds_obs_ato/>
<ds_pd_ds_tipo_doc_ext>Eletrônico</ds_pd_ds_tipo_doc_ext>
<ds_pd_ds_tipo_pedido_ext>Certidão Cível 20 anos</ds_pd_ds_tipo_pedido_ext>
<ds_pd_finalidade_ext>Junta comercial</ds_pd_finalidade_ext>
<ds_pd_status_pedido_ext>PAGAMENTO REALIZADO</ds_pd_status_pedido_ext>
<ds_pd_tipo_ato_ext>Busca Pessoal</ds_pd_tipo_ato_ext>
<ds_requerente>Mario Reina de Mesquita Neto</ds_requerente>
<dt_ato>1900-01-01T00:00:00</dt_ato>
<dt_nascimento/>
<dt_pagamento>2016-11-17T00:00:00</dt_pagamento>
<dt_pedido>2016-11-17T15:21:46.277</dt_pedido>
<dt_repasse/>
<dt_sla>2016-11-22T00:00:00</dt_sla>
<dt_status>2016-11-17T16:18:05.323</dt_status>
<id_CERP>4bc4fd42-2bcb-416c-bcd1-b27260d96dd3</id_CERP>
<id_CERP_original/>
<id_pd_tipo_ato>114</id_pd_tipo_ato>
<id_requisicao>541</id_requisicao>
<id_servico>728</id_servico>
<nm_busca>jose carlos</nm_busca>
<nm_livro/>
<nm_mae>mae</nm_mae>
<nm_natureza_ato/>
<nm_pai>Não Informado</nm_pai>
<nu_RGI/>
<nu_aleatorio_Original/>
<nu_ato/>
<nu_cpf_cnpj>80086462768</nu_cpf_cnpj>
<nu_cpf_cnpj_busca>59561432749</nu_cpf_cnpj_busca>
<nu_folha/>
<nu_logradouro/>
<nu_numero_A/>
<nu_numero_B/>
<nu_pedido>2016111714</nu_pedido>
<nu_requisicao>2016111713</nu_requisicao>
<nu_selo_Original/>
<nu_valor_total>99.5400</nu_valor_total>
<tp_logradouro/>
</Pedido>
<Pedido>
<cd_origem/>
<ds_bairro>                    </ds_bairro>
<ds_complemento_A/>
<ds_complemento_B/>
<ds_logradouro/>
<ds_obs_ato/>
<ds_pd_ds_tipo_doc_ext>Eletrônico</ds_pd_ds_tipo_doc_ext>
<ds_pd_ds_tipo_pedido_ext>Certidão Criminal 20 anos</ds_pd_ds_tipo_pedido_ext>
<ds_pd_finalidade_ext/>
<ds_pd_status_pedido_ext>EM EXECUÇÃO CARTÓRIO</ds_pd_status_pedido_ext>
<ds_pd_tipo_ato_ext>Busca Pessoal</ds_pd_tipo_ato_ext>
<ds_requerente>Priscila Roberta da Silva</ds_requerente>
<dt_ato>1900-01-01T00:00:00</dt_ato>
<dt_nascimento/>
<dt_pagamento>2016-11-17T00:00:00</dt_pagamento>
<dt_pedido>2016-11-17T15:42:32.737</dt_pedido>
<dt_repasse/>
<dt_sla>2016-11-22T00:00:00</dt_sla>
<dt_status>2016-11-17T16:11:53.473</dt_status>
<id_CERP>43802b00-3d25-47b7-92b3-08c267b6754f</id_CERP>
<id_CERP_original/>
<id_pd_tipo_ato>114</id_pd_tipo_ato>
<id_requisicao>543</id_requisicao>
<id_servico>728</id_servico>
<nm_busca>PRISCILA</nm_busca>
<nm_livro/>
<nm_mae>Não Informado</nm_mae>
<nm_natureza_ato/>
<nm_pai>Não Informado</nm_pai>
<nu_RGI/>
<nu_aleatorio_Original/>
<nu_ato/>
<nu_cpf_cnpj>05760556703</nu_cpf_cnpj>
<nu_cpf_cnpj_busca>88834382803</nu_cpf_cnpj_busca>
<nu_folha/>
<nu_logradouro/>
<nu_numero_A/>
<nu_numero_B/>
<nu_pedido>2016111721</nu_pedido>
<nu_requisicao>2016111720</nu_requisicao>
<nu_selo_Original/>
<nu_valor_total>99.5400</nu_valor_total>
<tp_logradouro/>
</Pedido>
</listarPedidos>
Sds,
Mario.

Percorrer um XML

Enviado: 24 Nov 2016 10:53
por Jairo Maia
Olá Pessoal,

Obrigado pelas respostas.

Rubens, valeu. Numa rápida olhada em seu código, estou propenso a acreditar que já está quase tudo pronto o que preciso. Obrigado.

Percorrer um XML

Enviado: 24 Nov 2016 12:19
por rubens
Jairo...

To implementando isso aí com a classe do Quintas...
Realmente é muito fácil de usar ela... e vai economizar muitas linhas e controle... quando estiver pronto já em Minigui/Bcc eu posto aqui... Incluisve escolhendo se baixa o xml ou escolhe o xml numa pasta.

Rubens

Percorrer um XML

Enviado: 24 Nov 2016 14:17
por JoséQuintas
Mário, nesse caso esta se referindo a um XML diferente de nota fiscal.

Do meio jeito eu faria assim:
Nota: aproveitando o array que criou pra outra leitura

Código: Selecionar todos

aPedidoList := MultipleNodeToArray( cXml, "pedido" )
FOR EACH oPedido IN aPedidoList
   FOR EACH cNodeName IN aNodeList
      ? cNodeName, XmlNode( oPedido, cNodeName )
   NEXT
NEXT

Percorrer um XML

Enviado: 25 Nov 2016 09:51
por Mario Mesquita
Bom dia a todos.

Quintas, seria pela sua classe? Muito interessante, posso baixar pra testar e adequar ao que preciso.

O que fiz aqui ainda deu um errinho mas quebrou o galho. Vou até modificar e dispensar o grid, gravando direto o vetor na tabela.

Mas como disse, é uma oportunidade de ter um utilitário funcional e didático ao mesmo tempo. Sou meio burro com classes de objetos, apesar de ter lidado bem com elas em um curso de Java.

Abraço,
Mario.

Percorrer um XML

Enviado: 25 Nov 2016 09:57
por JoséQuintas
A classe é pra trabalhar com nota fiscal eletrônica.
Junto com a classe, tem um arquivo com funções pra XML - ZE_XMLFUNC.PRG
Nesse fonte vai encontrar essas funções que usei.

Percorrer um XML

Enviado: 25 Nov 2016 10:06
por JoséQuintas
A XmlNode(), que basicamente pegaria de <tag> até </tag>
cValor := XmlNode( cXml, "nome" )

Código: Selecionar todos

FUNCTION XmlNode( cXml, cNode, lComTag )

   LOCAL nInicio, nFim, cResultado := ""

   hb_Default( @lComTag, .F. )
   nInicio := At( "<" + cNode, cXml )
   // a linha abaixo é depois de pegar o início, senão falha
   IF " " $ cNode
      cNode := Substr( cNode, 1, At( " ", cNode ) - 1 )
   ENDIF
   IF nInicio != 0
      IF ! lComTag
         nInicio := nInicio + Len( cNode ) + 2
         IF nInicio != 1 .AND. Substr( cXml, nInicio - 1, 1 ) != ">" // Quando tem elementos no bloco
            nInicio := hb_At( ">", cXml, nInicio ) + 1
         ENDIF
      ENDIF
      nFim := hb_At( "</" + cNode + ">", cXml, nInicio )
      IF nFim != 0
         nFim -=1
         IF lComTag
            nFim := nFim + Len( cNode ) + 3
         ENDIF
         cResultado := Substr( cXml, nInicio, nFim - nInicio + 1 )
      ENDIF
   ENDIF

   RETURN cResultado
a MultipleNodeToArray(), que repete a XmlNode() pra cada ocorrência de um mesmo node. Poderia ser <pedido 1> <pedido 2>, não está preso a apenas < pedido>
aNodeList := MultipleNodeToArray( cXml, "pedido" )

Código: Selecionar todos

FUNCTION MultipleNodeToArray( cXml, cNode )

   LOCAL aNodes := {}

   DO WHILE "<" + cNode + " " $ cXml .OR. "<" + cNode + ">" $ cXml
      Aadd( aNodes , XmlNode( cXml , cNode ) )
      IF ! "</" + cNode $ cXml
         cXml := ""
      ELSE
         cXml := Substr( cXml, At( "</" + cNode + ">", cXml ) + Len( "</" + cNode + ">" ) )
      ENDIF
   ENDDO

   RETURN aNodes
XmlHash(), particularmente não gosto de variável HASH, mas também criei esta, pega vários nodes e já coloca em variável hash:
oCampos := XmlToHash( cXml, { "numero", "nome", "endereco", "cep" } )
ou
oCampos := XmlToHash( cXml, { "numero", "nome", "endereco" }, oCampos ) // pra acumular no mesmo array
Depois:
? oCampos[ "numero" ], oCampos[ "nome" ], oCampos[ "endereço" ]

Código: Selecionar todos

FUNCTION XmlToHash( cXml, aTagList, oVar )

   LOCAL oElement

   oVar := iif( oVar == NIL, hb_Hash(), oVar )

   FOR EACH oElement IN aTagList
      oVar[ oElement ] := XmlNode( cXml, oElement )
   NEXT

   RETURN oVar

Até que são funções relativamente simples, mas resolvem muita coisa.

Percorrer um XML

Enviado: 26 Nov 2016 09:17
por Mario Mesquita
Bom dia a todos.

Quintas, muitíssimo obrigado por disponibilizar seus códigos. Serão úteis a todos, com certeza. O XML embora seja simples, tem lá seus macetes. E soluções simples são sempre as melhores.

Abraço e saudações,
Mario.