Gerando XML com PHP e MySQL

  • Autor do post:
  • Categoria do post:PHP DEV

Gerando XML com PHP e MySQL

Olá, escrevi alguns posts sobre gerar XML com PHP mas nenhum com banco de dados, hoje consegui tempo para criar um post sobre o assunto.
No exemplo proposto utilizei:
* PHP5
* MySQL
* XMLWriter (PHP)

Neste exemplo a idéia será gerar um XML com informações de músicas, geralmente os players em flash utilizam um xml para carregar os sons e todas as informações da música, tais como: albúm, artista, nome da faixa, duração da faixa, imagem da capa, etc…

Para isso precisaremos de:
* Classe de conexão com MySQL (utilizarei uma classe bem simples viu)
* 2 Tabelas (albuns e songs)
* 2 arquivos PHP (mysqlcon.class.php e o xml.php)

Então mãos nas teclas…

O arquivo mysqlcon.class.php

<?php
Class MySqlCon
{
	protected $host = "localhost";
	protected $user = "root";
	protected $pass = "root";
	protected $dbname = "music";
	protected $con = "";

	public function __construct()
	{
		$this->con = mysql_connect("$this->host" , "$this->user" , "$this->pass") or die ('Error');
		mysql_select_db("$this->dbname");
	}

	public function close()
	{
		mysql_close($this->con);
	}
}
?>

É só isso mesmo!

O script para criar as tabelas (no banco especificado na classe de conexao, neste exemplo o banco music)

/* Tables */
CREATE TABLE albuns (
  album_id  int AUTO_INCREMENT NOT NULL,
  name      varchar(30),
  author    varchar(30),
  imageurl  varchar(200),
  link      varchar(200),
  PRIMARY KEY (album_id)
) ENGINE = InnoDB;

CREATE TABLE songs (
  song_id        int AUTO_INCREMENT NOT NULL,
  name           varchar(200),
  duration       varchar(5),
  buylink        varchar(200),
  songurl        varchar(200),
  song_album_id  int,
  PRIMARY KEY (song_id)
) ENGINE = InnoDB;

/* Foreign Keys */
ALTER TABLE songs
  ADD CONSTRAINT fk_album_song
  FOREIGN KEY (song_album_id)
    REFERENCES albuns(album_id)
    ON DELETE RESTRICT
    ON UPDATE RESTRICT;

/* Data for table "albuns" */
INSERT INTO albuns (album_id, name, author, imageurl, link) VALUES
  (1, 'Funeral', 'The Arcade Fire', 'images/taf/image.jpg', 'http://www.arcadefire.com/');

/* Data for table "songs" */
INSERT INTO songs (song_id, name, duration, buylink, songurl, song_album_id) VALUES
  (1, 'Neighborhood #1', '3:26', 'http://www.arcadefirestore.com/', 'songs/taf/neighborhood_1.mp3', 1);

E por último, o arquivo xml.php que é o que nos interessa neste post

<?php
# Incluindo a classe de conexao
require_once 'mysqlcon.class.php';
# Instanciando a conexao MySql
$con = new MySqlCon;
# Instanciando o XMLWriter
$xml = new XMLWriter;
$xml->openMemory();
# Definindo o encoding do XML
$xml->startDocument( '1.0' , 'utf-8' );
# Primeiro elemento do XML
$xml->startElement("featureset");
	# Query na tabela albuns
	$rs_album = mysql_query("select * from albuns");
	while($album = mysql_fetch_array($rs_album))
	{
		# Transformando array em objeto
		$album = (object)$album;
		# Criando elemento album
		$xml->startElement("album");
		# Setando os atributos
		$xml->writeAttribute("name", "$album->name");
		$xml->writeAttribute("author", "$album->author");
		$xml->writeAttribute("imageUrl", "$album->imageurl");
		$xml->writeAttribute("link", "$album->link");

		# Query na tabela songs
		$rs_song = mysql_query("select * from songs where song_album_id = $album->album_id");
		while($song = mysql_fetch_array($rs_song))
		{
			$song = (object)$song;
			# Criando elemento song dentro do album
			$xml->startElement("song");
			# Setando os atributos
			$xml->writeAttribute("name", "$song->name");
			$xml->writeAttribute("duration", "$song->duration");
			$xml->writeAttribute("buyLink", "$song->buylink");
			$xml->text("$song->songurl");
			# Fechando o elemento song
			$xml->endElement();
		}
	}
	# Fechando o elemento album
	$xml->endElement();
# Fechando o elemento featureset
$xml->endElement();

# Encerrando a conexao
$con->close();

