Lendo e Escrevendo o DOM de XML com PHP

Usando a biblioteca DOM, o analisador SAX e expressões regulares

Técnicas em miríade estão disponíveis para ler e escrever XML em PHP. Este artigo apresenta três métodos para ler XML: usando a biblioteca DOM, usando o analisador SAX e usando expressões regulares. Escrever XML usando modelo de texto DOM e PHP também será coberto.

Jack Herrington, Editor-in-Chief, Code Generation Network

Um engenheiro com mais de 20 anos de experiência, Jack Herrington é atualmente o editor chefe da Code Generation Network. Ele é o autor de Code Generation in Action. Ele pode ser contatado em jack_d_herrington@codegeneration.net.



06/Dez/2005

Ler e gravar Extensible Markup Language (XML) em PHP pode parecer um pouco assustador. De fato, XML e todas as suas tecnologias relacionadas podem ser intimidadoras. No entanto, ler e escrever XML em PHP não precisa ser uma tarefa desanimadora. Primeiro, você precisa aprender um pouco sobre XML -- o que é e para o que é usado. Em seguida, é necessário aprender como ler e escrever XML em PHP, que você pode fazer de diversas maneiras.

Este artigo fornece uma curta introdução sobre XML, em seguida, explica como ler e escrever XML em PHP.

O que É XML?

XML é um formato de armazenamento de dados. Não define quais dados estão sendo armazenados nem a estrutura desses dados. XML simplesmente define tags e atributos para essas tags. Uma tag XML formada corretamente será semelhante a esta:

<name>Jack Herrington</name>

Essa tag <name> contém algum texto: Jack Herrington.

Uma tag XML que não contém nenhum texto parece esta:

<powerUp />

Pode haver mais de uma maneira para codificar algo em XML. Por exemplo, esta tag produz a mesma saída que a anterior:

<powerUp></powerUp>

Você também pode incluir atributos em uma tag XML. Por exemplo, esta tag <name> contém os atributos first e last :

<name first="Jack" last="Herrington" />

Você pode codificar caracteres especiais em XML, também. Por exemplo, um e comercial é codificado da seguinte forma:

&

Um documento XML que contém tags e atributos formatados como os exemplos fornecidos está bem formado , o que significa que as tags estão equilibradas e os caracteres estão codificados corretamente. A Lista 1 é um exemplo de XML bem formado.

Lista 1. Um Exemplo de Lista de Livros em XML
  <books>
  <book>
  <author>Jack Herrington</author>
  <title>PHP Hacks</title>
  <publisher>O'Reilly</publisher>
  </book>
  <book>
  <author>Jack Herrington</author>
  <title>Podcasting Hacks</title>
  <publisher>O'Reilly</publisher>
  </book>
  </books>

O XML na Lista 1 contém uma lista de livros. A tag pai <books> inclui um conjunto de tags <book> que cada uma contém tags <author>, <title> e <publisher> .

Documentos XML são válidos quando a estrutura das tags e seu conteúdo são validados por um arquivo de esquema externo. Os arquivos de esquema podem ser especificados em diversos formatos. Para os propósitos deste artigo, tudo o que precisa é de XML bem formado.

Se você acha que o XML parece muito com a Linguagem de Marcação de Hipertexto (HTML), você está certo. XML e HTML são linguagens baseadas em tag e possuem muitas similaridades. No entanto, é importante observar que enquanto documentos XML podem ser HTML bem formado, nem todos os documentos HTML são XML bem formado. A tag de quebra (br) é um exemplo excelente das diferenças entre XML e HTML. Esta quebra de linha é HTML bem formado,mas não XML bem formado:

<p>This is a paragraph<br>
With a line break</p>

Essa quebra de linha é XML e HTML bem formado:

<p>This is a paragraph<br />
With a line break</p>

Se quiser escrever HTML que seja XML bem formado, siga o padrão Extensible Hypertext Markup Language (XHTML) do World Wide Web Consortium (W3C) (consulte Recursos). Todos os navegadores modernos apresentam XHTML. Além disso, é possível usar ferramentas de XML para ler XHTML e localizar dados nos documentos, que é muito mais fácil do que analisar através de HTML.

Lendo XML Usando a Biblioteca DOM

