Access violation ao ler arquivo xml com o XMLDocument

Delphi

13/12/2015

Código usado:
procedure TForm1.Button1Click(Sender: TObject);
var vXMLDoc: TXMLDocument;
    no_Principal,no_pai,no_cabecalho: IXMLNode;
begin
  vXMLDoc := TXMLDocument.Create(self);
  vXMLDoc.LoadFromFile('nfe.xml');
  no_Principal := vXMLDoc.DocumentElement.ChildNodes.FindNode('Nfe');
  no_pai := no_Principal.ChildNodes.FindNode('infNFe');
  no_cabecalho := no_pai.ChildNodes['ide'];
  Edit1.Text := no_cabecalho.ChildNodes['serie'].Text;
end;


xml que esta lendo:

-<Nfe>
-<infNFe>
-<ide>
<serie>2</serie>
</ide>
</infNFe>
</Nfe>
Jhon

Jhon

Curtidas 1

Melhor post

Jhon

Jhon

17/12/2015

Consegui ler todas as informações do xml com exceção dos produtos, pois preciso colocar no loop e não estou conseguindo, até olhei alguns exemplos mas não deu certo. Da uma olhada no código que estou usando, ele importa as informações apenas do primeiro produto, isso por que esta fora do loop, como faria pra colocar no loop esse código e ler as informações de todos os produtos ?

NodePai := NodePrim.ChildNodes.FindNode('infNFe');
node_det:=NodePai.ChildNodes.FindNode('det');
node_prod:=node_det.ChildNodes.FindNode('prod');
Memo_Retorno.Lines.Add('cProd : '+ node_prod.ChildNodes['cProd'].Text);
Memo_Retorno.Lines.Add('cEAN : '+ node_prod.ChildNodes['cEAN'].Text);
Memo_Retorno.Lines.Add('xProd : '+ node_prod.ChildNodes['xProd'].Text);
Memo_Retorno.Lines.Add('NCM : '+ node_prod.ChildNodes['NCM'].Text);
Memo_Retorno.Lines.Add('CFOP : '+ node_prod.ChildNodes['CFOP'].Text);
Memo_Retorno.Lines.Add('uCom : '+ node_prod.ChildNodes['uCom'].Text);
Memo_Retorno.Lines.Add('qCom : '+ node_prod.ChildNodes['qCom'].Text);
Memo_Retorno.Lines.Add('vUnCom : '+ node_prod.ChildNodes['vUnCom'].Text);
Memo_Retorno.Lines.Add('vProd : '+ node_prod.ChildNodes['vProd'].Text);
Memo_Retorno.Lines.Add('cEANTrib : '+ node_prod.ChildNodes['cEANTrib'].Text);
Memo_Retorno.Lines.Add('uTrib : '+ node_prod.ChildNodes['uTrib'].Text);
Memo_Retorno.Lines.Add('qTrib : '+ node_prod.ChildNodes['qTrib'].Text);
Memo_Retorno.Lines.Add('vUnTrib : '+ node_prod.ChildNodes['vUnTrib'].Text);
Memo_Retorno.Lines.Add('indTot : '+ node_prod.ChildNodes['indTot'].Text);
GOSTEI 1

Mais Respostas

Raimundo Pereira

Raimundo Pereira

13/12/2015

O erro ocorre por conta do caminho do arquivo.
vXMLDoc.LoadFromFile('nfe.xml'); // aqui você está usando apenas o nome do arquivo.
Crie uma pasta no disco c: >> chamada 'Notas' e coloque o xml nfe.xml dentro da mesma.
Com isso o caminho será :
vXMLDoc.LoadFromFile('c:\notas\nfe.xml');

Debug o projeto e veja em qual linha exatamente apresenta o erro.
Há três meses há traz usava uma rotina própria para lêr XML.

Veja >

