Página 1 de 1

Ler XML com TAGS dentro de TAG com TXMLDocument()

Enviado: 19 Mai 2021 15:30
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.

Ler XML com TAGS dentro de TAG com TXMLDocument()

Enviado: 19 Mai 2021 15:49
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.

Ler XML com TAGS dentro de TAG com TXMLDocument()

Enviado: 19 Mai 2021 16:07
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.

Ler XML com TAGS dentro de TAG com TXMLDocument()

Enviado: 19 Mai 2021 16:17
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.

Ler XML com TAGS dentro de TAG com TXMLDocument()

Enviado: 23 Mai 2021 16:21
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.

Ler XML com TAGS dentro de TAG com TXMLDocument()

Enviado: 24 Mai 2021 12:16
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.

Ler XML com TAGS dentro de TAG com TXMLDocument()

Enviado: 24 Mai 2021 14:42
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.

Ler XML com TAGS dentro de TAG com TXMLDocument()

Enviado: 24 Mai 2021 15:10
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).

Ler XML com TAGS dentro de TAG com TXMLDocument()

Enviado: 24 Mai 2021 15:23
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]

Ler XML com TAGS dentro de TAG com TXMLDocument()

Enviado: 24 Mai 2021 15:29
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

Ler XML com TAGS dentro de TAG com TXMLDocument()

Enviado: 25 Mai 2021 09:00
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.