Ler XSD e Validar XML

Escrever este artigo surgiu da necessidade de um amigo através de uma conversa por Skype®.
A necessidade dele era ler o arquivo XSD e não apenas validar o XML contra o XSD.
Aproveitando o gancho, eu fiz as duas coisas. A leitura do XSD e a validação pelo XSD.

Se você não sabe o que é um XSD: http://pt.wikipedia.org/wiki/XML_Schema

Eu não vou ensinar aqui a criar o XSD, pois isso daria assunto para outro artigo. 🙂
Caso queiram aprender a criar o XSD: http://www.w3schools.com/schema/schema_intro.asp

Ok! Agora que já temos uma base e já sabemos do que se trata. Vamos ao que interessa.

Primeiramente iremos criar o nosso XSD de validação do XML.
Irei chamar de endereco.xsd

<?xml version="1.0" encoding="utf-8"?>
<xs:schema
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
	elementFormDefault="qualified"
	attributeFormDefault="unqualified"
>

	<!--definir os tipos primários do nosso xml-->
	<xs:simpleType name="TUF">
		<xs:annotation>
			<xs:documentation>Estado para usar no endereço</xs:documentation>
		</xs:annotation>
		<xs:restriction base="xs:string">
			<xs:enumeration value="AC"/>
			<xs:enumeration value="AL"/>
			<xs:enumeration value="AM"/>
			<xs:enumeration value="AP"/>
			<xs:enumeration value="BA"/>
			<xs:enumeration value="CE"/>
			<xs:enumeration value="DF"/>
			<xs:enumeration value="ES"/>
			<xs:enumeration value="GO"/>
			<xs:enumeration value="MA"/>
			<xs:enumeration value="MG"/>
			<xs:enumeration value="MS"/>
			<xs:enumeration value="MT"/>
			<xs:enumeration value="PA"/>
			<xs:enumeration value="PB"/>
			<xs:enumeration value="PE"/>
			<xs:enumeration value="PI"/>
			<xs:enumeration value="PR"/>
			<xs:enumeration value="RJ"/>
			<xs:enumeration value="RN"/>
			<xs:enumeration value="RO"/>
			<xs:enumeration value="RR"/>
			<xs:enumeration value="RS"/>
			<xs:enumeration value="SC"/>
			<xs:enumeration value="SE"/>
			<xs:enumeration value="SP"/>
			<xs:enumeration value="TO"/>
		</xs:restriction>
	</xs:simpleType>

	<xs:simpleType name="TCEP">
		<xs:annotation>
			<xs:documentation>Tipo CEP</xs:documentation>
		</xs:annotation>
		<xs:restriction base="xs:string">
			<xs:pattern value="[0-9\-]{9}"/>
		</xs:restriction>
	</xs:simpleType>

	<!--definir a estrutura do xml-->
	<xs:element name="enderecos">
		<xs:complexType>
			<xs:sequence>
				<xs:element name ="endereco" maxOccurs="unbounded">
					<xs:complexType>
						<xs:sequence>
							<xs:element name="logradouro" type="xs:string"></xs:element>
							<xs:element name ="numero" type="xs:integer"></xs:element>
							<xs:element name="estado" type="TUF"></xs:element>
							<xs:element name="cep" type="TCEP"></xs:element>
							<xs:element name="bairro" type="xs:string"></xs:element>
							<xs:element name="cidade" type="xs:string"></xs:element>
						</xs:sequence>
					</xs:complexType>
				</xs:element>
			</xs:sequence>
		</xs:complexType>
	</xs:element>
</xs:schema>

Ok! Criado o nosso xsd. Iremos criar mais dois arquivos endereco_erro.xml e endereco_ok.xml. Como os próprios nomes já dizem um com erro e um sem erro, para podermos testar nosso xsd.

endereco_erro.xml

<?xml version="1.0" encoding="utf-8" ?>
<enderecos>
	<endereco>
		<logradouro>rua nono NoNo no no </logradouro>
		<numero>123</numero>
		<estado>XX</estado>
		<cep>XXs111</cep>
		<bairro>NonnoNon</bairro>
		<cidade>Non on o nNOn</cidade>
	</endereco>
</enderecos>

endereco_ok.xml

<?xml version="1.0" encoding="utf-8" ?>
<enderecos>
	<endereco>
		<logradouro>rua nono NoNo no no </logradouro>
		<numero>123</numero>
		<estado>SP</estado>
		<cep>11111-111</cep>
		<bairro>NonnoNon</bairro>
		<cidade>Non on o nNOn</cidade>
	</endereco>
</enderecos>

Ok! Já temos os nossos xml’s e o nosso xsd. Agora precisamos do nosso aplicativo para ler o xsd e validar os xmls.

Para isso crie uma aplicação console no Visual Studio e cole o código abaixo na classe program.cs

Prestem atenção nas linhas em destaque. São nelas que iremos definir o nosso evento que irá capturar o erro do XML.

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Schema;