A maneira mais fácil de ler um arquivo XML bem formado é usar a biblioteca Document Object Model (DOM) compilada em algumas instalações de PHP. A biblioteca DOM lê todo o documento XML na memória e representa-o como uma árvore de nós, conforme ilustrado na Figura 1.

Figura 1. Árvore DOM de XML para o XML books
Árvore DOM de XML para o XML books

O nó books na parte superior da árvore possui duas tags filhas book . Em cada book, há nós author, publisher e title . Os nós author, publisher e title têm nós de texto filhos que contêm o texto.

O código para ler o arquivo XML books e exibir o conteúdo usando o DOM é mostrado na Lista 2.

Lista 2. .Lendo o XML books com o DOM
  <?php
  $doc = new DOMDocument();
  $doc->load( 'books.xml' );

  $books = $doc->getElementsByTagName( "book" );
  foreach( $books as $book )
  {
  $authors = $book->getElementsByTagName( "author" );
  $author = $authors->item(0)->nodeValue;

  $publishers = $book->getElementsByTagName( "publisher" );
  $publisher = $publishers->item(0)->nodeValue;

  $titles = $book->getElementsByTagName( "title" );
  $title = $titles->item(0)->nodeValue;

  echo "$title - $author - $publisher\n";
  }
  ?>

O script começa criando um objeto new DOMdocument e carregando o XML books nesse objeto usando o método load . Após isso, o script usa o método getElementsByName para obter uma lista de todos os elementos com o nome fornecido.

No loop dos nós book , o script usa o método getElementsByName para obter o nodeValue para as tags author, publisher e title . O nodeValue é o texto dentro do nó. O script exibe, então, esses valores.

Você pode executar o script PHP na linha de comando assim:

% php e1.php
PHP Hacks - Jack Herrington - O'Reilly
Podcasting Hacks - Jack Herrington - O'Reilly
%

Como pode ver, uma linha é impressa para cada bloco book. Esse é um bom início. No entanto, e se você não tiver acesso à biblioteca DOM de XML?


Lendo XML Usando o Analisador SAX

Outra maneira de ler XML é usando o analisador Simple API for XML (SAX). A maioria das instalações de PHP inclui o analisador SAX. O analisador SAX é executado em um modelo de retorno de chamada. Toda vez que uma tag é aberta ou fechada ou a qualquer tempo que o analisador vir algum texto, ele faz retornos de chamadas a algumas funções definidas pelo usuário com o nó ou informações de texto.

A vantagem de um analisador SAX é ser realmente leve. O analisador não mantém nada na memória por muito tempo, portanto, pode ser usado para arquivos extremamente grandes. A desvantagem é que escrever retornos de chamada do analisador SAX é um grande incômodo. A Lista 3 mostra o código para ler o arquivo XML books e exibir o conteúdo usando SAX.

Lista 3. Lendo o XML books com o Analisador SAX
  <?php
  $g_books = array();
  $g_elem = null;

  function startElement( $parser, $name, $attrs )
  {
  global $g_books, $g_elem;
  if ( $name == 'BOOK' ) $g_books []= array();
  $g_elem = $name;
  }

  function endElement( $parser, $name )
  {
  global $g_elem;
  $g_elem = null;
  }

  function textData( $parser, $text )
  {
  global $g_books, $g_elem;
  if ( $g_elem == 'AUTHOR' ||
  $g_elem == 'PUBLISHER' ||
  $g_elem == 'TITLE' )
  {
  $g_books[ count( $g_books ) - 1 ][ $g_elem ] = $text;
  }
  }

  $parser = xml_parser_create();

  xml_set_element_handler( $parser, "startElement", "endElement" );
  xml_set_character_data_handler( $parser, "textData" );

  $f = fopen( 'books.xml', 'r' );

  while( $data = fread( $f, 4096 ) )
  {
  xml_parse( $parser, $data );
  }

  xml_parser_free( $parser );

  foreach( $g_books as $book )
  {
  echo $book['TITLE']." - ".$book['AUTHOR']." - ";
  echo $book['PUBLISHER']."\n";
  }
  ?>

O script começa configurando a array g_books , que contém todos os livros e suas informações na memória, e uma variável g_elem , que armazena o nome da tag que o script está processando atualmente. O script define, então, as funções de retorno de chamada. Neste exemplo, as funções de retorno de chamada são startElement, endElement e textData. O startElement e endElement são chamadas quando as tags são abertas e fechadas, respectivamente. O textData é chamada no texto entre o início e o fim das tags.

