Unlock a world of possibilities! Login now and discover the exclusive benefits awaiting you.
Srs,
Estou com uma dúvida acerca de qual seria a melhor solução para a minha questão que segue:
Tenho um app que captura os xml's de notas fiscais de abastecimento e os "traduz" conforme script abaixo:
LOAD "XML",
TextBetween(XML,'KM:','.') as [NFe Abast - KM],
TextBetween(XML,'PLACA:','KM:') as [NFe Abast - Placa],
TextBetween(XML,'<chNFe>','</chNFe>') as [NFe Abast - Chave de Acesso],
TextBetween(XML,'<vUnCom>','</vUnCom>') as [NFe Abast - Valor Unitario],
len(TextBetween(XML,'<vUnCom>','</vUnCom>')) as [Nfe Abast - Un. Medida],
TextBetween(XML,'<vProd>','</vProd>') as [NFe Abast - Valor Total],
TextBetween(XML,'<uCom>','</uCom>') as [NFe Abast - Un Medida],
TextBetween(XML,'<xProd>','</xProd>') as [NFe Abast - Produto],
TextBetween(XML,'<nNF>','</nNF>') as [NFe Abast - Numero],
TextBetween(XML,'<xNome>','</xNome>') as [NFe Abast - Emitente Razao Social],
TextBetween(XML,'<xFant>','</xFant>') as [NFe Abast - Emitente Nome Fantasia],
TextBetween(XML,'<qCom>','</qCom>') as [NFe Abast - Quantidade],
date(SubField(TextBetween(XML,'<dhEmi>','</dhEmi>'),'T',1)) as [NFe Abast - Data Emissao],
Year((SubField(TextBetween(XML,'<dhEmi>','</dhEmi>'),'T',1))) as [NFe Abast - Ano Emissao],
Month((SubField(TextBetween(XML,'<dhEmi>','</dhEmi>'),'T',1))) as [NFe Abast - Mes Emissao],
Day((SubField(TextBetween(XML,'<dhEmi>','</dhEmi>'),'T',1))) as [NFe Abast - Dia Emissao],
Time(SubField(SubField(TextBetween(XML,'<dhEmi>','</dhEmi>'),'T',2),'-',1),'hh:mm') as [NFe Abast - Hora Emissao],
TextBetween(XML,'<xMotivo>','</xMotivo>') as [NFe Abast - Status]
FROM [lib://CARGA/NOTAS_ABASTECIMENTO.qvd](qvd);
Até aí tudo funciona "de boa" se, e somente se, a nota contiver apenas um item (o que ocorre em 99% dos casos que temos). Esse 1% é que me arrebenta...
Vejam como o xml da NF vem quando há mais de um item:
Eis então minha questão:
Como fazer a leitura desses dois itens, considerando que as tags que utilizo são as mesmas nos dois itens?
cleveranjos, afurtado, stalwar1
Abs e Sucesso!
Thiago,
Achei sua dúvida desafiadora e resolvi testar algo. Bom cheguei neste load que talvez resolva seu problema:
Para exemplificar gravei o conteudo dos 2 xmls enviados dentro de uma planilha excel para simular o banco de dados.
Ela tem duas linhas e dentro da celula eu colei os XML. (a planilha exemplo está anexada a resposta)
Para resolver o problema combinei a função TextBetween com a dupla (while & iterno) para criar um laço que se repete a cada linha tantas vezes for encontrada a tag </det> , isso determina o numero de itens de uma nf.
O comando while cria uma linha para cada ocorrência da tag </det> desde que seja menor que o total de ocorrências encontradas (resultado do substringcount).
Essa dica vale uns 10.000 pontos aqui na comunidade. Hahahahahaha..
Tai o script.
LOAD
Registro,
//cabeçalho NF
TextBetween(XML,'KM:','.') as [NFe Abast - KM],
TextBetween(XML,'PLACA:','KM:') as [NFe Abast - Placa],
TextBetween(XML,'<chNFe>','</chNFe>') as [NFe Abast - Chave de Acesso],
TextBetween(XML,'<vUnCom>','</vUnCom>') as [NFe Abast - Valor Unitario],
len(TextBetween(XML,'<vUnCom>','</vUnCom>')) as [Nfe Abast - Un. Medida],
date(SubField(TextBetween(XML,'<dhEmi>','</dhEmi>'),'T',1)) as [NFe Abast - Data Emissao],
Year((SubField(TextBetween(XML,'<dhEmi>','</dhEmi>'),'T',1))) as [NFe Abast - Ano Emissao],
Month((SubField(TextBetween(XML,'<dhEmi>','</dhEmi>'),'T',1))) as [NFe Abast - Mes Emissao],
Day((SubField(TextBetween(XML,'<dhEmi>','</dhEmi>'),'T',1))) as [NFe Abast - Dia Emissao],
Time(SubField(SubField(TextBetween(XML,'<dhEmi>','</dhEmi>'),'T',2),'-',1),'hh:mm') as [NFe Abast - Hora Emissao],
TextBetween(XML,'<xMotivo>','</xMotivo>') as [NFe Abast - Status],
TextBetween(XML,'<nNF>','</nNF>') as [NFe Abast - Numero],
TextBetween(XML,'<xNome>','</xNome>') as [NFe Abast - Emitente Razao Social],
TextBetween(XML,'<xFant>','</xFant>') as [NFe Abast - Emitente Nome Fantasia],
//itens NF
TextBetween(det_XML,'<vProd>','</vProd>') as [NFe Abast - Valor Total],
TextBetween(det_XML,'<uCom>','</uCom>') as [NFe Abast - Un Medida],
TextBetween(det_XML,'<xProd>','</xProd>') as [NFe Abast - Produto],
TextBetween(det_XML,'<qCom>','</qCom>') as [NFe Abast - Quantidade];
LOAD Registro,
XML,
TextBetween(XML,'<det nItem','</det>',iterno()) as det_XML
FROM
[Dados XML.xlsx]
(ooxml, embedded labels, table is Planilha1)
while iterno() <= SubStringCount(XML,'det nItem') ;
Por isso que eu adoro script de Qlik !!!!!
Abraço,
Pablo
Thiago,
tens algum XML de exemplo?
Thiago,
Se você estivesse lendo diretamente o arquivo XML, o proprio Qlik iria gerar o script necessário para extrair os itens de detalhe da nfe, mas como está lendo de um campo, ai complicou.
Talvez o uso do subfield te ajude a gerar uma linha para cada ocorrencia da string "<det nItem="
Tá na mão mestre!
Pois é Pablo. Nesse caso, meu ERP armazena todos os arquivos xml em uma tabela da qual eu os extraio e os salvo num qvd.
Up!
Alguém?!?
Terias como fazer o acesso e ler diretamente do banco ao invés do XML?
Se não, poderia fazer um load tradicional e o não tradicional quando o tamanho do arquivo xml for superior ao tradicional . Apenas uma ideia, mas: pega a lista dos xmls do diretório, separa o que é normal e carrega, as exceções lê com a estrutura diferente.
Ricardo, gostei da ideia porque sim, eu posso e faço a leitura diretamente do bd. Mas seria muito abuso se eu te pedisse pra me dar um exemplo prático no que se refere ao que você chama de load tradicional e não tradicional?
Para facilitar a exemplificação, disponho dois modelos de xml que tenho: um com apenas um item (talvez esse chamaríamos de tradicional) e outro com 2 itens (não tradicional).
Abs e muito obrigado desde já pelo tempo dispendido.
Bom dia Thiago,
Uma vez que está fazendo a extração para qvd, por que não fazer a extração para xml mesmo e desta forma simplifica a carga dos dados? Talvez seja uma saída para o problema.