Ler XML com TAGS dentro de TAG com TXMLDocument()

Projeto [x]Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

Avatar do usuário
ANDRIL
Usuário Nível 5
Usuário Nível 5
Mensagens: 1297
Registrado em: 06 Jul 2004 00:44
Contato:

Ler XML com TAGS dentro de TAG com TXMLDocument()

Mensagem por ANDRIL »

Estou tentando fazer uma integração com um empresa, a api responde somente em XML e não estou conseguindo pegar tags especificas obedecendo os NÓS.
O xml bem simples
<pedido>
<nroPedido>2464</nroPedido>
<ValorTotal>65.98</ValorTotal>
<DescricaoPagamento>Dinheiro</DescricaoPagamento>
<DataHoraPedido>2021-05-18 15:43:37</DataHoraPedido>
<itens>
<item>
<Codigo>3592</Codigo>
<Descricao>Mussarela c/ alho gratinado</Descricao>
<Quantidade>1</Quantidade>
<ValorUnit>37.99</ValorUnit>
<adicionais>
<adicional>
<Codigo>960</Codigo>
<Descricao>Borda cheddar</Descricao>
<Quantidade>1</Quantidade>
<ValorUnit>0.00</ValorUnit>
</adicional>
<adicional>
<Codigo>962</Codigo>
<Descricao>Mussarela</Descricao>
<Quantidade>1</Quantidade>
<ValorUnit>0.00</ValorUnit>
</adicional>
</adicionais>
</item>
<item>
<Codigo>3593</Codigo>
<Descricao>Calabresa</Descricao>
<Quantidade>1</Quantidade>
<ValorUnit>27.99</ValorUnit>
<adicionais>
<adicional>
<Codigo>961</Codigo>
<Descricao>Borda catupiry</Descricao>
<Quantidade>1</Quantidade>
<ValorUnit>0.00</ValorUnit>
</adicional>
<adicional>
<Codigo>963</Codigo>
<Descricao>Milho</Descricao>
<Quantidade>1</Quantidade>
<ValorUnit>0.00</ValorUnit>
</adicional>
</adicionais>
</item>
</pedido>
Aqui faço a procura pela tag <adicionais> acho a primeira e logo em seguindafaço um loop obtendo os valores, o problema é que esta retornando dados dos dois itens, ou seja, 4 tags <adicional> estão sendo lidas para o primeiro item, não sei como respeitar a leitura apenas dentro de cada item. Ele tá lendo de todo o XML.

Código: Selecionar todos

cStr="arquivo.xml"

oXML := TXMLDocument():New( cStr, HBXML_STYLE_NOESCAPE )
	IF oXML:nError != HBXML_ERROR_NONE
		alert( oXML:nError )
		RETURN 
	ENDIF

oAdicional:= oXML:findfirst( "adicional" )
DECLARE _aAdc[4]
DO WHILE .T. // comeco dos adicionais
oIteratorAdc := TXmlIterator():New( oAdicional)

	DO WHILE .T.
	   oCurrentAdc := oIteratorAdc:Next()
		IF oCurrentAdc == NIL
			EXIT
		ENDIF		
		IF oCurrentAdc:cName == "Codigo"  //1
			_var = se(oCurrentAdc:cData)  
			_aAdc[1] = val(_var)

			ELSEIF oCurrentAdc:cName == "Descricao" //2
			_var = se(oCurrentAdc:cData)  
			_aAdc[2] = _var

			ELSEIF oCurrentAdc:cName == "Quantidade"  //3
			_var = se(oCurrentAdc:cData)  
			_aAdc[3] = val(_var)

			ELSEIF oCurrentAdc:cName == "ValorUnit"  //4
			_var = se(oCurrentAdc:cData)  
			_aAdc[4] = val(_var)

		ENDIF													


	ENDDO //adicional

	_textoadc=se(_aAdc[3])+"x "+se(_aAdc[2])+chr(13)+chr(10)
	wait"saiu de um adicional"

oAdicional := oXML:findnext( "adicional" )
If oAdicional == NIL
	exit