Neste exemplo, a tag startElement está procurando a tag book para iniciar um novo elemento na array book . Em seguida, a função textData verifica o elemento atual para ver se é uma tag publisher, titleou author . Se esse for o caso, a função coloca o texto atual no livro atual.

Para que a análise comece, o script cria o analisador com a função xml_parser_create . Em seguida, configura os manipuladores de retorno de chamada. Após isso, o script lê o arquivo e envia partes do arquivo para o analisador. Após o arquivo ser lido, a função xml_parser_free exclui o analisador. O fim do script faz dump do conteúdo da array g_books .

Como pode ver, isso é código muito mais difícil de escrever do que o DOM equivalente. E se você não tiver a biblioteca DOM ou a biblioteca SAX? Há outra alternativa?


Analisar XML com Expressões Regulares

Com certeza serei vilipendiado por alguns engenheiros por até mesmo mencionar essa abordagem, mas é possível analisar XML com expressões regulares. A Lista 4 mostra um exemplo de como usar as funções preg_ para ler o arquivo books.

Lista 4. Lendo o XML books com Expressões Regulares
  <?php
  $xml = "";
  $f = fopen( 'books.xml', 'r' );
  while( $data = fread( $f, 4096 ) ) { $xml .= $data; }
  fclose( $f );

  preg_match_all( "/\<book\>(.*?)\<\/book\>/s",
  $xml, $bookblocks );

  foreach( $bookblocks[1] as $block )
  {
  preg_match_all( "/\<author\>(.*?)\<\/author\>/",
  $block, $author );
  preg_match_all( "/\<title\>(.*?)\<\/title\>/",
  $block, $title );
  preg_match_all( "/\<publisher\>(.*?)\<\/publisher\>/",
  $block, $publisher );
  echo( $title[1][0]." - ".$author[1][0]." - ".
  $publisher[1][0]."\n" );
  }
  ?>

Observe como esse código é curto. Começa lendo o arquivo em uma string grande. Usa, então, uma função regex para ler em cada item book. Por fim, usando o loop foreach , o script faz o loop em torno de cada bloco book e seleciona o autor, título e editora.

Então, quais são as deficiências? O problema em usar código de expressão regular para ler XML é que não verifica antes para assegurar que o XML esteja bem formado. Isso significa que você pode não saber que você tem XML que não está bem formado antes de começar a lê-lo. Além disso, alguns formatos válidos de XML podem não corresponder às suas expressões regulares, portanto, será necessário modificá-los posteriormente.

Nunca recomendo usar expressões regulares para ler o XML, mas às vezes é a maneira mais compatível, pois as funções de expressão regular estão sempre disponíveis. Não use expressões regulares para ler o XML que é fornecido diretamente por usuários; você não controla o formato nem a estrutura desse XML. Sempre leia o XML dos usuários usando uma biblioteca DOM ou analisador SAX.


Escrevendo XML com o DOM

Ler XML é somente uma parte da equação. E escrever? A melhor maneira de escrever XML é usar o DOM. A Lista 5 mostra como o DOM constrói o arquivo XML books.

Lista 5. Escrevendo XML books com o DOM
  <?php
  $books = array();
  $books [] = array(
  'title' => 'PHP Hacks',
  'author' => 'Jack Herrington',
  'publisher' => "O'Reilly"
  );
  $books [] = array(
  'title' => 'Podcasting Hacks',
  'author' => 'Jack Herrington',
  'publisher' => "O'Reilly"
  );

  $doc = new DOMDocument();
  $doc->formatOutput = true;

  $r = $doc->createElement( "books" );
  $doc->appendChild( $r );

  foreach( $books as $book )
  {
  $b = $doc->createElement( "book" );

  $author = $doc->createElement( "author" );
  $author->appendChild(
  $doc->createTextNode( $book['author'] )
  );
  $b->appendChild( $author );

  $title = $doc->createElement( "title" );
  $title->appendChild(
  $doc->createTextNode( $book['title'] )
  );
  $b->appendChild( $title );

  $publisher = $doc->createElement( "publisher" );
  $publisher->appendChild(
  $doc->createTextNode( $book['publisher'] )
  );
  $b->appendChild( $publisher );

  $r->appendChild( $b );
  }

  echo $doc->saveXML();
  ?>

