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); ?>
É 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
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.
Charles, obrigado pelo comentário, fico feliz que tenha conseguido tirar do blog algo que pudesse aplicar em seu trabalho.
abraços,
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 😀
Ó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…
Valeu Rafa,
até logo,
OK!!!!Mostrou na tela …. mas ao gerar o arquivo songs.xml não há nenhum conteúdo dentro…?????
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);
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
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.
Chebaca, você precisa criar o server e o client para usar o ws.
Veja esse exemplo básico de server e client (hello word)
http://www.scottnichol.com/nusoapintro.htm
Mais um ótimo post! Exatamente o que eu procurava. Valeu!
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?
Newber, você descomentou quais linhas? Quais foram comentadas?
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.
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.
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
Talvez você tenha que passar o ID no método chart.setDataURL()
http://pastebin.com/37fFY6Ee
Desculpe depois que vi que o codigo era no pastebin… segue
http://pastebin.com/f80Wci0h
Charles, é igual aos demais:
$xml->startElement(“elemento”);
$xml->writeAttribute(“name”, “valor”);