Validando XML no PHP

Garanta a integridade de dados e valide documentos XML em um esquema XML no PHP

Geralmente, os desenvolvedores em PHP necessitam de serviços de um analisador Extensible Markup Language (XML) em seu código. Juntamente com essas linhas, normalmente precisam validar a entrada XML. Felizmente, é possível realizar isso facilmente no PHP. Este artigo mostra como validar documentos XML dentro do PHP e determinar a causa das falhas de validação.

Brian M. Carey, Senior Systems Engineer, Triangle Information Solutions

Photo of Brian CareyBrian Carey é um consultor de sistemas de informação especializado na arquitetura, design e implementação de aplicativos corporativos Java.



01/Dez/2009

Por que a validação XML?

XML é uma linguagem de marcações que permite que você, como um desenvolvedor, crie sua própria linguagem customizada. Esta linguagem é, então, usada para transportar, mas não necessariamente exibir, dados de forma independente da plataforma. A linguagem é definida com o uso de tags de marcação, de forma semelhante ao Hypertext Markup Language (HTML).

O XML cresceu em popularidade nos últimos anos porque representa o melhor de dois mundos: Ele é facilmente legível pelos usuários e por computadores do mesmo modo. As linguagens XML são expressadas como estrutura em árvore com elementos e atributos descrevendo dados importantes. Os nomes de elementos e atributos são, geralmente, escritos em inglês simples (portanto, é possível entendê-los). Elas também são altamente estruturadas (portanto, computadores podem analisá-las).

Agora, por exemplo, suponha que você crie sua própria linguagem XML, chamada LuresXML. LuresXML simplesmente define um meio para definição de vários tipos de atrativos que são oferecidos em seu Web site. Primeiro, crie um esquema XML que define como o documento XML deverá parecer, como em Lista 1.

Lista 1. lures.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="lures">
 <xs:complexType>
  <xs:sequence>
   <xs:element name="lure">
    <xs:complexType>
     <xs:sequence>
     <xs:element name="lureName" type="xs:string"/>
     <xs:element name="lureCompany" type="xs:string"/>
     <xs:element name="lureQuantity" type="xs:integer"/>
     </xs:sequence>
    </xs:complexType>
   </xs:element>
  </xs:sequence>
 </xs:complexType>
</xs:element>
</xs:schema>

Este é, intencionalmente, um exemplo bastante simples. O elemento-raiz é chamado de lures. Ele é o elemento-pai de um ou mais elementos lure , cada um dos quais é o pai de três outros elementos. O primeiro elemento é o nome do atrativo (lureName). O segundo elemento é o nome da empresa que fabrica o atrativo (lureCompany). E, finalmente, o último elemento é a quantidade (lureQuantity), ou quantos atrativos sua empresa possui no inventário. Os dois primeiros desses elementos filho são definidos como cadeias de caracteres, considerando que o elemento lureQuantity esteja definido como um número inteiro.

Agora, digamos que você deseje criar um documento XML (às vezes chamado de instância) com base nesse esquema. Ele talvez seja semelhante a algo como a Lista 2.

Lista 2. lures.xml
<lures>
 <lure>
  <lureName>Silver Spoon</lureName>
  <lureCompany>Clark</lureCompany>
  <lureQuantity>Seven</lureQuantity>
 </lure>
</lures>

Esta é uma instância de documento XML simples do esquema da Lista 1. Neste caso, a instância do documento lista apenas um atrativo. O nome do atrativo é Silver Spoon. A empresa fabricante é Clark. E a quantidade em mãos é Seven.

Esta é a questão: Como saber se o documento XML na Lista 2 é uma instância apropriada do esquema definido na Lista 1? De fato, não é (isso também é intencional).

Observe o elemento lureQuantity conforme definido na Lista 1. Ele é do tipo xs:integer. Ainda na Lista 2 , o elemento lureQuantity contém, na verdade, uma palavra (Seven), não um número inteiro.

o propósito da validação XML é capturar exatamente esses tipos de erros. A validação apropriada garante que um documento XML corresponda com as regras definidas em seu esquema.

Continuando com este exemplo, ao tentar validar o documento XML na Lista 2, um erro é emitido. Corrija esse erro (trocando Seven por um 7) antes de usar o documento dentro de seu aplicativo de software.

A validação XML é importante porque você deseja capturar erros o mais cedo possível no processo de troca de informações. Caso contrário, resultados imprevisíveis podem ocorrer se, ao tentar analisar um documento XML, ele contiver tipos de dados inválidos ou uma estrutura inesperada.