EndIf
ENDDO //adicionais
Peguei o exemplo postado pelo Itamar e adaptei, mas não consigo obter o resultado que desejo. Para comparar a um xml de NFE é como se em um XML tivesse mais de uma nota onde cada uma tem o campo <det>, queria pegar os valores por nota.
Não sei que consegui passar o que preciso.
Clipper 5.2e / Blinker 5.1 / Harbour 3.2 / GTwvg
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Ler XML com TAGS dentro de TAG com TXMLDocument()

Mensagem por Itamar M. Lins Jr. »

Olá!
O segredo é jogar fora o que já pegou.
Senão cai sempre no primeiro.
Vai cortando o bloco/string.
cBloco := substr(cBloco,nInicio+nFim)
Aqui é feito o corte

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Ler XML com TAGS dentro de TAG com TXMLDocument()

Mensagem por Itamar M. Lins Jr. »

Ola!
Sim, confundi com HTML, XML é mais fácil.
Vou ver aqui o código.

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Ler XML com TAGS dentro de TAG com TXMLDocument()

Mensagem por Itamar M. Lins Jr. »

Olá!
Neste caso especifico desse XML é melhor cortar.

Usar:
cTagItem:= 'Item'
cTagItem := XmlNode( cStr , cTagItem)

E cortar, não usar a classe TXMLDocument

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
ANDRIL
Usuário Nível 5
Usuário Nível 5
Mensagens: 1297
Registrado em: 06 Jul 2004 00:44
Contato:

Ler XML com TAGS dentro de TAG com TXMLDocument()

Mensagem por ANDRIL »

Itamar M. Lins Jr. escreveu:cTagItem:= 'Item'
cTagItem := XmlNode( cStr , cTagItem)
Esta função XmlNode é do Quintas ou tem no harbour? Ela consegue abstrair tags dentro de múltiplos níveis, exemplo:
<item>
<adicionais>
<adicional>
</adicional>
</adicionais>
</item>

<item>
<adicionais>
<adicional>
</adicional>
</adicionais>
</item>

<item>
<adicionais>
<adicional>
</adicional>
</adicionais>
</item>
Quando busco por <adicional> tenho pegar tudo que esta entre a tag <item></item> da cor azul apenas, depois fazer para a cor laranja e por ultimo da cor verde. Acontece que quando procuro, acabo pegando os demais, precisa obedecer a hierarquia. É isso que tá pegando e ainda não consegui.
Clipper 5.2e / Blinker 5.1 / Harbour 3.2 / GTwvg
Avatar do usuário
ANDRIL
Usuário Nível 5
Usuário Nível 5
Mensagens: 1297
Registrado em: 06 Jul 2004 00:44
Contato:

Ler XML com TAGS dentro de TAG com TXMLDocument()

Mensagem por ANDRIL »

Achei a solução aqui mesmo no fórum Fivewin postado pelo colega Kapiaba. Funções que transformam o XML em HASH e facilita e muito o acesso aos dados. São estas: mxmlLoadString(), mxmlFindElement(), mxmlWalkNext(), mxmlGetType(), mxmlGetText(), mxmlGetElement(), mxmlGetNextSibling(). Mais funções digite no prompt hbmk2 -find mxml

Tópico contendo o código de exemplo
https://pctoledo.org/forum/viewto ... =2&t=16692

Muito obrigado pela ajuda.
Clipper 5.2e / Blinker 5.1 / Harbour 3.2 / GTwvg
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Ler XML com TAGS dentro de TAG com TXMLDocument()

Mensagem por Itamar M. Lins Jr. »

Olá!
Blz, estou atarefado, depois vou olhar com calma.
Na verdade é do Rafa Carmona o exemplo, mas a informação é que é importante que o Kapiaba trouxe.

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Ler XML com TAGS dentro de TAG com TXMLDocument()

Mensagem por JoséQuintas »

XmlNode() é do Quintas...rs
Tem também MultipleNodeToArray() para casos igual a dos itens.

