Pesquisando no Google, encontrei uma porção de sites capazes de fazer a validação on-line e também ferramentas - algumas gratuitas, outras pagas. No caso da NFe, a própria Receita Federal faz essa validação mas é preciso submeter ao Web Service deles e aguardar a resposta assíncrona.
Como não encontrei nada que eu achasse prático, resolvi montar um validador por minha conta, para ter à mão sempre que necessário. Pra minha surpresa, descobri que o framework .Net já possui classes para validar um XML e que o uso delas é bastante simples.
Mãos à obra ! Montei uma aplicação simples em C# no Visual Studio 2008 : tem 3 caixas de edição e um botão, como mostra o print screen abaixo:

Ao clicar o botão, o arquivo indicado na caixa Caminho do XML é carregado através de um Reader previamente configurado para realizar a validação enquanto faz a carga. Abaixo, o código comentado do evento de clique no botão :
/* XmlReaderSettings é a configuração de como o XML deve ser lido */
XmlReaderSettings settings = new XmlReaderSettings();
FileStream fs = null;
/* Informa qual é o namespace (se houver) e o caminho do esquema XSD que será usado p/ validar o XML durante a leitura */
settings.Schemas.Add (edNamespace.Text, edXSD.Text);
/* Se dentro do XSD houver referência a outros XSDs externos, pode ser necessário ter certas permissões para localizá-lo. Usa um "Resolver" com as credencias-padrão para obter esse recurso externo. */
XmlUrlResolver resolver = new XmlUrlResolver();
resolver.Credentials = CredentialCache.DefaultCredentials;
/* Informa à configuração de leitura do XML que deve usar o "Resolver" criado acima e que a validação deve respeitar o esquema informado no início. */
settings.XmlResolver = resolver;
settings.ValidationType = ValidationType.Schema;
try {
/* Abre o arquivo XML usando o caminho que foi informado na tela. */
fs = new FileStream(edXML.Text, FileMode.Open,
FileAccess.Read);
/* Constrói o leitor de XML, passando o arquivo XML que foi aberto e as configurações que sinalizam como o leitor deve trabalhar. */
XmlReader reader = XmlReader.Create (fs, settings);
/* Constrói um documento XML vazio */
XmlDocument xmlDoc = new XmlDocument();
/* Manda carregar as informações nesse XML através do leitor montado acima. */
xmlDoc.Load(reader);
/* Só chega aqui se carregou tudo OK. */
MessageBox.Show(this, "Validação concluída com sucesso.",
"Aviso", MessageBoxButtons.OK,
MessageBoxIcon.Information);
} catch (Exception exc)
{
/* Se houver erro na validação do XML, uma exceção é levantada e o fluxo vem para esse ponto, exibindo a mensagem de erro.*/
MessageBox.Show(this, exc.Message, "Erro",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
/* Fecha o stream para liberar o arquivo. */
if (fs != null)
{
fs.Close();
fs.Dispose();
}
Ao final, se foi tudo OK com a carga, tem-se na instância xmlDoc a árvore do XML montada, validada e pronta para ser usada pelo programa.XmlReaderSettings settings = new XmlReaderSettings();
FileStream fs = null;
/* Informa qual é o namespace (se houver) e o caminho do esquema XSD que será usado p/ validar o XML durante a leitura */
settings.Schemas.Add (edNamespace.Text, edXSD.Text);
/* Se dentro do XSD houver referência a outros XSDs externos, pode ser necessário ter certas permissões para localizá-lo. Usa um "Resolver" com as credencias-padrão para obter esse recurso externo. */
XmlUrlResolver resolver = new XmlUrlResolver();
resolver.Credentials = CredentialCache.DefaultCredentials;
/* Informa à configuração de leitura do XML que deve usar o "Resolver" criado acima e que a validação deve respeitar o esquema informado no início. */
settings.XmlResolver = resolver;
settings.ValidationType = ValidationType.Schema;
try {
/* Abre o arquivo XML usando o caminho que foi informado na tela. */
fs = new FileStream(edXML.Text, FileMode.Open,
FileAccess.Read);
/* Constrói o leitor de XML, passando o arquivo XML que foi aberto e as configurações que sinalizam como o leitor deve trabalhar. */
XmlReader reader = XmlReader.Create (fs, settings);
/* Constrói um documento XML vazio */
XmlDocument xmlDoc = new XmlDocument();
/* Manda carregar as informações nesse XML através do leitor montado acima. */
xmlDoc.Load(reader);
/* Só chega aqui se carregou tudo OK. */
MessageBox.Show(this, "Validação concluída com sucesso.",
"Aviso", MessageBoxButtons.OK,
MessageBoxIcon.Information);
} catch (Exception exc)
{
/* Se houver erro na validação do XML, uma exceção é levantada e o fluxo vem para esse ponto, exibindo a mensagem de erro.*/
MessageBox.Show(this, exc.Message, "Erro",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
/* Fecha o stream para liberar o arquivo. */
if (fs != null)
{
fs.Close();
fs.Dispose();
}
Obs: No lugar de ler o XML de um arquivo, pode-se usar qualquer tipo de Stream - até mesmo lido da memória (MemoryStream).
Clique aqui para fazer o download do programa. Inclui aqui no blog também alguns posts sobre a construção de arquivos XSD para facilitar o entendimento de como isso funciona.

Poste o link para dowload desse programa
ResponderExcluirChris
ResponderExcluirObrigado pelo seu feedback ! Inclui no post um link para download do programa do exemplo.
[]s
Uma duvida esse validador identica a má formação do XML, eu pergunto porque tive uma resposta da receita dessa forma "má formação do XML" em ambiente Scan.
ResponderExcluirMeu email: analista.edilson@hotmail.com
A ideia do programa é justamente verificar se o XML está bem formado, isto é, se ele atende às regras de formação estipuladas no XSD (esquema). Então, a resposta é "sim", ele será capaz de apontar as má formações estruturais apresentadas pelo seu XML.
ResponderExcluirNo entanto, ele não conseguirá identificar má formação semântica, isto é, relativa aos cruzamentos que a Receita Federal faz com alguns campos. Por exemplo, se a inscrição estadual informada é válida ou não; se o Estado ou Município do Emissor que foi informado na NFe está diferente daquele registrado na própria Receita; etc..
Gustavo,
ResponderExcluirVejo que no exemplo disponível para download tem como pegar todos os erros e apenas o primeiro. Como você fez isso?
No código listado no post, o .NET gera uma exceção quando o primeiro erro é encontrado, interrompendo imediatamente a validação.
ResponderExcluirPara obter todos os erros de uma vez, usei o evento ValidationEventHandler existente no XmlReaderSettings. Para usá-lo, crie uma nova instância da classe ValidationEventHandler e a atribuí à propriedade de mesmo nome no settings. O construtor dessa classe recebe como parâmetro uma função para onde as exceções relativas à validação são redirecionadas.
Assim, basta concatenar as mensagens de erro recebidas por essa função e exibí-las ao fim da validação.
Opa, boa tarde a todos.
ResponderExcluirNão compreendi muito bem a parte:
"Para obter todos os erros de uma vez, usei o evento ValidationEventHandler existente no XmlReaderSettings. Para usá-lo, crie uma nova instância da classe ValidationEventHandler e a atribuí à propriedade de mesmo nome no settings. O construtor dessa classe recebe como parâmetro uma função para onde as exceções relativas à validação são redirecionadas" !?!
Kaichiro
ResponderExcluirA versão do código C# para validação que está reproduzida no post interrompe sua execução ao encontrar um erro; outros erros que eventualmente existam no XML só serão revelados depois que esse primeiro erro for corrigido.
Assim, se quiser capturar todos os erros do XML de uma única vez, responda ao evento ValidationEventHandler existente no XmlReaderSettings. A cada erro encontrado, o evento é disparado uma vez, dando a oportunidade de você salvar as mensagens para exibição.
Veja a documentação dele no MSDN : evento ValidationEventHandler
Opa, vlw. Deu certo agora.
ResponderExcluirOlá Luis, posso usar seu programa como um fiel da balança para um cliente, explico.
ResponderExcluirTenho que gerar vários xml para esse cliente, meu programa gera e valida, mas eu gostaria de um programa de terceiros para ficar como um "tira-teima", posso usar seu programa para isso?? tem algum custo??
Pode usá-lo, sem problemas. Ele não tem custo, até porque o código que faz a validação está todo reproduzido no post. Isto também te deixa livre para criar sua própria versão do validador, implementando outras funcionalidades que julgar necessárias.
ResponderExcluirLuis, estou tentando fazer a validação e está dando um erro 'http://www.w3.org/2000/09/xmldsig#:Signature' não foi declarado.
ResponderExcluirVoce tem msn facil?
Rapozao (?)
ResponderExcluirÉ bem provável que o XML que você passou não possui a tag Signature exigida pelo esquema XSD.
O valor http://www.w3.org/2000/09/xmldsig# é o namespace onde a tag Signature deve ser inserida. Lembre-se de que, se um namespace não for especificado, a tag é considerada no escopo do namespace do nó-pai onde ela está inserida.
No caso da NFe, por exemplo, você deve declarar explicitamente o Signature como parte do http://www.w3.org/2000/09/xmldsig#, senão o namespace considerado será http://www.portalfiscal.inf.br/nfe, o que resultará em erro quando o XML for confrontado com o XSD.
Aqui no blog tem um post sobre assinatura digital de arquivos XML que pode te ajudar :
Incluindo a assinatura digital no XML.
tem como mandar o fonte do exemplo nao ? ou melhor ainda deixa o fonte disponivel no blog.
ResponderExcluirse possivel por email (tbalbinos@oi.com.br)
obrigado
Parabéns !! Thiago B.
Thiago
ResponderExcluirO código completo para a validação está listado no corpo do post e inclui comentários sobre o funcionamento de cada parte. Insira esse código como resposta a um evento - como o clique de um botão "Validação" num form, por exemplo.
[]s
não achei o post ccom o link para baixar o fonte do programa e gostaria de receber, sera que pode me mandar no e-mail, o meu email é tom.camara@gmail.com, desde já agradeço
ResponderExcluirTom
ResponderExcluirComo eu disse no comentário anterior, o código está todo no post. Se está com dificuldade de incluí-lo como resposta a um evento, poste sua dúvida (ou envie no email do blog).
Amigo, obrigado pelo programa e pelo código.
ResponderExcluirFicou faltando apenas dar um Close no Stream depois da validação. Peguei seu programa para validar o XML que o meu sistema estava gerando, e após cada validação, preciso fechar seu aplicativo, gerar o novo XML, abrir seu aplicativo e digitar novamente o schema, caminho do XSD e do XML.
Claro que pra facilitar meu trabalho, já gerei a minha própria versão corrigida, mas vale você corrigir o seu também!
Obrigado pelo aviso ! Já tinha feito essa alteração na minha versão local mas não tinha atualizado o post.
ExcluirAgora o encerramento do stream está no código do post e subi de novo o arquivo pra download.
[]s
Muito bom seu post... porém gostaria de sabe se caso vc possui os fontes, teria como disponibilizar?
ResponderExcluirPois o aplicativo que tem pra download, tem um segundo botão no qual "valida tudo".
Desde já muito obrigado!
PS: meu email é edilsonld@gmail.com
Edilson
ExcluirComo eu disse em outro comentário, se quiser capturar todos os erros do XML de uma única vez, você terá que responder ao evento ValidationEventHandler existente no XmlReaderSettings. A cada erro encontrado, o evento é disparado uma vez, dando a oportunidade de você salvar as mensagens para exibição.
Veja a documentação dele no MSDN : evento ValidationEventHandler.
Muito obrigado!
ExcluirFuncionou o que queria fazer.
Elemento 'http://www.portalfiscal.inf.br/nfe:nfeProc' não foi declarado.
ResponderExcluirCARA QUANDO VOU VALIDAR DA ESSE ERRO OQUE PODE SER ??
cassio.infro@gmail.com
Cássio
ExcluirO XML que você está testando não bate com a estrutura definida no esquema XSD. A definição do XSD exige a presença da tag nfeProc mas o XML não tem uma tag com esse nome - ao menos não no lugar esperado, que me parece ser a raiz. Veja se a tag existe e se está declarada no namespace correto (http://www.portalfiscal.inf.br/nfe).
[]s