Análise XML simples em PHP

Está além do escopo deste artigo fornecer uma visão geral detalhada sobre a análise de documentos XML em PHP. Entretanto, abordo os conceitos básicos do carregamento de um documento XML em PHP.

Para manter as coisas simples, continue usando o esquema da Lista 1 e o documento XML da Lista 2. Lista 3 demonstra alguns códigos PHP básicos para carregamento do documento XML.

Lista 3. testxml.php
<?php

$xml = new DOMDocument();
$xml->load('./lures.xml');

?>

Tampouco há algo de complicado nisso. Você está usando a classe DOMDocument para carregar o documento XML, chamado aqui de lures.xml. Observe que, para este código funcionar em seu próprio servidor PHP, o arquivo lures.xml deve residir no mesmo caminho que o código PHP.

Neste ponto, ele está tentando iniciar a análise do documento XML. Entretanto, conforme foi visto, é melhor, primeiro, validar o documento para garantir que ele corresponda com as especificações da linguagem expressadas no esquema.

Validação XML simples em PHP

Continue incluindo no código PHP na Lista 3 inserindo algum código de validação simples, como na Lista 4.

Lista 4. testxml.php melhorado
<?php

$xml = new DOMDocument();
$xml->load('./lures.xml');

if (!$xml->schemaValidate('./lures.xsd')) {
   echo "invalid<p/>";
}
else {
   echo "validated<p/>";
}

?>

Uma vez mais, observe que o arquivo de esquema da Lista 2 deve estar no mesmo diretório em que o código PHP está localizado. Caso contrário, o PHP retornará um erro.

Este novo código invoca o método schemaValidate no objeto DOMDocument que carregou o XML. O método aceita um parâmetro: o local do esquema XML usado para validar o documento XML. O método retorna um valor booleano em que true indica uma validação bem-sucedida e false indica uma validação malsucedida.

Agora, implemente o código PHP da Lista 3 em seu próprio servidor PHP. Chame-o de testxml.php porque este é o nome dado nas Listas 3 e 4. Certifique-se de que o documento XML (da Lista 2) e o esquema XML (da Lista 1) estejam ambos no mesmo diretório. Uma vez mais, o PHP reporta um erro se este não for o caso.

Aponte seu navegador para testxml.php. Você deverá ver uma palavra simples na tela: "inválido".

A boa notícia é que a validação do esquema está funcionando. Ela deveria retornar um erro, e retornou.

A má notícia é que você não tem ideia alguma de onde está localizado o erro dentro do documento XML. Tudo bem, você talvez saiba por que mencionei a origem do erro anteriormente no artigo. Mas finja que isso não aconteceu, certo?

Há um erro, mas onde?

Para repetir: A má notícia é que você não tem ideia alguma de onde está localizado o erro dentro do documento XML. Ignore. Seria bom se o código PHP, na realidade, relatasse o local do erro, assim como a natureza do erro, para que você pudesse tomar a ação corretiva. Algo parecido com "Atenção! Não posso aceitar uma cadeia de caracteres para lureQuantity" seria bom.

Para visualizar o erro que foi encontrado, é possível usar a função libxml_get_errors() . Infelizmente, a saída de texto dessa função não identifica especificamente onde no documento XML ocorreu o erro. Em vez disso, ela identifica onde no código PHP um erro foi encontrado. Como isso é claramente inútil, você procura uma outra opção.

Há uma outra função PHP chamada libxml_use_internal_errors(). Esta função aceita um valor booleano como seu único parâmetro. Se configurá-lo como true, isso significará que você está desativando o relatório de erro libxml e buscando você mesmo os erros. Isso é o que você faz.

Claro, isso significa que é necessário escrever um pouco mais de código. Mas a recompensa é um relatório de erros mais específico. A longo prazo, isso economiza muito tempo.

Lista 5 mostra o produto concluído.

Lista 5. O testxml.php final
<?php
function libxml_display_error($error)
{
$return = "<br/>\n";
switch ($error->level) {
case LIBXML_ERR_WARNING:
$return .= "<b>Warning $error->code</b>: ";
break;
case LIBXML_ERR_ERROR:
$return .= "<b>Error $error->code</b>: ";
break;
case LIBXML_ERR_FATAL:
$return .= "<b>Fatal Error $error->code</b>: ";
break;
}
$return .= trim($error->message);
if ($error->file) {
$return .= " in <b>$error->file</b>";
}
$return .= " on line <b>$error->line</b>\n";

return $return;
}

