Logo Hardware.com.br
João Marcelo
João Marcelo Geek Registrado
3K Mensagens 71 Curtidas

[Resolvido] Script para importar XML para MySQL

#1 Por João Marcelo 01/08/2011 - 11:18
Olá, tenho um pequeno servidor CentOS rodando o MySQL que precisa ser atualizado diariamente com algumas informações que me são passadas via arquivo XML.

O XML tem a seguinte estrutura:


<?xml version="1.0"?>



01
898002342517744
023805
MARIA MARIA MARIA
8888888888
03/08/2011
12:07
1
016326
CAROLINA CAROLINA
0302
TESTE
11
RECEPCAO



01
898001928493418
033165
MANOEL MANOEL
8999999999
09/08/2011
11:08
1
015525
POLYANNA POLYANNA
0104
TESTE
14
RECEPCAO



e por ai vai.
Sou totalmente leigo em PHP porém encontrei em um site algo parecido com o que quero fazer: http://phpbr.wordpress.com/2007/07/07/xml-to-mysql-transformando-um-arquivo-xml-em-queries-sql-e-blablabla/

Tentei adaptar às minhas necessidades, mas não estou conseguindo, no meu caso o script ficou assim:


<?php

$banco = 'xml2mysql';
$host = 'localhost'; // host
$usuario = 'root'; // usuario
$senha = 'minha_senha'; // senha

// connectamos ao host e selecionamos o banco
mysql_connect($host, $usuario, $senha);
mysql_select_db($banco);

// esta variavel sera a query utilizada para insercao dos
// dados no banco, tendo o %d substituido pelo id_exemplo
// e o %s substituido pela descricao
$query = 'insert into exemplo (GM8_DTATEND, GCS_NOMLOC, GM8_HORAGE, RA_NOME, GM8_MATRIC, GM8_CELULAR) values ("%s", "%s", "%s", "%s", "%s")';

// carregamos o conteudo do arquivo XML
$xml = file_get_contents('demo2.xml');

// transformamos o XML em um objeto, para que possamos trabalhar
// de forma mais simples com ele
$sxml = new SimpleXMLElement($xml);

// aqui iteramos por todo o XML:
// a cada iteracao, $line ira conter um objeto to tipo
// SimpleXMLElement, sendo o equivalente a:
//
//
// 1
// Primeiro exemplo
//
//
foreach ($sxml as $linhaAtual) {
// aqui vamos obter cada item do xml que seria referente
// ao campo da tabela.
// Necessario cast pelo fato de que a propriedade do objeto
// tambem é um objeto do tipo SimpleXMLElement
$data = (string) $linhaAtual->GM8_DATEND;
$local = (string) $linhaAtual->GCS_NOMLOC;
$hora = (string) $linhaAtual->GM8_HORAGE;
$nome = (string) $linhaAtual->RA_NOME;
$matricula = (string) $linhaAtual->GM8_MATRIC;
$celular = (int) $linhaAtual->GM8_CELULAR;

// aqui preparamos a query para ser utilizada
$tmpQuery = sprintf($query, $data, $local, $hora, $nome, $matricula, $celular);

// exibimos a query que será executada
echo sprintf('Executando query: %s%s', $tmpQuery, "\n");

// e aqui executamos a query
mysql_query($tmpQuery);
}


Antes de rodar eu criei o banco "xml2mysql" e a tabela "exemplo":


mysql> show tables;
+---------------------+
| Tables_in_xml2mysql |
+---------------------+
| exemplo |
+---------------------+
1 row in set (0.00 sec)


mysql> SHOW INDEX FROM xml2mysql.exemplo;
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| exemplo | 0 | PRIMARY | 1 | id | A | 0 | NULL | NULL | | BTREE | |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
1 row in set (0.00 sec)


Criei as colunas na tabela e aproveitei e introduzi apenas uma linha na mão:
mysql> SELECT * FROM exemplo;
+----+------------+-------+-------+---------+------------+----------+
| id | data | local | hora | nome | matricula | celular |
+----+------------+-------+-------+---------+------------+----------+
| 1 | 23/10/2010 | prt | 12:00 | teste01 | 12345 | 77777777 |
+----+------------+-------+-------+---------+------------+----------+
1 row in set (0.00 sec)

Mas ao rodar o script PHP, ele executa, mas não mostra o número do celular corretamente e nada vai parar no MySQL:

[localdomain tmp]# php test.php
Executando query: insert into exemplo (GM8_DTATEND, GCS_NOMLOC, GM8_HORAGE, RA_NOME, GM8_MATRIC, GM8_CELULAR) values (0, "RECEPCAO ", "12:07", "CAROLINA CAROLINA ", "898002342517744", "0")
Executando query: insert into exemplo (GM8_DTATEND, GCS_NOMLOC, GM8_HORAGE, RA_NOME, GM8_MATRIC, GM8_CELULAR) values (0, "RECEPCAO ", "11:08", "POLYANNA POLYANNA", "898001928493418", "0")
[localdomain tmp]#


Alguém saberia me informar onde está o erro?

Obrigado,

João Marcelo
Responder
waldony ximenes
waldony xime... Super Participante Registrado
612 Mensagens 46 Curtidas
#2 Por waldony xime...
01/08/2011 - 11:32
Coloca um mysql_erro() nessa linha


$query = 'insert into exemplo (GM8_ID, GM8_DTATEND, GCS_NOMLOC, GM8_HORAGE, RA_NOME, GM8_MATRIC, GM8_CELULAR) values (%d, "%s", "%s", "%s", "%s", "%s")';


ficando assim $query = 'insert into exemplo (GM8_ID, GM8_DTATEND, GCS_NOMLOC, GM8_HORAGE, RA_NOME, GM8_MATRIC, GM8_CELULAR) values (%d, "%s", "%s", "%s", "%s", "%s")' . mysql_erro();

Para poder exibir os erros de envio de arquivos.
jcferranti
jcferranti General de Pijama Registrado
4.7K Mensagens 162 Curtidas
#4 Por jcferranti
01/08/2011 - 14:43
João Marcelo disse:
waldony, obrigado pela ajuda. Tentei fazer o que você sugeriu, mas ocorreu o seguinte:

[localdomain tmp]# php test.php
PHP Fatal error: Call to undefined function mysql_erro() in /tmp/test.php on line 15

a função é mysql_error()
Casa:MS Windows Seven (empolgando)
Trampo: MS Windows Seven (desapontando)

Quer um Fórum exclusivamente sobre Open Source? Aqui: www.linuxbsd.com.br/forum
João Marcelo
João Marcelo Geek Registrado
3K Mensagens 71 Curtidas
#5 Por João Marcelo
01/08/2011 - 14:55
Obrigado jcferranti, percebi depois :P voltei aqui para postar o resultado, porém você foi mais rápido que eu.

Desculpem novamente a noobisse, mas onde será gerado o aquivo de log com o erro? Procurei em /var/log/mysql.log e /var/lib/mysql nada. Procurei também por arquivos com a extensão .err e nada.
Melhor que ficar esperando resposta é pesquisar e ter a resposta na hora. isso_ai.png

Up The Irons!



waldony ximenes
waldony xime... Super Participante Registrado
612 Mensagens 46 Curtidas
#6 Por waldony xime...
01/08/2011 - 20:26
João Marcelo disse:
Obrigado jcferranti, percebi depois :P voltei aqui para postar o resultado, porém você foi mais rápido que eu.

Desculpem novamente a noobisse, mas onde será gerado o aquivo de log com o erro? Procurei em /var/log/mysql.log e /var/lib/mysql nada. Procurei também por arquivos com a extensão .err e nada.


Mas não há log de erro, me diga uma coisa você definil a função?