Na parte superior do script, a array books é carregada com alguns livros de exemplo. Esses dados podem vir do usuário ou de um banco de dados.

Após os livros de exemplo serem carregados, o script cria um new DOMDocument e inclui o nó raiz books no mesmo. Em seguida, o script cria um elemento para o autor, título e editora para cada livro e inclui um nó de texto para cada um desses nós. A etapa final para cada nó book é anexá-lo novamente ao nó raiz books .

O fim do script efetua dump do XML no console usando o método saveXML . (Você também pode usar o método save para criar um arquivo a partir do XML.) A saída do script é mostrada na Lista 6.

Lista 6. Saída do Script de Construção do DOM
  % php e4.php
  <?xml version="1.0"?>
  <books>
  <book>
  <author>Jack Herrington</author>
  <title>PHP Hacks</title>
  <publisher>O'Reilly</publisher>
  </book>
  <book>
  <author>Jack Herrington</author>
  <title>Podcasting Hacks</title>
  <publisher>O'Reilly</publisher>
  </book>
  </books>
  %

O real valor de usar o DOM é que o XML que cria é sempre bem formado. Mas o que você pode fazer se não tiver acesso ao DOM para criar XML?


Escrevendo XML com PHP

Se o DOM não estiver disponível, é possível usar o modelo de texto PHP para escrever XML. A Lista 7 mostra como PHP constrói o arquivo XML books.

Lista 7. Escrevendo XML books com PHP
  <?php
  $books = array();
  $books [] = array(
  'title' => 'PHP Hacks',
  'author' => 'Jack Herrington',
  'publisher' => "O'Reilly"
  );
  $books [] = array(
  'title' => 'Podcasting Hacks',
  'author' => 'Jack Herrington',
  'publisher' => "O'Reilly"
  );
  ?>
  <books>
  <?php

  foreach( $books as $book )
  {
  ?>
  <book>
  <title><?php echo( $book['title'] ); ?></title>
  <author><?php echo( $book['author'] ); ?>
  </author>
  <publisher><?php echo( $book['publisher'] ); ?>
  </publisher>
  </book>
  <?php
  }
  ?>
  </books>

A parte superior do script é semelhante ao script DOM. A parte inferior do script abre a tag books , em seguida, itera por cada livro, criando a tag book e todas as tags internas title, author e publisher .

O problema com essa abordagem é a codificação das entidades. Para assegurar que as entidades sejam codificadas corretamente, a função htmlentities deve ser chamada em cada item, conforme mostrado na Lista 8.

Lista 8. Usando a Função htmlentities para Codificar Entidades
  <books>
  <?php

  foreach( $books as $book )
  {
  $title = htmlentities( $book['title'], ENT_QUOTES );
  $author = htmlentities( $book['author'], ENT_QUOTES );
  $publisher = htmlentities( $book['publisher'], ENT_QUOTES );
  ?>
  <book>
  <title><?php echo( $title ); ?></title>
  <author><?php echo( $author ); ?> </author>
  <publisher><?php echo( $publisher ); ?>
  </publisher>
  </book>
  <?php
  }
  ?>
  </books>

Por isso é incômodo escrever XML em PHP básico. Você acha que está criando XML perfeito, mas depois descobre que determinados elementos não estão codificados corretamente quando você tenta executar dados através dele.


Conclusões

XML sempre teve muita comoção e confusão a seu redor. No entanto, não é tão difícil quando você imagina -- principalmente em uma linguagem excelente como PHP. Quando você entende e implementa XML corretamente, descobrirá que há muitas ferramentas poderosas que você pode usar. XPath e XSLT são duas dessas ferramentas que valem a pena verificar.

Recursos

Aprender

Obter produtos e tecnologias

  • Visite PHP.net para aprender sobre as novidades mais recentes sobre PHP, localizar downloads e aprender com outros usuários.
  • Aprenda sobre Expat XML Parser, o analisador que é usado para fornecer a funcionalidade do analisador SAX para PHP.
  • Inove seu próximo projeto de desenvolvimento de software livre com software de avaliação da IBM, disponível para download ou em DVD.

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=382640
ArticleTitle= Lendo e Escrevendo o DOM de XML com PHP
publish-date=12062005