X:INTEGER;
_vXMLDoc: TXMLDocument;
_Node_Ret_Pai,
_Node_Ret_Inform,
_NodeProd,
_NodeImpProd,
_NodeIcms00,
_NodeIcms,
_NodeItens,
_Node_Mae ,

_Node_Ret_Conteudo : IXMLNode;

vXMLDoc:TXMLDocument;
NodePai,NodeSec,NODE_P2,NodeTmp,NodeImp,NodeImposto: IXMLNode;

nome :STRING;
codigo:STRING;

BEGIN
ARQUIVO_SELECIONADO:='';
if ARQUIVO_SELECIONADO='' then
BEGIN
ShowMessage('Selecione uma NF-e !');
END
ELSE
BEGIN
vXMLDoc:= TXMLDocument.Create(SELF);
TRY
vXMLDoc.LoadFromFile(ARQUIVO_SELECIONADO);
vXMLDoc.Active := True;

NodePai :=vXMLDoc.DocumentElement.childNodes.First.ChildNodes.FindNode('infNFe');
NodeSec := NodePai.ChildNodes.FindNode('det');
NodeSec.ChildNodes.First;

E assim carrego por tags.
Para carregar os produtos uso um loop.

Há três meses passei a usar o Acbr.

if Chamada_F='PRINT' then
BEGIN

Chamada_F:='';
ACBrNFe.NotasFiscais.Clear;
ACBrNFe.NotasFiscais.LoadFromFile(PXML.FileName);
ACBrNFe.NotasFiscais.Imprimir;
ACBrNFe.NotasFiscais.Clear;
END;


if (CHAMADA_TIPO='NFe')AND (ARQUIVO_SELECIONADO<>'') then
BEGIN
NOME_COLIGADO_DESTINO_XML:='';
NOME_EMISSOR_XML:='';
DATA_EMISSAO_DOC_XML:='';
NOME_DEST_XML:='';
CNPJ_CPF_DEST_XML:='';
CNPJ_EMISSOR_XML:='';
NUMERO_NFE_XML:='';

ACBrNFe.NotasFiscais.Clear;
ACBrNFe.NotasFiscais.LoadFromFile(ARQUIVO_SELECIONADO);

NUMERO_NFE_XML:= IntToStr( ACBrNFe.NotasFiscais.Items[0].NFe.Ide.nNF);

DATA_EMISSAO_DOC_XML:=DateToStr(ACBrNFe.NotasFiscais.Items[0].NFe.Ide.dEmi);
NOME_EMISSOR_XML:=
ACBrNFe.NotasFiscais.Items[0].NFe.Emit.xNome;
CNPJ_EMISSOR_XML:=ACBrNFe.NotasFiscais.Items[0].NFe.Emit.CNPJCPF;
NOME_DEST_XML:=ACBrNFe.NotasFiscais.Items[0].NFe.Dest.xNome;
CNPJ_CPF_DEST_XML:=ACBrNFe.NotasFiscais.Items[0].NFe.Dest.CNPJCPF;

L_RET_EMISSOR.Caption:='Emissor da NF-e '+NOME_EMISSOR_XML+' ['+EMISSOR+']';
L_RET_nfe.Caption:='Número da NF-e ['+NUMERO_NFE_XML+']';
L_RET_DATA_EMISSAO.Caption:='Data de Emissão da NF-e ['+DATA_EMISSAO_DOC_XML+']';
L_RET_CNPJ_DEST.Caption:='Documento CPF/CNPJ ['+CNPJ_CPF_DEST_XML+']';
L_RET_NOME_DEST.Caption:='Nome do Destinatário ['+NOME_DEST_XML+']';

OBS_XML:=(ACBrNFe.NotasFiscais.Items[0].NFe.InfAdic.infCpl);

CHAVE_ACESSO_XML:=(ACBrNFe.NotasFiscais.Items[0].NFe.procNFe.chNFe);

PROTOCOLO_XML:=(ACBrNFe.NotasFiscais.Items[0].NFe.procNFe.nProt);

