Olá amigos! Neste pequeno artigo pretendo mostrar uma forma de validar seus arquivos XML baseados em seus Schemas (XSD). Se você tem dúvidas a respeito de XML e XSD, sugiro que dê uma olhada no site W3Schools, que é uma ótima fonte de referência sobre desenvolvimento voltado para a web.
Pré-Requisitos
Os exemplos abaixo utilizam a classe DomDocument disponível na biblioteca DOM do PHP 5.
Windows
Certifique-se de que você possui o arquivo php_dom.dll em seu diretório de extensões, e que no arquivo php.ini existe uma referência à essa biblioteca: extension=php_dom.dll.
Linux
O PHP deve ser compilado com o parâmetro --with-dom. Se precisar, mais informações sobre essa extensão podem ser obtidas no manual do PHP: http://br2.php.net/manual/pt_BR/ref.dom.php.
Mas por quê usar XSD?
Além de verificar a sintaxe de um arquivo XML, é preciso também checar se os dados nele contidos também são válidos de acordo com a aplicação que irá utilizá-los. Com a validação de XML via XSD, é possível determinar a freqüencia em que certos elementos podem aparecer em seu arquivo, definir tipos de dados para garantir a integridade das informações, especificar a ordem em que aparecem os elementos, entre outras utilidades.
Por essas razões, XSD é considerado muito mais poderoso que os DTDs (Document Type Definitions), onde seu poder de definição de regras é bem mais limitado.
Obs.: Mais informações sobre DTD podem ser obtidas no W3Schools.
E onde eu uso isso?
Muitas aplicações web hoje em dia fornecem uma API para que outras aplicações possam fazer requisições a ela utilizando XML como linguagem intermediária. Porém, para evitar o recebimento de instruções mal-formadas no arquivo XML, geralmente são fornecidos XSDs que contém as regras de formação das requisições, verificando diversos fatores já citados como a ordem dos elementos no arquivo. Com isso, espera-se que você crie uma aplicação que utilize os arquivos XSD para validar suas requisições antes de enviá-las, economizando tempo e banda.
Exemplo: Catálogo de Livros
Vamos trabalhar em cima de um simples e hipotético sistema de catálogo de livros. Suponhamos que o sistema utilize como banco de dados arquivos XML formatados conforme o exemplo abaixo:
<?xml version="1.0"?>
<catalogo>
<livro>
<isbn>8504006115</isbn>
<autor>George Orwell</autor>
<titulo>1984</titulo>
<paginas>302</paginas>
</livro>
<livro>
<isbn>8588639173</isbn>
<autor>Ramez Elmasri</autor>
<autor>Shamkant Navathe</autor>
<titulo>Sistemas de Bancos de Dados</titulo>
<paginas>744</paginas>
<editora>744</editora>
</livro>
</catalogo>
Como vocês puderam perceber, no nosso segundo livro, a tag autor aparece duas vezes. Utilizando XSD é possível estabelecer regras que determinam a freqüencia com a qual determinadas tags podem aparecer. Baseado na forma de organização que desejamos para o nosso arquivo XML, podemos abstrair algumas regras:
- Todo livro deve ter um único ISBN
- Todo livro deve ter pelo menos um autor e no máximo N autores
- Todo livro deve ter um único título
- Todo livro deve ter uma especificação do número de páginas
- O nome da editora é opcional, e assume-se que apenas uma editora tenha os direitos de publicação da obra.
- A ordem de aparição dos dados deve ser: ISBN, autor, titulo e número de páginas
Essas definições estão bem longe da realidade, mas para o nosso exemplo servem muito bem. Transformando isso em uma definição de esquema pra XML (XSD), nosso arquivo ficaria da seguinte maneira:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- Este é o nosso nó principal -->
<xs:element name="catalogo">
<!-- Define um tipo formado por outros elementos -->
<xs:complexType>
<!-- Determina que os elementos a seguir devem aparecer nesta mesma ordem -->
<xs:sequence>
<!-- Define que o tipo "livro" pode ocorrer N vezes (unbounded = sem limite)-->
<xs:element name="livro" maxOccurs="unbounded">
<!-- Define que "livro" é formado por outros elementos -->
<xs:complexType>
<!-- Os componentes de "livro" devem aparecer nessa ordem -->
<xs:sequence>
<!-- Define o ISBN -->
<xs:element name="isbn">
<!-- Define como tipo simples por não ser formado por outros elementos -->
<xs:simpleType>
<!-- Define o tipo "string" para ISBN e informa que existem restrições -->
<xs:restriction base="xs:string">
<!-- Determina como 10 o tamanho máximo -->
<xs:length value="10"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<!-- Define que o elemento "autor" é obrigatório mas pode aparecer N vezes -->
<xs:element name="autor" type="xs:string" minOccurs="1" maxOccurs="unbounded"/>
<!-- O valor-padrão para minOccurs e maxOccurs é 1 quando não forem definidos -->
<xs:element name="titulo" type="xs:string"/>
<xs:element name="paginas" type="xs:integer"/>
<!-- Elemento editora não é obrigatório -->
<xs:element name="editora" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Pronto! Agora você já tem um XSD para poder validar seus arquivos XML!
Obs.: Novamente reforço o conselho: para mais informações sobre como criar corretamente seu schema, visite o site W3Schools! Este é o link para o tutorial de XSD: http://www.w3schools.com/schema/default.asp.
PHP Entra em Cena
Depois de criar seus Schemas, basta criar o código PHP responsável pela validação do XML. Graças à biblioteca php-dom, essa tarefa se torna bem mais fácil.
<?php
/**
* Ao tentar validar um arquivo XML, se algum erro
* for encontrado a libxml irá gerar Warnings, o que
* não creio que seja o mais interessante para nós.
* Para evitar que isso aconteça, você pode determinar
* que irá obter os erros por sua própria conta. Lembre-se
* que esta função abaixo deve ser chamada antes de
* instanciar qualquer objeto da classe DomDocument!
*/
libxml_use_internal_errors(true);
/* Cria um novo objeto da classe DomDocument */
$objDom = new DomDocument();
/* Carrega o arquivo XML */
$objDom->load("catalogo.xml");
/* Tenta validar os dados utilizando o arquivo XSD */
if (!$objDom->schemaValidate("catalogo.xsd")) {
/**
* Se não foi possível validar, você pode capturar
* todos os erros em um array
*/
$arrayAllErrors = libxml_get_errors();
/**
* Cada elemento do array $arrayAllErrors
* será um objeto do tipo LibXmlError
*/
print_r($arrayAllErrors);
} else {
/* XML validado! */
echo "XML obedece às regras definidas no arquivo XSD!";
}
?>
Se quiser, agora você pode abrir o arquivo catalogo.xml e remover algumas tags para ver quais os erros que serão exibidos na tela.
Finalizando
Agora que ficou fácil validar os arquivos XML com seus Schemas, você já pode criar APIs para seus sistemas com uma interface XML, e disponibilizar aos softwares clientes não somente os arquivos XSD, mas também classes que já façam essa validação. Enfim, exemplos não faltam!
Downloads
Código PHP, arquivos XML e XSD: http://downloads.padron.blog.br/artigos/validando_xml/codigos.zip