# Definindo cabecalho de saida
header( 'Content-type: text/xml' );
# Imprimindo a saida do XML
print $xml->outputMemory(true);

# Salva arquivo em disco
//$file = fopen('songs.xml','w+');
//@fwrite($file,$xml->outputMemory(true));
//fclose($file);

?>

Saída:

É isso, acho que os comentários no código já o explica, no entanto irei fazer breves comentários.

Existem 2 whiles porque são 2 tabelas, o primeiro while busca a tabela albuns e a cada registro encontrado pega o id do album e faz uma seleção na tabela songs, isso porque as tabelas são relacionadas, a tabela songs possui para cada registro o ID do album, então a cada albúm é realizada a busca por songs.

Para ver melhor o resultado em XML, populem as tabelas.

Outra coisa que poupa algumas linhas de código é o (object), se não tivéssemos utilizado esse cara ficaria algo como:

 while($song = mysql_fetch_array($rs_song))
 {
   $name = $song['name'];
   $duration = $song['duration'];
   $buylink = $song['buylink'];
   $xml->startElement("song");
   $xml->writeAttribute("name", "$name");
   $xml->writeAttribute("duration", "$duration");
   $xml->writeAttribute("buyLink", "$buylink");
 }

# Utilizando o (object)
while($song = mysql_fetch_array($rs_song))
{
   $song = (object)$song;
   $xml->startElement("song");
   $xml->writeAttribute("name", "$song->name");
   $xml->writeAttribute("duration", "$song->duration");
   $xml->writeAttribute("buyLink", "$song->buylink");
}

Referências:
XMLWriter: http://br3.php.net/XMLWriter
mysql_query: http://br3.php.net/mysql_query
(object):  http://br3.php.net/manual/en/language.types.object.php

Abraços,

Rafael Clares

