XML: Mais sobre XSD

Introdução

Este é o último artigo desta série sobre XML. No primeiro artigo você foi apresentando a XML, no segundo artigo foi mostrado o que é um documento XML válido e como é possível validar-lo, no penúltimo artigo foram dados os primeiros passos para a criação de um XML Schema (Esquema XML). Neste último artigo serão apresentadas mais restrições e regras utilizadas no XML Schema, também designado como XSD (XML Schema Definition - Definição de Esquema XML). Então vamos lá e fique atento para não perder nada.

Obs1: No decorre do artigo a criação do arquivo XSD será baseado no namespace "http://www.w3.org/2001/XMLSchema", para maiores esclarecimentos leia o segundo artigo desta série.

Obs2: Devido este artigo ser uma continuação direta do terceiro artigo da série, assim como lá deste ponto por diante serão apresentados exemplos explicados para facilitar a sua compreensão.

Utilizando lista de valores

Pode-se definir uma lista de valores possíveis através de um conjunto enumerado.

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
...
    <xsd:element name="estado_civil_1">
        <xsd:simpleType>
            <xsd:restriction base="xsd:string">
                <xsd:enumeration value="Solteiro(a)"/>
                <xsd:enumeration value="Casado(a)"/>
                <xsd:enumeration value="Divorciado(a)"/>
                <xsd:enumaration value="Viuvo(a)"/>
            </xsd:restriction>
        </xsd:simpleType>
    </xsd:element>
...
    <xsd:element name="estado_civil_2" type="tpEstCivil"/>

    <xsd:simpleType name="tpEstCivil">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="Solteiro(a)"/>
            <xsd:enumeration value="Casado(a)"/>
            <xsd:enumeration value="Divorciado(a)"/>
            <xsd:enumaration value="Viuvo(a)"/>
        </xsd:restriction>
    </xsd:simpleType>
...
</xsd:schema>

Explicando o esquema

O elemento estado_civil_1 é do tipo xsd:string e só pode assumir os valores Solteiro(a), Casado(a), Divorciado(a) e Viuvo(a). O elemento estado_civil_2 é do tipo tpEstCivil, sendo esse um tipo simples declarado logo abaixo, com os mesmos valores do elemento estado_civil_1.

Esse esquema mostrou duas maneiras para se criar listas com conjuntos enumerados, nos dois casos o resultado da validação será a mesma, cabendo ao desenvolvedor do esquema escolher o que melhor se aplica a cada caso.

Declarando elemento complexo através de tipo

No exemplo anterior o elemento simples estado_civil_2 foi declarado como sendo do tipo tpEstCivil. Da mesma maneira pode-se declarar um elemento complexo através de um tipo complexo pré-definido no projeto.
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
...
    <xsd:element name="professor" type="tpPessoa"/>
    <xsd:element name="aluno" type="tpPessoa"/>
...
    <xsd:complexType name="tpPessoa">
        <xsd:sequence>
            <xsd:element name="nome" type="xsd:string"/>
            <xsd:element name="idade" type="xsd:integer"/>
        </xsd:sequence>
    </xsd:complexType>
...
    <xsd:element name="empregado" type="tpPessoa_2"/>
...
    <xsd:complexType name="tpPessoa_2">
        <xsd:complexContent>
            <xsd:extension base="tpPessoa">
                <xsd:sequence>
                    <xsd:element name="setor" type="xsd:string"/>
                    <xsd:element name="cargo" type="xsd:string"/>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
...
</xsd:schema>

Explicando o esquema

Os elementos professoraluno são do tipo tpPessoa que é um tipo complexo declarado no mesmo esquema. O tipo complexo tpPessoa tem os atributos nome e idade do tipo xsd:string e xsd:integer respectivamente.

O elemento empregado é do tipo complexo tpPessoa_2. Esse tipo complexo herda os atributos do tipo complexo tpPessoa e inclui os atributos setor e cargo, ambos do tipo xsd:string. Perceba que foi dito herda, pois assim como no paradigma orientado a objetos (POO), a XML permite a herança, mas neste caso apenas de características, enquanto que em POOherança vai além disso.

Elemento complexo só com atributo

Um elemento complexo pode ser definido para conter apenas atributos.

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
...
    <xsd:element name="semestre">
        <xsd:complexType>
            <xsd:attribute name="id" type="xsd:positiveInteger"/>
        </xsd:complexType>
    </xsd:element>
...
</xsd:schema>

Explicando o esquema

O elemento semestre não conterá nenhum elemento ou valor agregado a sua declaração no documento XML. O único dado que será colocado na sua declaração será um valor para o atributo id que é do tipo xsd:positiveInteger, ou seja, só aceitará valores inteiros e possitivos.

Elemento complexo só com valor

Um elemento complexo pode ser definido para conter apenas valores.

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
...
    <xsd:element name="curso" type="tpCurso"/>
...
    <xsd:complexType name="tpCurso">
        <xsd:simpleContent>
            <xsd:extension base="xsd:string"/>
        </xsd:simpleContent>
    </xsd:complexType>
...
</xsd:schema>

Explicando o esquema

O elemento curso é do tipo tpCurso que pela definição só aceitarar um valor do tipo xsd:string.

Elemento complexo com conteúdo misto

Um elemento complexo pode conter valores e outros elementos.

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <xsd:element name="carta" type="tpSolicitacao"/>

    <xsd:complexType name="tpSolicitacao" mixed="true">
        <xsd:sequence>
            <xsd:element name="nome" type="xsd:string"/>
            <xsd:element name="idSolicitacao" type="xsd:positiveInteger"/>
            <xsd:element name="data" type="xsd:date"/>
        </xsd:sequence>
    </xsd:complexType>

</xsd:schema>

Explicando o esquema

O elemento carta é do tipo tpSolicitacao, o atributo mixed desse tipo está declarado como true, indicando que ele é um elemento misto, isso significa que além dos elementos nome, idSolicitacao e data ele também pode receber valores. Veja no exemplo abaixo um possível documento XML que pode ser validado pelo esquema anterior:

<?xml version="1.0" encoding="UTF-8"?>
<carta>
  Caro <nome>Tadeu Pereira</nome>, sua solicitação <idSolicitacao>1234</idSolicitacao> 
foi recebida em <data>2015-01-27</data> e será encaminhada para o avaliação.
</carta>

Indicando a ordem dos elementos

A ordem dos elementos filhos de um elemento complexo pode variar de acordo com a necessidade do esquema.

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
...
    <xsd:element name="disciplina">
        <xsd:complexType>
            <xsd:all>
                <xsd:element name="idDisciplina" type="xsd:string"/>
                <xsd:element name="Nome" type="xsd:string"/>
                <xsd:element name="professor" type="tpPessoa"/>
            </xsd:all>
        </xsd:complexType>
    </xsd:element>
...
    <xsd:element name="membro">
        <xsd:complexType>
            <xsd:choice>
                <xsd:element name="professor" type="tpPessoa"/>
                <xsd:element name="aluno" type="tpPessoa"/>
            </xsd:choice>
        </xsd:complexType>
    </xsd:element>
...
    <xsd:element name="curso">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="nome" type="xsd:string"/>
                <xsd:element name="qtSemestre" type="xsd:positiveInteger"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
...
</xsd:schema>

Explicando o esquema

O elemento <xsd:all> informa que os elementos filhos de disciplina podem aparecer em qualquer ordem, mas cada elemento filho deve ocorrer apenas 1 (uma) única vez. Uma possível alteração seria <xsd:all minOccurs="0">, neste caso os elementos filhos podem aparecer em qualquer ordem, mas os mesmos devem ocorrer 0 (zero) ou 1 (uma) vez.

No elemento membro tem o elemento <xsd:choice>, esse elemento indica que só pode ser informado 1 (um) dos 2 (dois) elementos filhos, em outras palavras, no documento XML que será validado pelo esquema, deve ser informado um elemento filho professor ou um elemento filho aluno.

Já o elemento curso utiliza o elemento <xsd:sequence> indicando que os elementos filhos devem ocorrer na ordem informada, dessa maneira o elemento filho nome deve ser colocado obrigatoriamente antes do elemento filho qtSemestre.

Quantidade de ocorrência

Pode-se informar a quantidade mínima e máxima que um elemento pode ocorre no documento XML.

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
...
    <xsd:element name="nota" minOccurs="0" maxOccurs="unbounded">
...
</xsd:schema>

Explicando o esquema

O atributo minOccurs especifica o número mínimo de ocorrência do elemento nota dentro do documento XML, por sua vez, o atributo maxOccurs especifica o número máximo de ocorrência do mesmo elemento. O valor unbounded dado ao atritubo maxOccurs está informando que não exisitra um limite máximo de ocorrência, embora fosse possível entrar com um valor inteiro positivo no seu lugar como por exemplo maxOccurs="100", isto indicaria que o número máximo de ocorrência não poderia ser superior a 100 (cem).

Vamos brincar um pouco

Só para fechar essa série de artigos sobre XML, analise o XML Schema abaixo e comente se é possível criar um documento XML válido tendo como base o mesmo.

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <xsd:element name="notas">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="nota" minOccurs="0" maxOccurs="unbounded">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="aluno" type="tpPessoa"/>
                            <xsd:element name="disciplinas" minOccurs="0" maxOccurs="5">
                                <xsd:complexType>
                                    <xsd:sequence>
                                        <xsd:element name="disciplina">
                                            <xsd:complexType>
                                                <xsd:all>
                                                    <xsd:element name="idDisciplina" type="xsd:string"/>
                                                    <xsd:element name="Nome" type="xsd:string"/>
                                                    <xsd:element name="professor" type="tpPessoa"/>
                                                </xsd:all>
                                            </xsd:complexType>
                                        </xsd:element>
                                        <xsd:element name="av1" type="xsd:positiveInteger" />
                                        <xsd:element name="av2" type="xsd:positiveInteger" />
                                        <xsd:element name="avf" type="xsd:positiveInteger" />
                                    </xsd:sequence>
                                </xsd:complexType>
                            </xsd:element>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element name="notas">
</xsd:schema>

Conclusão

Este artigo finaliza esta série sobre XML, mas vale ressaltar que o assunto não foi esgotado, podendo e devendo ser aprofundado por todos, tanto da área de banco de dados, quanto de programação. O motivo é bem simples, a XML é muito utilizada para transferir dados entre aplicativos, logo o conhecimento de como criar, ler e validar informações dos documentos XML é muito importante nos tempos atuais onde a heterogeneidade de hardware e software é cada vez mais comum.

Não deixe de lê os outros três artigos desta série.

Até o próximo artigo.