XML
- Validando um Documento XML com um Schema (C#)
Você já precisou validar um documento XML verificando se ele esta em conformidade com um schema XML ?
Mas onde será que isso pode ser aplicado ?
Se você desejar usar a Nota Fiscal Eletrônica ( NF-e) talvez precise realizar tais validações XML.
Pois hoje vamos mostrar como realizar esta tarefa usando a linguagem C#.
A validação de um documento XML é realizada com a aplicação do respectivo Schema XML, que contêm a definição dos campos e conteúdos válidos para o documento XML a ser validado.
Um esquema XML define as regras que um determinado tipo de documento XML deve seguir. O esquema inclui regras que definem o seguinte:
Os elementos
e atributos que podem aparecer em um documento;
Os tipos de dados para elementos e atributos;
A estrutura de um documento, incluindo os elementos que
são filhos de outros elementos;
A ordem e o número de elementos filhos que aparecem em um
documento;
Se os elementos estiverem vazios, podem incluir texto, ou
exigir valores fixos;
Em seu nível mais básico, um XML Schema Definition (XSD) define os elementos que podem ocorrer em um documento XML.
Documentos XSD são escritos em XML, e você usa um elemento predefinido separado (chamado <element>) no documento XSD para indicar cada elemento que é necessário no documento XML onde o atributo type indica o tipo de dados.
Aqui está um exemplo para nome e preço de produto:
<xsd:element
name="produtoNome" type="xsd:string" />
<xsd:element name="produtoPreco" type="xsd:decimal"
/>
Os tipos de tipos de dados de esquema são definidos pelo www.w3.org/TR/xmlschema-2 eles são mapeados para os tipos de dados .NET incluindo string, int, long, decimal, float , dataTime, boolean.
Em nosso exemplo tanto o produtoNome como produtoPreco são tipos simples, porque eles contêm somente dados caractere. Elementos que contêm elementos aninhados são chamados de tipos complexos. Você pode aninhá-los em conjunto, utilizando uma tag <sequence>, se a ordem for importante, ou uma tag <all> se não for. A seguir um exemplo de como você pode modelar o elemento <produto> no catálogo de produtos. Observe que os atributos são sempre declarados após os elementos e eles não são agrupados com uma tag <sequence> ou <all> porque a ordem não é importante:
| <xsd:complexType
name="produto"> <xsd:sequence> <xsd:element name="produtoNome" type="xsd:string"/> <xsd:element name="produtoPreco" type="xsd:decimal"/> <xsd:element name="emEstoque" type="xsd:boolean"/> </xsd:sequence> <xsd:attribute name="id" type="xsd:integer"/> </xsd:complexType> |
Por padrão, um elemento listado pode ocorrer exatamente uma vez em um documento. Você pode configurar este comportamento especificando os atributos maxOccurs minOccurs. A seguir temos um exemplo que permite um número ilimitado de produtos no catálogo:
<xsd:element name="produto" type="produto" maxOccurs="unbounded" />
Abaixo está o arquivo de esquema para o catalogo de produtos :
<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!-- Define o tipo complexo produto. -->
<xsd:complexType name="produto">
<xsd:sequence>
<xsd:element name="produtoNome" type="xsd:string"/>
<xsd:element name="descricao" type="xsd:string"/>
<xsd:element name="produtoPreco" type="xsd:decimal"/>
<xsd:element name="emEstoque" type="xsd:boolean"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:integer"/>
</xsd:complexType>
<!-- Esta é a estrutura que o documento precisa estar em conformidade.
Ela incia com o elemento produtoCatalogo que aninha outros elementos. -->
<xsd:element name="catalogoProdutos">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="catalogoNome" type="xsd:string"/>
<xsd:element name="dataValidade" type="xsd:date"/>
<xsd:element name="produtos">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="produto" type="produto"
maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
|
A classe XmlReader
pode impor estas regras do esquema, permitindo a você solicitar
explicitamente uma validação, quando você usar o método XmlReader.Create.
(Mesmo que você não usa um leitor de validação, uma exceção
será lançada se o leitor descobre que o XML não esta bem
formado, como um caráter ilegal,
tags aninhadas indevidamente, etc.). Assim temos que:
1- ) Quando você chama XmlReader.Create,
a chamada de um objeto XmlReaderSettings indica que você deseja
executar validação;
2- ) Em seguida, movimentando através do nó do documento um de cada
vez pela chamada do XmlReader.Read, e capturando
todas as exceções de validação.;
3- ) Para encontrar todos os erros em um documento sem capturar
exceções, você pode tratar o evento ValidationEventHandler
no objeto XmlReaderSettings dado como parâmetro
para XmlReader;
Depois de ter criado o seu leitor de validação, a validação ocorre automaticamente quando você ler o documento. Assim que um erro for encontrado, o XmlReader gera um evento ValidationEventHandler com informações do erro sobre o objeto XmlReaderSettings dada no momento da criação.
Se você quiser, você pode manipular este evento e continuar processando o documento para encontrar mais erros. Se você não tratar esse evento, uma exceção XmlException será lançada quando o primeiro erro for encontrado, e o processamento será abortado.
A seguir veremos um exemplo para lhe dar um idéia de como podemos fazer a validação de um documento XML. Para isso vou criar uma classe usando a linguagem C# que exibe todos os erros de um documento XML quando o método ValidarXML for chamado.
Os erros serão exibidos em uma janela do console e uma variável boleana será retornada para indicar se a validação ocorreu com sucesso ou não.
Realizando a validação XML
Abra o Visual C# 2010 Express Edition e crie uma aplicação do tipo Console Application com o nome Validando_XML;
No menu Project clique em Add Class e informe o nome da classe como ValidacaoXML.cs. A seguir inclua o código abaixo neste arquivo:
using System;
using System.Xml;
using System.Xml.Schema;
namespace Validando_XML
{
public class ValidacaoXML
{
private bool falhou;
public bool Falhou
{
get { return falhou; }
}
public bool ValidarXml(string xmlFilename, string schemaFilename)
{
// Define o tipo de validação
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
// Carrega o arquivo de esquema
XmlSchemaSet schemas = new XmlSchemaSet();
settings.Schemas = schemas;
// Quando carregar o eschema, especificar o namespace que ele valida
// e a localização do arquivo
schemas.Add(null, schemaFilename);
// Especifica o tratamento de evento para os erros de validacao
settings.ValidationEventHandler += ValidationEventHandler;
// cria um leitor para validação
XmlReader validator = XmlReader.Create(xmlFilename, settings);
falhou = false;
try
{
// Faz a leitura de todos os dados XML
while (validator.Read()) {}
}
catch (XmlException err)
{
// Um erro ocorre se o documento XML inclui caracteres ilegais
// ou tags que não estão aninhadas corretamente
Console.WriteLine("Ocorreu um erro critico durante a validacao XML.");
Console.WriteLine(err.Message);
falhou = true;
}
finally
{
validator.Close();
}
return !falhou;
}
private void ValidationEventHandler(object sender, ValidationEventArgs args)
{
falhou = true;
// Exibe o erro da validação
Console.WriteLine("Erros da validação : " + args.Message);
Console.WriteLine();
}
}
}
|
Agora vamos incluir no projeto o arquivo de esquema XSD com o nome Produtos.xsd que iremos usar para validar o documento XML. No menu Project clique em Add New Item e a seguir selecione o template XML File e a seguir copie o conteúdo do arquivo XML conforme abaixo :
![]() |
Vamos agora incluir um arquivo XML chamado CatalogoProdutos.xml no projeto. No menu Project clique em Add New Item e a seguir selecione o template XML File e inclua o seguinte código neste arquivo:
![]() |
Agora vamos usar a classe que criamos para validar o documento XML usando o esquema definido. Para isso eu vou copiar os arquivos .xsd e .xml na pasta c:\dados assim fica mais fácil localizar os arquivos.
No arquivo Program.cs digite o código abaixo que irá realizar a validação do arquivo CatalogoProdutos.xml usando o arquivo de esquema Produtos.xsd:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Validando_XML
{
class Program
{
static void Main(string[] args)
{
ValidacaoXML validadorXML = new ValidacaoXML();
Console.WriteLine("Validando o arquivo CatalogoProdutos.xml pelo esquema Produtos.xsd.");
bool ok = validadorXML.ValidarXml(@"C:\dados\CatalogoProdutos.xml",@"c:\dados\Produtos.xsd");
if (!ok)
Console.WriteLine("A validação falhou.");
else
Console.WriteLine("A validação foi realizada com sucesso.");
Console.ReadLine();
}
}
}
|
No método Main() temos o seguinte:
Se nenhum erro for encontrado será exibida somente a mensagem : "A validação foi realizada com sucesso."
Vamos então executar o projeto e verificar o resultado:
![]() |
Vamos agora alterar o arquivo CatalogoProdutos.xml produzindo alguns erros para vermos o resultado obtido. Altere o arquivo conforme abaixo:
<?xml version="1.0" encoding="utf-8" ?>
<catalogoProdutos>
<catalogoNome>JcmSoft Catalogo 2011</catalogoNome>
<dataValidade>01 de aneiro de 2012</dataValidade>
<produtos>
<produto id="1001">
<produtoNome>Super DVD NET</produtoNome>
<descricao>Material de suporte para Estudo</descricao>
<produtoPreco>60.00</produtoPreco>
<emEstoque>true</emEstoque>
</produto>
<produto id="1002">
<produtoNome>Super DVD Video Aulas</produtoNome>
<descricao>Video aulas com exemplos praticos </descricao>
<produtoPreco>50.00</produtoPreco>
<emEstoque>yes</emEstoque>
</produto>
<produto id="1003">
<produtoNome>Super CD VB</produtoNome>
<descricao>Codigos fontes e material de suporte </descricao>
<produtoPreco>50.00</produtoPreco>
<Estoque>true</emEstoque>
</produto>
</produtos>
</catalogoProdutos>
|
Executando novamente a validação iremos obter o seguinte resultado:
![]() |
Como podemos observar recebemos 3 mensagens de erro correspondendo as alterações que fizemos no arquivo XML para provocar tais erros.
Apenas para mostrar outra maneira de realizar a validação vamos incluir um novo método no arquivo ValidacaoXML.cs com o nome ValidarDocumentoXML conforme o código abaixo:
public bool ValidarDocumentoXML(string xmlPath, string xsdPath)
{
try
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(null, xsdPath);
settings.ValidationType = ValidationType.Schema;
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(xmlPath);
XmlReader xmlReader = XmlReader.Create(new StringReader(xmlDocument.InnerXml), settings);
while (xmlReader.Read()) { }
return true;
}
catch (Exception ex)
{
Console.Write(ex.Message);
return false;
}
}
|
Vimos assim como realizar a validação de um arquivo XML contra um arquivo de esquema (.XSD) de uma forma bem simples e objetiva.
Pegue o projeto completo
aqui :
Validando_XML.zip
"Porque já estais mortos, e a vossa vida esta escondida com Cristo em Deus." Colossenses 3:3
Referências: