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
Olá tudo bem ?
Poderia me enviar um retorno no email… precisava de um favor seu.. se pudesse me ajudar. obrigado !
Att,
Heitor Lima
Olá Heitor.
Enviei um e-mail para você.
[]’s