function libxml_display_errors() {
$errors = libxml_get_errors();
foreach ($errors as $error) {
print libxml_display_error($error);
}
libxml_clear_errors();
}

// Enable user error handling
libxml_use_internal_errors(true);

$xml = new DOMDocument();
$xml->load('./lures.xml');

if (!$xml->schemaValidate('./lures.xsd')) {
print '<b>Errors Found!</b>';
libxml_display_errors();
}
else {
echo "validated<p/>";
}

?>

Primeiro, observe a função na parte superior da lista de código. Ela é chamada libxml_display_error() e aceita um objeto LibXMLError como seu único parâmetro. Em seguida, ela usa a conhecida instrução de comutação para determinar o nível de erro e criar uma mensagem de erro apropriada para esse nível. Quando o nível é determinado, o código produz uma cadeia de caracteres que relata o nível apropriado.

Em seguida, ocorrem duas outras coisas. Primeiro, o objeto de erro é examinado para determinar se uma propriedade file contém um valor. Se contiver, então esse valor de file será anexado à mensagem de erro para que o local do arquivo seja relatado. Em seguida, a propriedade line é anexada à mensagem de erro para que o usuário possa ver exatamente onde no arquivo XML o erro ocorreu. Não é necessário dizer que isso é extremamente importante para propósitos de depuração.

Também deve ser observado que libxml_display_error() simplesmente produz uma cadeia que descreve o erro. A real impressão do erro na tela é deixada para o responsável pela chamada, neste caso, libxml_display_errors().

A função abaixo dessa é a libxml_display_errors() mencionada anteriormente, que não assume nenhum parâmetro. A primeira coisa que esta função faz é chamar libxml_get_errors(). Isso retorna uma array de objetos LibXMLError que representam todos os erros encontrados quando o método schemaValidate() foi invocado no documento XML.

Em seguida, você passa por cada um dos erros encontrados e invoca a função libxml_display_error() para cada objeto de erro. Qualquer que seja a cadeia retornada por essa função, ela será impressa na tela. Um grande benefício da manipulação de erros dessa forma é que todos os erros são impressos de uma vez. Isso significa que é necessário executar o código apenas uma vez para visualizar todos os erros específicos para esse documento XML em particular.

Finalmente, libxml_clear_errors() limpa os erros recentemente encontrados pelo método schemaValidate() . Isso significa que, se schemaValidate() for executado novamente dentro da mesma sequência de código, você iniciará a partir do zero, e apenas novos erros serão relatados. Se não fizer isso e executar schemaValidate() novamente, então todos os erros da primeira invocação de schemaValidate() permanecerão na array retornada por libxml_get_errors(). Obviamente, isso apresenta problemas se você estiver procurando por um novo conjunto de erros.

Também é importante observar que realizei uma pequena alteração na instrução if-then na parte inferior do código na Lista 5. Se um erro for encontrado, será impresso "Erros Localizados!" em negrito e, em seguida, invocada a função libxml_display_errors() supramencionada, que exibe todos os erros encontrados antes de limpar a array de erro. Optei por esta solução em vez de apenas imprimir "inválido", conforme fiz na Lista 4.

Segundo teste

Agora, é hora de testar novamente. Mova o arquivo PHP da Lista 5 para o seu servidor PHP. Mantenha o mesmo nome de arquivo (testxml.php). Como antes, certifique-se de que o arquivo XML Schema Definition (XSD) e os arquivos XML estejam no mesmo diretório que o arquivo PHP. Aponte seu navegador para testxml.php mais uma vez e, agora, você deverá ver algo como o seguinte:

Erros Localizados!
Erro 1824: Elemento 'lureQuantity': 'Seven' não é um valor válido do tipo atômico 'xs:integer'. em /home/thehope1/public_html/example.xml na linha 5

Bem, isso é bastante descritivo, não é? A mensagem de erro informa em qual linha o erro ocorreu. Ela também informa onde está o arquivo (como se você não soubesse). E ela informa exatamente o motivo da ocorrência do erro. Essa informação você pode usar.

Corrigindo o problema

Agora é possível deixar o arquivo PHP e trabalhar na correção do problema em seu documento XML.

Como o erro relatado ocorreu na linha 5 do documento XML, é uma boa ideia consultar a linha 5 e ver o que há lá. Conforme esperado, a linha 5 é o local do elemento lureQuantity . E, conforme você consulta cuidadosamente a linha, de repente você tem uma revelação de que Seven é uma cadeia, não um número. Assim, você altera a cadeia Seven para o numeral 7. A cópia final do documento XML deverá ser semelhante à Lista 6.

