Validando XML Schema em .NET

O que XML Schema? Onde é usado

Recentemente precisei trabalhar com algum formato de arquivos em XML e resolvi fazer um XML Schema.

Mas pra que serve esse tal de XML Schema?

Basicamente o XML Schema é um formato para detalhar ainda mais um arquivo XML. O XML descreve uma estrutura de namespaces, nós, valores, atributos que podem ser usados arbitrariamente por uma aplicação, porém, se quisermos restringir mais ainda o formato, podemos usar um XML Schema.

O XML Schema determina: tipos de valores dos nós, seqüência de nós, ordem, qual nó é valido dentro de outro nó e assim sucessivamente.

É um padrão relativamente complexo, mas que paga o preço, já que muitas ferramentas sabem lidar com esse formato e praticamente toda framework de desenvolvimento hoje sabe validar um XML contra um Schema.

De uns tempos pra cá tem sido usado em muitos lugares, entre eles:

  • Visual Studio: Para gerar classes a partir de XSD
  • Protocolo SOAP: É utilizado internamente pelo protocolo SOAP para detalhar o formato dos tipos e valores das chamadas
  • Ferramentas de integração como SAP PI (Process Integration) e outras

Por essas e outra razões, vale a pena usar.

Exemplos

Os exemplos abaixo foram extraídos do W3Schools:

Exemplo de um arquivo XML:

<?xml version="1.0" encoding="ISO-8859-1"?>

<shiporder orderid="889923"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="shiporder.xsd">
  <orderperson>John Smith</orderperson>
  <shipto>
    <name>Ola Nordmann</name>
    <address>Langgt 23</address>
    <city>4000 Stavanger</city>
    <country>Norway</country>
  </shipto>
  <item>
    <title>Empire Burlesque</title>
    <note>Special Edition</note>
    <quantity>1</quantity>
    <price>10.90</price>
  </item>
  <item>
    <title>Hide your heart</title>
    <quantity>1</quantity>
    <price>9.90</price>
  </item>
</shiporder>

Exemplo de um XSD que valida o XML acima:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="shiporder">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="orderperson" type="xs:string"/>
      <xs:element name="shipto">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="address" type="xs:string"/>
            <xs:element name="city" type="xs:string"/>
            <xs:element name="country" type="xs:string"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="item" maxOccurs="unbounded">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="title" type="xs:string"/>
            <xs:element name="note" type="xs:string" minOccurs="0"/>
            <xs:element name="quantity" type="xs:positiveInteger"/>
            <xs:element name="price" type="xs:decimal"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
    <xs:attribute name="orderid" type="xs:string" use="required"/>
  </xs:complexType>
</xs:element>

</xs:schema>

Como validar um XSD em .NET

Na framework do .NET, temos prontinho como validar um XSD. Houveram algumas mudanças recentes, algumas API’s antigas foram anotadas como “deprecated”. Por isso, me motivei a jogar isso num post.

  public class SchemaValidator
  {
    public bool ValidationErrors = false;

    public void ValidateXML(string XMLFile, string XSDFile)
    {
      this.ValidationErrors = false;

      FileStream xsdStream = new FileStream(XSDFile, FileMode.Open);
      FileStream xmlStream = new FileStream(XMLFile, FileMode.Open);

      XmlReader schemaReader = XmlReader.Create(xsdStream);

      XmlReaderSettings readerSettings = new XmlReaderSettings();
      readerSettings.ValidationType = ValidationType.Schema;
      readerSettings.Schemas.Add("", schemaReader);
      readerSettings.ValidationEventHandler += OnValidate;

      this.ValidationErrors = false;
      XmlReader xr = XmlReader.Create(xmlStream, readerSettings);
      using (xr)
        while (xr.Read()) ;

      xsdStream.Close();
      xmlStream.Close();
    }

    private void OnValidate(object sender, ValidationEventArgs e)
    {
      this.ValidationErrors = true;
      Console.WriteLine(e.Message);
    }

  }

Como o XmlReader lê o XML em pedaços, sem a necessidade de carregá-lo todo para memória, a validação do schema também ocorre em pedaços. Por essa razão existe a necessidade de assinar o evento OnValidate e verificar se houve erro na validação.

MSBuild

Para quem gosta de MSBuild, a task Xml do MSBuild Extensions Pack possui uma task prontinha para usá-la.

Tutorial completo

Lá no W3Schools tem um tutorial completinho de XML Schema: XML Schema Tutorial.

Código fonte

Segue o código fonte de exemplo: SchemaValidation.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s