Verify_Destinatario(SELF);
BEGIN
if NFE_COLIGADO='X' then
BEGIN
L_RET_TIPO_CLIENTE.Caption:='Destino NF-e [COLIGADO]';
END
ELSE
BEGIN
L_RET_TIPO_CLIENTE.Caption:='Destino NF-e [CLIENTE]';
END;

END;
END;

if (CHAMADA_TIPO='CCE')AND (ARQUIVO_SELECIONADO<>'') then
BEGIN
LENDO_CCE(SELF);
END;


END;
GOSTEI 0
Raimundo Pereira

Raimundo Pereira

13/12/2015

Para Lista os Itens faça o seguinte.

var
X:INTEGER;
_vXMLDoc: TXMLDocument;
_Node_Ret_Pai,
_Node_Ret_Inform,
_NodeProd,
_NodeImpProd,
_NodeIcms00,
_NodeIcms,
_NodeItens,
_Node_Mae ,

_Node_Ret_Conteudo : IXMLNode;

vXMLDoc:TXMLDocument;
NodePai,NodeSec,NODE_P2,NodeTmp,NodeImp,NodeImposto: IXMLNode;

nome :STRING;
codigo:STRING;

BEGIN
ARQUIVO_SELECIONADO:='';
ARQUIVO_SELECIONADO:=caminho completo do arquivo xml;

if ARQUIVO_SELECIONADO='' then
BEGIN
ShowMessage('Selecione uma NF-e !');
END
ELSE
BEGIN

Application.CreateForm(TF_PNFE,F_PNFE);// Aqui eu criei um outro form

DM.INSTRUC.SQL.Text:='DELETE FROM TMP_ITENS'; // tenho uma tabela temporária onde armazeno os itens então eu limpo esta tabela
DM.INSTRUC.ExecSQL;

DM.CD_PRODUTOS.CLOSE; //Essa é a tabela temporária deixo aberta para inciar o insert
DM.CD_PRODUTOS.OPEN; //

vXMLDoc:= TXMLDocument.Create(SELF);

TRY
vXMLDoc.LoadFromFile(ARQUIVO_SELECIONADO);
vXMLDoc.Active := True;
//_______________________________________________________________________________

NodePai :=vXMLDoc.DocumentElement.childNodes.First.ChildNodes.FindNode('infNFe');
NodeSec := NodePai.ChildNodes.FindNode('det');

// Esse nó vai ser usado no LOOP
NodeSec.ChildNodes.First;
repeat
// referencia a tag <prod> dentro de <det>
NodeTmp := NodeSec.ChildNodes['prod'];
// da pra ver que é um XML resumido da NFe (so temos uma tag <prod> para cada <det> então não precisaria da linha abaixo
// agora se tivéssemos mais de uma seria o caso de posicionar também na primeira ocorrencia.
NodeTmp.ChildNodes.First;


repeat
// pega os dados que vc quiser dentro da tag <prod>

if NodeTmp.ChildNodes['cProd'].text<>'' then
BEGIN
DM.CD_PRODUTOS.Insert;
DM.CD_PRODUTOS.FieldByName('cProd').ASSTRING:=NodeTmp.ChildNodes['cProd'].text;
DM.CD_PRODUTOS.FieldByName('cEAN').ASSTRING:=NodeTmp.ChildNodes['cEAN'].text;
DM.CD_PRODUTOS.FieldByName('xProd').ASSTRING:=NodeTmp.ChildNodes['xProd'].text;
DM.CD_PRODUTOS.FieldByName('NCM').ASSTRING:=NodeTmp.ChildNodes['NCM'].text;
DM.CD_PRODUTOS.FieldByName('CFOP').ASSTRING:=NodeTmp.ChildNodes['CFOP'].text;
DM.CD_PRODUTOS.FieldByName('uComu').ASSTRING:=NodeTmp.ChildNodes['uComu'].text;
DM.CD_PRODUTOS.FieldByName('qCom').ASSTRING:=NodeTmp.ChildNodes['qCom'].text;
DM.CD_PRODUTOS.FieldByName('vUnCom').ASSTRING:=NodeTmp.ChildNodes['vUnCom'].text;
DM.CD_PRODUTOS.FieldByName('vProd').ASSTRING:=NodeTmp.ChildNodes['vProd'].text;
DM.CD_PRODUTOS.FieldByName('NFE').ASSTRING:=Consulta_NFE.FieldByName('NFE').AsString;
DM.CD_PRODUTOS.POST;
END;
NodeTmp := NodeTmp.NextSibling;
until NodeTmp = nil;