namespace XSD_XML
{
    class Program
    {
        static void Main(string[] args)
        {
            #region Ler o XSD

            WriteConsole("Lendo definição do arquivo XSD");
            //primeiro vamos ler nosso xsd. e ver suas definições
            XmlSchema schema = XmlSchema.Read(new XmlTextReader("xsd/endereco.xsd"), null);

            //lista os namespaces
            XmlQualifiedName[] namespaces = schema.Namespaces.ToArray();
            foreach (XmlQualifiedName item in namespaces)
                Console.WriteLine(string.Format("Nome: {0} Namespace: {1}", item.Name, item.Namespace));

            //lista os tipos
            string[] nomeTipo = null;

            foreach (object item in schema.Items)
            {
                nomeTipo = new string[3];

                if (item is XmlSchemaSimpleType)
                {
                    XmlSchemaSimpleType sType = item as XmlSchemaSimpleType;
                    nomeTipo[0] = sType.Name;
                    nomeTipo[1] = "SimpleType";

                    //lista as restrições deste tipo. Se houver
                    XmlSchemaSimpleTypeRestriction restriction = sType.Content as XmlSchemaSimpleTypeRestriction;
                    if (restriction != null)
                    {
                        foreach (XmlSchemaFacet facet in restriction.Facets)
                            nomeTipo[2] += facet.Value + ",";
                    }

                    Console.WriteLine(string.Format("Nome: {0} Tipo: {1} Restrição:{2} ", nomeTipo));
                }
                else if (item is XmlSchemaElement)
                {
                    //tipo elemento
                    XmlSchemaElement eType = item as XmlSchemaElement;
                    nomeTipo[0] = eType.Name;
                    nomeTipo[1] = eType.SchemaTypeName.Name;
                    nomeTipo[2] = "Não Tem";

                    Console.WriteLine(string.Format("Nome: {0} Tipo: {1} Restrição:{2} ", nomeTipo));

                    //le os itens deste elemento
                    WriteItens(eType);
                }
            }
            #endregion

            //criar o settings
            XmlReaderSettings settings = new XmlReaderSettings();

            /*
             * ATENÇÃO:
             * Aqui iremos definir o evento que será chamado se nosso xml tiver erros
             */

            settings.ValidationEventHandler += new ValidationEventHandler(validatingReader_ValidationEventHandler);
            settings.ValidationType = ValidationType.Schema;
            settings.Schemas.Add(schema);

            //abrir o xml com erro
            XmlReader validatingReader = XmlReader.Create("xml/endereco_erro.xml", settings);

            ////validar o xml
            WriteConsole("Validando o XML com erros");
            while (validatingReader.Read()) { };

            //xml sem erros
            validatingReader = XmlReader.Create("xml/endereco_ok.xml", settings);
            WriteConsole("Validando o XML sem erros");
            while (validatingReader.Read()) { };
            Console.ReadKey();
        }

        /// <summary>
        /// escreve os items de um elemento
        /// </summary>
        /// <param name="element">elemento xml</param>
        private static void WriteItens(XmlSchemaElement element)
        {
            System.Xml.Schema.XmlSchemaType type = element.SchemaType as System.Xml.Schema.XmlSchemaType;
            if (type == null) return;

            System.Xml.Schema.XmlSchemaComplexType complex = type as System.Xml.Schema.XmlSchemaComplexType;
            if (complex == null) return;

            System.Xml.Schema.XmlSchemaSequence sequence = complex.Particle as System.Xml.Schema.XmlSchemaSequence;
            if (sequence == null) return;

            WriteConsole("Linhas do tipo complexo", ConsoleColor.DarkMagenta);

            foreach (XmlSchemaElement item in sequence.Items)
            {
                Console.WriteLine(string.Format("Nome: {0}", item.Name));
            }
        }

        /// <summary>
        /// método de validação do XML. É aqui que iremos tratar o erro do nosso XML.
        /// </summary>
        /// <param name="sender">objeto que chamou o método</param>
        /// <param name="e">argumentos do evento</param>
        static void validatingReader_ValidationEventHandler(object sender, ValidationEventArgs e)
        {
            WriteConsole(e.Message, ConsoleColor.Red);
        }

        /// <summary>
        /// escreve uma linha no console
        /// </summary>
        /// <param name="message">mensagem</param>
        /// <param name="color">cor da mensagem</param>
        private static void WriteConsole(string message, ConsoleColor color)
        {
            Console.ForegroundColor = color;
            Console.WriteLine(message);
            Console.ResetColor();
        }

        /// <summary>
        /// Escreve uma linha no console. Cor padrão azul
        /// </summary>
        /// <param name="message">mensagem</param>
        private static void WriteConsole(string message)
        {
            WriteConsole(message, ConsoleColor.Blue);
        }

    }
}

Link para o download do projeto de exemplo. (formato .zip Visual Studio 2010) [download id=’16’]


É isso ai pessoal 🙂
Até o próximo
♦ Marcelo

Marcelo

Nascido em Juruaia/MG em uma fazenda de criação de búfalos, e residindo na região Sul do Brasil.
Trabalha com desenvolvimento de aplicações desde os 17 anos. Atualmente é Arquiteto Organizacional na Unimake Software.
Para saber mais ... http://desenvolvedores.net/marcelo
[]'s

Você vai gostar de...

Postagens populares.

2 Comments

  1. Olá tudo bem ?
    Poderia me enviar um retorno no email… precisava de um favor seu.. se pudesse me ajudar. obrigado !

    Att,

    Heitor Lima

    1. Olá Heitor.

      Enviei um e-mail para você.
      []’s

Deixe um comentário

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.