Este post tem 19 comentários

  1. Charles Mousinho

    Boa noite rafael,
    gostaria de agradecer pelo suporte que me deste quanto a este seu tutorial, gracas a ele consegui resolver meu problema.
    Gostaria de agradecer tambem, pois foi atraves do seu ensinamento que vi que trabalhar com object e mais facil que com o fetch-array 😉
    Definitivamente aprendi a trabalhar com ele.

    To na espera do proximo tutorial para aprender mais.

    sorry os erros, teclado americano sux.

    1. Rafael Clares

      Charles, obrigado pelo comentário, fico feliz que tenha conseguido tirar do blog algo que pudesse aplicar em seu trabalho.
      abraços,

    2. hugão

      Realmente, depois de ler este pequeno (e excelente!!!) tutorial, percebi que trabalhar com object, ao invés de array é, sem sombra de dúvidas, uma opção muito mais legível :)…
      Boas práticas de programação é tudo 😀

  2. Rafaela Sacconi

    Ótimos posts, parabéns!

    Está muito bem explicado, está funcional… testei e deu certo de primeira. Além disso, não deixou a simplicidade de lado. Virei frequentadora do seu blog. =)

    Até mais…

  3. KARLOS

    OK!!!!Mostrou na tela …. mas ao gerar o arquivo songs.xml não há nenhum conteúdo dentro…?????

  4. Gabriel da Vitória

    Parabens Rafael, estou aplicando esse post em um trabalho meu, De muita utilidade. Porem estou tendo um problema desse tipo de não carregar os registros para dentro do songs.xml. Porem quando utiliza as tabelas descritas, passa, se mudar de tabela da bixeira.

    Erro no processamento de XML: nenhum elemento encontrado
    Posição: http://localhost/social/xml/xml.php
    Número da linha 2, coluna 2888:

    Mas se usar o firebub mostra a resposta com os registros, so que n salva. Sabe o que pode ser?

    Olha o meu Cod.
    ————————————————————–
    # Incluindo a classe de conexao
    require_once ‘mysqlcon.class.php’;
    # Instanciando a conexao MySql
    $con = new MySqlCon;
    # Instanciando o XMLWriter
    $xml = new XMLWriter;
    $xml->openMemory();
    # Definindo o encoding do XML
    $xml->startDocument( ‘1.0’ , ‘utf-8’ );
    # Primeiro elemento do XML
    $xml->startElement(“novosmembros”);
    # Query na tabela albuns
    $rs_album = mysql_query(“select * from novos_cadastros order by id_pessoa”);
    while($album = mysql_fetch_array($rs_album))
    {
    # Transformando array em objeto
    $album = (object)$album;
    # Criando elemento album
    $xml->startElement(“novomembro”);
    # Setando os atributos

    $xml->writeAttribute(“id_pessoa”, “$album->id_pessoa”);
    $xml->writeAttribute(“nome”, “$album->nome”);
    $xml->writeAttribute(“cpf”, “$album->cpf”);
    $xml->writeAttribute(“activo”, “$album->activo”);
    $xml->writeAttribute(“sexo”, “$album->sexo”);
    $xml->writeAttribute(“sit_pg”, “$album->sit_pg”);
    $xml->writeAttribute(“nivel”, “$album->nivel”);
    $xml->writeAttribute(“agencia”, “$album->agencia”);
    $xml->writeAttribute(“conta”, “$album->conta”);
    $xml->writeAttribute(“data_cadastro”, “$album->data_cadastro”);
    $xml->writeAttribute(“numero_boleto”, “$album->numero_boleto”);
    $xml->writeAttribute(“data_gerado”, “$album->data_gerado”);
    $xml->writeAttribute(“data_vencimento”, “$album->data_vencimento”);

    }
    # Fechando o elemento album
    $xml->endElement();

    # Fechando o elemento featureset
    $xml->endElement();

    # Encerrando a conexao
    $con->close();

    # Definindo cabecalho de saida
    header( ‘Content-type: text/xml’ );
    # Imprimindo a saida do XML
    print $xml->outputMemory(true);

    # Salva arquivo em disco
    $file = fopen(‘songs.xml’,’w’);
    fwrite($file,$xml->outputMemory(true));
    fclose($file);

    1. Rafael Clares

      Gabriel, desculpe a demora em responder, estive de mudança e fiquei sem net.
      Me envie o código para [email protected] para eu avaliar.
      Obs: nunca envie dúvidas para esse email, as dúvidas devem ser sanadas no post. Abs

      1. chebaca

        Rafael, obrigado pelo retorno, eu consegui regar o XML, porem tive de mudar toda a estrutura do meu sistema e trabalhar em webservices,

        Mesmo assim agradeço pela atenção. Sobre WebServices Nusoap, Estou com uma dificuldade em fazer uma função especifica funcionar, saberia como faço para testa-la? Ex; quando acesso o serviço do WS, ele me mostra a folha do ws com o parâmetro a ser passado para se obter um retorno, não sei como faço uma função que criei amarrada em uma view no meu DB funcionar.

  5. Mozart

    Mais um ótimo post! Exatamente o que eu procurava. Valeu!

  6. newber

    Eu refiz a simulação do teste que vc apresentou no post criando o mesmo banco de dados com menos nomes, porém coloquei na web para testar, ele gera o arquivo xml, porém quando vai gravar no servidor ele cria o arquivo em branco o que pode ser?

    1. Rafael Clares

      Newber, você descomentou quais linhas? Quais foram comentadas?

  7. LeoChaves

    Obrigado por compartilhar as informações. =)
    Eu precisava processar uma lista de exclusão/exceção condicional. E nao sei como fazer o select disso ser considerado na hora de montar o xml. Alguém pode dar uma luz?

    Tenho uma lista no banco e mais de um sistema que baixa essa lista, o complicador é que cada sistema tem peças que nao devem ser exibidas e outras que devem ser exibidas no lugar.

    Pensei em montar uma tabela com isso e quando a função de montar o XML fosse processada ela faria as alterações necessárias com base nessa lista.

    1. Rafael Clares

      Leo, neste caso o ideal é você criar um arquivo ou método para cada sistema, talvez passando um parâmetro na url, ex:
      Sistema 1 = Mostra todas as peças geraXml.php?tipo=1
      Sistema 2 = Mostra algumas as peças geraXml.php?tipo=2

      Assim dependendo da url o script faz um ou outro select
      if($_GET[‘tipo’] == 1)
      {
      $str = “select * from tb1 where …..”;
      }
      elseif($_GET[‘tipo’] == 2)
      {
      $str = “select * from tb1 where …..”;
      }
      elseif($_GET[‘tipo’] == 3)
      {
      ///
      }

      De toda forma, gerar o XML será o de menos, você precisa mesmo, de início é separar as seleções de acordo com as condições que precisa;
      Infelizmente, é meio vago para mim como funciona seu sistema.

  8. [email protected]

    Rafael utilizo o fusion realizando a consulta direto no BD. Porem não consigo fazer isso quando tento passar uma get para personalizar a consulta, consegue me ajudar?
    Segue link do código: http://pastebin.com/QyuZmkJb

    1. Rafael Clares

      Charles, é igual aos demais:
      $xml->startElement(“elemento”);
      $xml->writeAttribute(“name”, “valor”);

Os comentários estão encerrados.