Lista 6. Arquivo XML atualizado
<lures>
 <lure>
  <lureName>Silver Spoon</lureName>
  <lureCompany>Clark</lureCompany>
  <lureQuantity>7</lureQuantity>
 </lure>
</lures>

Agora, copie este novo arquivo XML para o seu servidor PHP. E, uma vez mais, aponte seu navegador para testxml.php. Você deverá ver apenas uma palavra: "validado". Essa é uma excelente notícia por duas razões. Primeiro, significa que o código de validação está funcionando adequadamente porque o documento XML é, de fato, válido. Segundo, você provavelmente validou seu primeiro documento XML em PHP. Parabéns!

Como eu sempre aconselho, agora é hora de consertar. Modifique lures.xsd para torná-lo um esquema mais complexo. Modifique lures.xml para torná-lo uma instância mais complexa desse esquema. Copie esses arquivos para o servidor PHP e, uma vez mais, execute testxml.php. Veja o que acontece. Intencionalmente, produza um documento inválido por várias razões e veja o que acontece.

Além disso, observe que quando você consertar, não será necessário alterar o código PHP. Apenas se certifique de que os nomes dos arquivos (lures.xml e lures.xsd) sejam os mesmos e você possa modificá-los conforme desejar.

Conclusão

O PHP torna fácil para os desenvolvedores a validação de documentos XML. Usando a classe DOMDocument em conjunto com o método schemaValidate() , é possível garantir que seus documentos XML estejam em conformidade com as especificações em seus respectivos esquemas. Isso é importante para garantir a integridade de dados em seus aplicativos de software.

Recursos

Aprender

  • DOMDocument (este link reside fora de ibm.com): Consulte a entrada do Manual de PHP sobre esta classe, que representa um documento HTML ou XML inteiro e atua como a raiz da árvore de documentos.
  • Validação XML (este link reside fora de ibm.com): Leia a explicação do Wikipedia para o processo de verificação de um documento escrito em XML.
  • Analisando XML usando PHP (este link reside fora de ibm.com) (Burhan Khalid, DevPapers, dezembro de 2003): Execute este excelente tutorial sobre análise XML com o analisador PHP integrado (com base na biblioteca expat escrita por James Clark).
  • XML for PHP developers (Cliff Morgan, developerWorks, março de 2007): Explore ainda mais a combinação XML-PHP nesta série de artigos em 3 partes:
    • Part 1: The 15-minute PHP-with-XML starter: Conheça a implementação XML do PHP5 e, se você for relativamente iniciante no uso do XML com PHP, aprenda a ler, analisar, manipular e escrever um arquivo XML curto e descomplicado, usando o DOM e o SimpleXML em um ambiente PHP.
    • Part 2: Advanced XML parsing techniques: Revise as técnicas de análise XML do PHP5, com foco na análise de documentos XML grandes ou complexos. Obtenha algum conhecimento sobre as extensões de análise e, especialmente, quais métodos de análise são mais adequados para determinados tipos de documentos XML e por quê.
    • Part 3: Advanced techniques to read, manipulate, and write XML: Aprenda mais técnicas para leitura, manipulação e escrita XML no PHP5. Nele, o foco está nas APIs DOM e SimpleXML atualmente familiares em ambientes mais sofisticados e, pela primeira vez nesta série de três partes, na extensão XSL.
  • Tutorial: Validating XML (Nicholas Chase, developerWorks, agosto de 2003): Aprenda o que é a validação e como verificar um documento com uma Document Type Definition (DTD) ou documento de Esquema XML.
  • New to XML: Visite este excelente ponto de partida para obter os recursos disponíveis para desenvolvedores XML no IBM developerWorks.
  • Certificação XML da IBM: Descubra como se tornar um IBM-Certified Developer em XML e tecnologias relacionadas.
  • Biblioteca técnica XML: Consulte a zona XML do developerWorks para obter uma ampla variedade de artigos técnicos e dicas, tutoriais, padrões e IBM Redbooks.
  • Eventos técnicos e webcasts do developerWorks: Fique atualizado sobre tecnologia nessas sessões.
  • Podcasts do developerWorks: Ouça interessantes entrevistas e discussões para desenvolvedores de software.

Obter produtos e tecnologias

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre
ArticleID=451603
ArticleTitle=Validando XML no PHP
publish-date=12012009