Um exemplo de uso está na própria SefazClass, pra extrair dados de nota fiscal e outros.

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

Exemplos:

Código: Selecionar todos

cBlocoTransporte := XmlNode( cXmlInput, "transp" )
      cBlocoTransp := XmlNode( cBlocoTransporte, "transporta" )
         oDocSped:Transporte:Cnpj              := Transform( XmlNode( cBlocoTransp, "CNPJ" ), "@R 99.999.999/9999-99" )
         oDocSped:Transporte:Nome              := Upper( XmlNode( cBlocoTransp, "xNome" ) )
         oDocSped:Transporte:InscricaoEstadual := XmlNode( cBlocoTransp, "IE" )
         oDocSped:Transporte:Endereco          := Upper( XmlNode( cBlocoTransp, "xEnder" ) )
         oDocSped:Transporte:Cidade            := Upper( XmlNode( cBlocoTransp, "xMun" ) )
         oDocSped:Transporte:Uf                := Upper( XmlNode( cBlocoTransp, "UF" ) )

Código: Selecionar todos

  aList := MultipleNodeToArray( cXmlInput, "det" )
   FOR EACH cBlocoItem IN aList
      AAdd( oDocSped:Produto, NFEProdutoClass():New() )
      nCont := Len( oDocSped:Produto )
      cBlocoProd := XmlNode( cBlocoItem, "prod" )
         oDocSped:Produto[ nCont ]:Codigo          := XmlNode( cBlocoProd, "cProd" )
         oDocSped:Produto[ nCont ]:Nome            := Upper( XmlNode( cBlocoProd, "xProd" ) )
         oDocSped:Produto[ nCont ]:CFOP            := Transform( XmlNode( cBlocoProd, "CFOP" ), "@R 9.9999" )
Complemento:
MultipleNodeToArray() é quando tem vários blocos com mesmo nome, cada bloco vai para um elemento do array.
Depois é só tratar um elemento de cada vez (FOR EACH).
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"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 do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Ler XML com TAGS dentro de TAG com TXMLDocument()

Mensagem por JoséQuintas »

Numa tabela html:

Código: Selecionar todos

cTxt := "[table]" + ;
   "[tr] [td] 1 [/td] [td] 2 [/td] [/tr]" + ;
   "[tr] [td] 1 [/td] [td] 2 [/td] [/tr]" + ;
   "[tr] [td] 1 [/td] [td] 2 [/td] [/tr]" + ;
   "[tr] [td] 1 [/td] [td] 2 [/td] [/tr]" + ;
   "[/table]"

FOR EACH cTxtRow IN MultipleNodeToArray( XmlNode( cTxt, "table" ), "tr" ) // extrai cada linha delimitada por [tr][/tr]
   FOR EACH cTxtCol IN MultipleNodeToArray( cTxtRow, "td" ) // extrai cada coluna delimitada por [td][/td]
      ? cTxtCol
   NEXT
NEXT
E funciona mesmo se houver complemento [det item=1][/det][det item=2][/det]
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"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 do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Ler XML com TAGS dentro de TAG com TXMLDocument()

Mensagem por JoséQuintas »

Olhando o seu XML, os itens estão em [itens] e tem o nome de [item]

Código: Selecionar todos

cBlocoItens := XmlNode( cTxt, "itens" )
FOR EACH cBlocoItem IN MultipleNodeToArary( cBlocoItens, "item" )
   ? XmlNode( cBlocoItem, "Codigo" )
   ? XmlNode( cBlocoItem, "Descricao" )
   ...
NEXT
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"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 do usuário
ANDRIL
Usuário Nível 5
Usuário Nível 5
Mensagens: 1297
Registrado em: 06 Jul 2004 00:44
Contato:

Ler XML com TAGS dentro de TAG com TXMLDocument()

Mensagem por ANDRIL »

Boa Quintas, obrigado pelos exemplos, vou testar para aprendizado. Já consegui fazer com o código que citei neste post, ficou muito fácil também.
Clipper 5.2e / Blinker 5.1 / Harbour 3.2 / GTwvg
Responder