NodeSec := NodeSec.NextSibling;
until NodeSec = nil;

EXCEPT
END;
END;
vXMLDoc.Free;

DM.CD_PRODUTOS.Open;
if DM.CD_PRODUTOS.RecordCount>0 then
BEGIN
F_PNFE.ShowModal; //esse é um form com um grid linkado a tabela temporária DM.CD_PRODUTOS
END
ELSE
BEGIN
ShowMessage('Nehum item registrado na NF-e');
END;
GOSTEI 0
Jhon

Jhon

13/12/2015

Consegui ler as informações dos produtos, obrigado. Queria saber qual o nome dos componentes que esta usando para a tabela temporária e qual o tipo de campo que colocou para o campo de unitário e total do produto, representados no xml pelas tags vUnCom e vProd.
GOSTEI 0
Raimundo Pereira

Raimundo Pereira

13/12/2015

Que bom, como no meu caso não realizo nenhum calculo eu crio Clientdaset em run time, monto os campos todos como string.

Repare que na tabela temporária .ASSTRING
No node .text;

DM.CD_PRODUTOS.FieldByName('vUnCom').ASSTRING:=NodeTmp.ChildNodes['vUnCom'].text;
DM.CD_PRODUTOS.FieldByName('vProd').ASSTRING:=NodeTmp.ChildNodes['vProd'].text;

Você pode criar uma tabela dentro do seu banco com os dados importantes.
Antes de iniciar a leitura você realiza um delete na sua tabela.

Fique a vontade para definir os tipos de campo na sua tabela podendo ser string, double ou numeric 18,4.
Como disse não realizo cálculos o string me ajuda eu apenas preciso saber os itens da NF-e.
Pois geralmente meus clientes solicitam a segunda via de nota, muitas das vezes não lembras datas ou números das NFe.

Rsrs, as vezes só lembram do produto que compraram em um determinado período.
Veja o exemplo da minha tela;
[img]http://arquivo.devmedia.com.br/forum/imagem/437747-20151219-094453.png[/img]

Se for criar o dataset em run time dá uma olhada no tutorial.
http://www.activedelphi.com.br/forum/viewtopic.php?t=71070&sid=f1be599f33790b5f4c9f13a9e1f95419


Espero que tenha ajudado .
Sucesso
GOSTEI 0
Jhon

Jhon

13/12/2015

Ta ok, vou criar a tabela em run time e depois gravo na tabela do banco. Obrigado. Aproveitando a situação, não sei se poderia me ajudar, mas eu não consigo aplicar comandos do tipo delete, insert ou update sem dar o erro : SQLQuery1: Cursor not returnet from Query. Só consigo dar select, que funciona perfeitamente, mas outros comandos não. Estou usando os componentes : SQLQuery,DataSetProvider,ClientDataSet e DataSource. Talvez tenho de usar outro componente para aplicar outros comandos, fora select, saberia me dizer qual ?
GOSTEI 0
Anderson Gaitolini

Anderson Gaitolini

13/12/2015

Verifique se a estrutura do XML que esta sendo lida não foi modificada, pois uma NFe depois de autorizada ganha novas tag alterando a leitura do Nodes pelo Fonte. O ideal seria fazer sua estrutura num laço (While, For e ou Repeat)
GOSTEI 0
POSTAR