Tenta defini-la, vou baixar aqui o script para tentar te ajudar melhor.
jofrelscalvet
jofrelscalve... Veterano Registrado
1.3K Mensagens 51 Curtidas
#7 Por jofrelscalve...
02/08/2011 - 06:59
GM8_CELULA no arquivo xml não é o mesmo que GM8_CELULAR em
[php][/$celular = (int) $linhaAtual->GM8_CELULAR;
php]

Para que a dica dada pelos colegas funcionasse é necessário que você mude a ordem de execução de algumas linhas, alem disso não sei se o mysql_error() pode ser executado dentro de mysql_query(). Eu simplesmente acrescentaria uma nova linha
[php]echo "\n
Mysql error: " .mysql_error() . "\n
"[/php]
depois de
[php]mysql_query($tmpQuery);
[/php]
Descoberto o bug é claro que a linha deve ser eliminada ou mostrada apenas de forma condicional ...

Outra dica: simplexml_load_file() poderia encurtar em 1 comando seu código (claro que se nem funciona ainda não faz sentido você tentar "melhorar" o código).
Melhore o futuro do fórum: Diga se a dica funcionou ou conte-nos como conseguiu resolver a sua dúvida!
Se eu errar ou for pouco claro, reclame! Quando possivel eu tentarei melhorar.
waldony ximenes
waldony xime... Super Participante Registrado
612 Mensagens 46 Curtidas
#9 Por waldony xime...
03/08/2011 - 19:17
João Marcelo disse:
jofrelscalvet, obrigado pela dica, realmente o CELULA passou batido daa.png .

Vou modificar o script e depois posto o resultado.

Ximenes, como disse, sou noob em PHP, tudo que fiz tá aí. smile.png


Encontrei um Script na net que talvez possa te ajudar. ele é muito bom testei e deu certo.


1.)extrairCamposArquivoXML($campos, $elemento, $i) > Extrai os campos do elemento do arquivo XML, usados para inserção na tabela da base de dados.

private function extrairCamposArquivoXML($campos, $elemento, $i){
$doc = new DomDocument;
$doc->Load($this->arquivoXML); // Carrega o arquivo XML com um arquivo DOMDocument

$items = $doc->getElementsByTagName($elemento); //Seleciona o elemento ou tabela a ser importada
$valor = array();
foreach ($campos as $campo) {
$valor[] = "'" . $items->item($i)->getElementsByTagName($campo)->item(0)->nodeValue . "'"; //Extrai o valor para cada campo passado para extração
}

$value = ' (';
$value .= implode(',', $valor);
$value .= ') ';

return $value; //Retorna string no seguinte formato ('valor1','valor2','valor3','valor4',...,'valorn')
}


2.)extrairQuantidadeItensArquivoXML($elemento) > Extrai o número total de registros do elemento XML.

private function extrairQuantidadeItensArquivoXML($elemento){
$doc = new DomDocument;
// Carrega o arquivo XML com um arquivo DOMDocument
$doc->Load($this->arquivoXML);
$items = $doc->getElementsByTagName($elemento);
return $items->length; //Retorna a quantidade de elementos ou registros
}


3.)criarQueryImportacaoXML($campos, $elemento, $tabela, $colunas, $quantidade) > Constrói a query SQL para inserção na base de dados.

private function criarQueryImportacaoXML($campos, $elemento, $tabela, $colunas, $quantidade){
$query = "insert into $tabela (";
$query .= implode (",",$colunas);
$query .= ") values ";
$query .= $this->extrairCamposArquivoXML($campos, $elemento, $quantidade);
echo $query;
return $query; Retorna a query no seguinte formato insert into $tabela (campo1,campo2,campo3,...,campon) values ('valor1','valor2','valor3','valor4',...,'valorn')
}


Estas 3 funções são a base da importação, pois são responsável pela extração dos dados XML e criação da query SQL, abaixo o script completo (Classe importação, para exemplo).

<?php
// Informações da Classe Importação
// Versão 0.1a
// Data de criação 27/12/2010
// Última modificação 27/12/2010

// Classe construída para importação da base de dados do Publique para o CMS Unideia
// Após a extração colocar o arquivo XML no mesmo lugar do importacao.php, depois só executar no browser ou prompt

// Desenvolvida por
// Diego Muniz Cerqueira
// Programador Web
// Octonal Comercio e Serviços de Informática Ltda.
// +55 21 3296-9328
// [email]dcerqueira@allnetgroup.com.br[/email]
// www.allnetgroup.com.br
// Microsoft Crm Certified Partner
// Microsoft Infrastructure Certified Partner

// Observações
// - Ao instanciar a classe tem que se informar se deseja ativar o SQL, o nome da base de dados e o nome do arquivo XML.
// - Para teste mude valor de $ativar_conexao para false. Ex.: $importar = new importacao(false, 'diego', 'database.xml');

// Descrição dos métodos
// __construct($ativar, $bd, $arquivo) > Método construtor da classe.
// construirBase() > Método responsável por criar a nova base de dados e as tabelas a serem utilizadas.
// executarSQL($query) > Recebe a string SQL para execução.
// extrairCamposArquivoXML($campos, $elemento, $i) > Extrai os campos do elemento do arquivo XML, usados para inserção na tabela da base de dados.
// extrairQuantidadeItensArquivoXML($elemento) > Extrai o número total de registros do elemento XML.
// criarQueryImportacaoXML($campos, $elemento, $tabela, $colunas, $quantidade) > Constrói a query SQL para inserção na base de dados.
// importarUsuarios() > Responsável por importar os usuários do arquivo XML para a base de dados MySQL no novo formato.
// importarMaterias() > Responsável por importar as matérias do arquivo XML para a base de dados MySQL no novo formato.
// importarSecao() > Responsável por importar as seções do arquivo XML para a base de dados MySQL no novo formato.
// principal() > Controla a execução do código, método principal, único com possibilidade de acesso externo.

class Importacao{

private $ativar_conexao;
private $conexao;
private $base;
private $arquivoXML;

public function __construct($ativar, $bd, $arquivo){
$this->ativar_conexao = $ativar;
$this->base = $bd;
$this->arquivoXML = $arquivo;
}

private function construirBase(){
if ($this->ativar_conexao == true) {
$this->conexao = mysql_connect("localhost","root","") or die('falha ao conectar');
$query = 'CREATE DATABASE IF NOT EXISTS diego;';

if(!mysql_query($query,$this->conexao)) {
echo mysql_error().'
falha ao criar base de dados
';
}

mysql_select_db($this->base,$this->conexao) or die($msg[1]);


$query = "CREATE TABLE IF NOT EXISTS `usuario` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`nome` varchar(250) DEFAULT NULL,
`email` varchar(250) DEFAULT NULL,
`login` varchar(250) DEFAULT NULL,
`senha` varchar(50) DEFAULT NULL,
`ativo` tinyint(1) NOT NULL,
`perfil` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;";


if(!mysql_query($query,$this->conexao)) {
echo mysql_error().'
falha ao criar tabela
';
}

$query = "CREATE TABLE IF NOT EXISTS `materia` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`estado` int(10) DEFAULT NULL,
`data` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`idSecao` int(10) DEFAULT NULL,
`titulo` varchar(250) DEFAULT NULL,
`idUsuario` int(10) DEFAULT NULL,
`subtitulo` longtext,
`texto` longtext,
`imagem` varchar(250) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;";

if(!mysql_query($query,$this->conexao)) {
echo mysql_error().'
falha ao criar tabela
';
}

$query = "CREATE TABLE IF NOT EXISTS `secao` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`nome` varchar(250) DEFAULT NULL,
`tag` varchar(250) DEFAULT NULL,
`descricao` longtext,
`idSecaoPai` int(10) DEFAULT NULL,
`link` varchar(250) DEFAULT NULL,
`ordem` varchar(250) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;";

if(!mysql_query($query,$this->conexao)) {
echo mysql_error().'
falha ao criar tabela
';
}

}
}

private function executarSQL($query){
if ($this->ativar_conexao == true) {
if(!mysql_query($query,$this->conexao)) {
echo mysql_error().'
falha ao inserir dados
';
} else {
echo '
registro copiado
';
}
}
}

private function extrairCamposArquivoXML($campos, $elemento, $i){
$doc = new DomDocument;
// Carrega o arquivo XML com um arquivo DOMDocument
$doc->Load($this->arquivoXML);
$items = $doc->getElementsByTagName($elemento);
$valor = array();
foreach ($campos as $campo) {
$valor[] = "'" . $items->item($i)->getElementsByTagName($campo)->item(0)->nodeValue . "'";
}

$value = ' (';
$value .= implode(',', $valor);
$value .=
') ';

return $value;
}

private function extrairQuantidadeItensArquivoXML($elemento){
$doc = new DomDocument;
// Carrega o arquivo XML com um arquivo DOMDocument
$doc->Load($this->arquivoXML);
$items = $doc->getElementsByTagName($elemento);
return $items->length;
}

private function criarQueryImportacaoXML($campos, $elemento, $tabela, $colunas, $quantidade){
$query = "insert into $tabela (";
$query .= implode (",",$colunas);
$query .= ") values ";
$query .= $this->extrairCamposArquivoXML($campos, $elemento, $quantidade);
echo $query;
return $query;
}

private function importarUsuarios(){

$elemento = 'Actor';
$campos = array('ActorID','ActorName','Login','Password','Email','IsActive');

$tabela = 'usuario';
$colunas = array('id','nome','login','senha','email','ativo');

for ($i=0; $i < $this->extrairQuantidadeItensArquivoXML($elemento); $i++) {
$this->executarSQL($this->criarQueryImportacaoXML($campos, $elemento, $tabela, $colunas, $i));
echo '';
}
}

private function importarMaterias(){

$elemento = 'Info';
$campos = array('InfoID','Title','Summary','ActorID','HeadLineImage','FullText', 'State', 'SectionID');

$tabela = 'materia';
$colunas = array('id','titulo','subtitulo','idUsuario','imagem','texto', 'estado', 'idSecao');
for ($i=0; $i < $this->extrairQuantidadeItensArquivoXML($elemento); $i++) {
$this->executarSQL($this->criarQueryImportacaoXML($campos, $elemento, $tabela, $colunas, $i));
echo '';
}
}

private function importarSecao(){

$elemento = 'Section';
$campos = array('SectionID','SectionName','Description','URL','infoOrderCriteria','ParentSectionID', 'tag');

$tabela = 'secao';
$colunas = array('id','nome','descricao','link','ordem','idSecaoPai', 'tag');
for ($i=0; $i < $this->extrairQuantidadeItensArquivoXML($elemento); $i++) {
$this->executarSQL($this->criarQueryImportacaoXML($campos, $elemento, $tabela, $colunas, $i));
echo '';
}
}

public function principal(){
$this->construirBase();
echo "===========================================
";
echo "=== IMPORTANDO DADOS DOS USUÁRIOS =======
";
echo "===========================================
";
$this->importarUsuarios();
echo "===========================================
";
echo "=== IMPORTANDO DADOS DAS MATERIAS =======
";
echo "===========================================
";
$this->importarMaterias();
echo "===========================================
";
echo "=== IMPORTANDO DADOS DAS SECOES =======
";
echo "===========================================
";
$this->importarSecao();
echo "===========================================
";
echo "IMPORTAÇÃO ENCERRADA CONFIRA A BASE DE DADOS
";
echo "===========================================
";
}

}
$importar = new Importacao(false, 'diego', 'database.xml');
$importar->principal();
?>



Creditos à Diego Muniz Cerqueira
João Marcelo
João Marcelo Geek Registrado
3K Mensagens 71 Curtidas
#10 Por João Marcelo
04/08/2011 - 08:09
Ximenes, muito obrigado pela ajuda, mas com a dica do jofrelscalvet para mostrar o erro do script eu já consegui resolver. O problema era que, apesar do no site a linha " $query = 'insert into exemplo (GM8_DTATEND, GCS_NOMLOC, GM8_HORAGE, RA_NOME, GM8_MATRIC, GM8_CELULAR) values ("%s", "%s", "%s", "%s", "%s")'; " fazer referência ao XML, na verdade ela deve fazer aos campos da tabela exemplo MySQL. Agora isso parece óbvio, mas demorei para perceber.

Mesmo assim seu script está anotado e com certeza será estudado.
Obrigado novamente.

Abraços,

João Marcelo
Melhor que ficar esperando resposta é pesquisar e ter a resposta na hora. isso_ai.png

Up The Irons!



waldony ximenes
waldony xime... Super Participante Registrado
612 Mensagens 46 Curtidas
#11 Por waldony xime...
04/08/2011 - 17:21
João Marcelo disse:
Ximenes, muito obrigado pela ajuda, mas com a dica do jofrelscalvet para mostrar o erro do script eu já consegui resolver. O problema era que, apesar do no site a linha " $query = 'insert into exemplo (GM8_DTATEND, GCS_NOMLOC, GM8_HORAGE, RA_NOME, GM8_MATRIC, GM8_CELULAR) values ("%s", "%s", "%s", "%s", "%s")'; " fazer referência ao XML, na verdade ela deve fazer aos campos da tabela exemplo MySQL. Agora isso parece óbvio, mas demorei para perceber.

Mesmo assim seu script está anotado e com certeza será estudado.
Obrigado novamente.

Abraços,

João Marcelo


Valeu posta ai o script todo se puder, e não esquece de colocar resolvido no titulo para futuras duvidas.

Abraço...
João Marcelo
João Marcelo Geek Registrado
3K Mensagens 71 Curtidas
#12 Por João Marcelo
05/08/2011 - 09:45
Segue o script:


<?php

// modificado por JM
$banco = 'xml2mysql';
$host = '127.0.0.1'; // host
$usuario = 'root'; // usuario
$senha = 'senha'; // senha

mysql_connect($host, $usuario, $senha);
mysql_select_db($banco);

$query = 'insert into exemplo (data, local, hora, nome, matricula, celular) values ("%s", "%s", "%s", "%s", "%s", "%s")';

$xml = file_get_contents('demo.xml');

$sxml = new SimpleXMLElement($xml);

foreach ($sxml as $linhaAtual) {
$data = (string) $linhaAtual->GM8_DTATEND;
$local = (string) $linhaAtual->GCS_NOMLOC;
$hora = (string) $linhaAtual->GM8_HORAGE;
$nome = (string) $linhaAtual->RA_NOME;
$matricula = (string) $linhaAtual->GM8_MATRIC;
$celular = (string) $linhaAtual->GM8_CELULA;

$tmpQuery = sprintf($query, $data, $local, $hora, $nome, $matricula, $celular);

echo sprintf('Executando query: %s%s', $tmpQuery, "\n");

mysql_query($tmpQuery);
echo "\n
Mysql error: " .mysql_error() . "\n
";
}

Preferi deixar a última linha como aviso de minha noobisse :/

Obrigado a todos! isso_ai.png
Melhor que ficar esperando resposta é pesquisar e ter a resposta na hora. isso_ai.png

Up The Irons!



Responder Tópico
© 1999-2024 Hardware.com.br. Todos os direitos reservados.
Imagem do Modal