Gerar XML com PHP e XMLWriter

Publicado: setembro 29, 2009 em PHP, XML

Olá,
Mais um exemplo de como gerar XML com PHP5,  neste caso iremos utilizar a Classe nativa do PHP5  o XMLWriter para gerar a saída XML formatada.

Este exemplo, sem dúvidas é bem mais simples que o anterior que utiliza o DOM ou SimpleXML.

Vejamos o código:

<?
# Instancia do objeto XMLWriter
$xml = new XMLWriter;

# Cria memoria para armazenar a saida
$xml->openMemory();

# Inicia o cabeçalho do documento XML
$xml->startDocument( '1.0' , 'iso-8859-1' );

# Adiciona/Inicia um Elemento / Nó Pai <item>
$xml->startElement("item");

#  Adiciona um Nó Filho <quantidade> e valor 8
$xml->writeElement("quantidade", 8);

#  Adiciona um Nó Filho <preco> e valor 110
$xml->writeElement("preco", 110);

#  Finaliza o Nó Pai / Elemento <Item>
$xml->endElement();

#  Configura a saida do conteúdo para o formato XML
header( 'Content-type: text/xml' );

# Imprime os dados armazenados
print $xml->outputMemory(true);

# Salvando o arquivo em disco
# retorna erro se o header foi definido
# retorna erro se outputMemory já foi chamado
$file = fopen('foo.xml','w+');
fwrite($file,$xml->outputMemory(true));
fclose($file);
?>

Obs: A chamada ao método $xml->outputMemory() descarrega os dados da memória então você só consegue chama-lo uma vez, logo, para salvar o arquivo você não pode ter chamado este método ainda.

Para salvar o arquivo corretamente você deve comentar as linhas abaixo:

# header( ‘Content-type: text/xml’ );
# print $xml->outputMemory(true);

Comente as linhas abaixo para apenas exibir o XML no browser:

# $file = fopen(‘foo.xml’,'w+’);
# fwrite($file,$xml->outputMemory(true));
# fclose($file);

Referência: http://br.php.net/manual/pt_BR/book.xmlwriter.php

 

Por enquanto é isso galera, bom divertimento e até mais.

Comentários
  1. JULIOOXX disse:

    Boa camarada!

  2. Thiago disse:

    Ótimo exemplo. Claro e preciso!
    Parabéns!

  3. Mônica disse:

    Prezado Rafael,

    Necessito de uma ajudinha urgente.

    Tenho um form em html com 4 campos que tem como action uma página em php que exibe os dados digitados na página html.
    Além de exibir os dados, necessito gerar um arquivo XML com os dados digitados no form.

    Agradeço desde já a ajuda.

    • Rafael Clares disse:

      Mônica você precisa apenas substituir os dados do xml proposto neste exemplo pelos dados do post, ex:
      Supondo que os campos do formulário sejam nome, email e fone,

      <?php
      extract($_POST);
      // aqui o inicio do xml como no exemplo
      .
      .
      // aqui os elementos com os valores dos campos
      $xml->writeElement("nome", "$nome");
      $xml->writeElement("email", "$email");
      $xml->writeElement("fone", "$fone");
      .
      .
      //restande do xml como no exemplo
      ?>

      Obs: o extract($_POST) cria automaticamente as var $nome, $email e $fone com os valores vindos do XML
      Espero ter ajudado, mesmo pq eu não encontrei um forma de simplificar o exemplo e a explicação.
      Boa sorte

      • Mônica disse:

        Rafael, desculpe incomodá-lo.
        A minha página de ação ficou assim:

        openMemory();

        # Inicia o cabeçalho do documento XML
        $xml->startDocument( ’1.0′ , ‘iso-8859-1′ );

        # Adiciona/Inicia um Elemento / Nó Pai
        #$xml->startElement(“item”);
        $xml->startElement(“Automóvel”);

        $xml->writeElement(“modelo”, “$modelo”);
        $xml->writeElement(“cor”, “$cor”);
        $xml->writeElement(“fabricante”, “$fabricante”);
        $xml->writeElement(“ano”, “$ano”);

        # Finaliza o Nó Pai / Elemento
        $xml->endElement();

        # Configura a saida do conteúdo para o formato XML
        header( ‘Content-type: text/xml’ );

        # Imprime os dados armazenados
        print $xml->outputMemory(true);

        # Salvando o arquivo em disco
        # retorna erro se o header foi definido
        # retorna erro se outputMemory já foi chamado
        #$file = fopen(‘foo.xml’,'w+’);
        $file = fopen(‘auto.xml’,'w+’);
        fwrite($file,$xml->outputMemory(true));
        fclose($file);
        ?>

        E infelizmente não acontece nada.
        Mais uma vez muito obrigada.

      • Rafael Clares disse:

        Mônica, não faltou o extract($_POST) ?

        extract($_POST);
        openMemory();

        # Inicia o cabeçalho do documento XML
        $xml->startDocument( ’1.0′ , ‘iso-8859-1′ );

        # Adiciona/Inicia um Elemento / Nó Pai
        #$xml->startElement(“item”);
        $xml->startElement(“Automóvel”);

        $xml->writeElement(“modelo”, “$modelo”);
        $xml->writeElement(“cor”, “$cor”);
        $xml->writeElement(“fabricante”, “$fabricante”);
        $xml->writeElement(“ano”, “$ano”);

        # Finaliza o Nó Pai / Elemento
        $xml->endElement();

        # Configura a saida do conteúdo para o formato XML
        header( ‘Content-type: text/xml’ );

        # Imprime os dados armazenados
        print $xml->outputMemory(true);

        # Salvando o arquivo em disco
        # retorna erro se o header foi definido
        # retorna erro se outputMemory já foi chamado
        #$file = fopen(‘foo.xml’,’w+’);
        $file = fopen(‘auto.xml’,’w+’);
        fwrite($file,$xml->outputMemory(true));
        fclose($file);
        ?>

  4. Mônica disse:

    Perdão, segue o código. Coloquei o extract($_POST) sim. Veja abaixo:

    openMemory();

    # Inicia o cabeçalho do documento XML
    $xml->startDocument( ’1.0′ , ‘iso-8859-1′ );

    # Adiciona/Inicia um Elemento / Nó Pai
    #$xml->startElement(“item”);
    $xml->startElement(“Automóvel”);

    $xml->writeElement(“modelo”, “$modelo”);
    $xml->writeElement(“cor”, “$cor”);
    $xml->writeElement(“fabricante”, “$fabricante”);
    $xml->writeElement(“ano”, “$ano”);

    # Finaliza o Nó Pai / Elemento
    $xml->endElement();

    # Configura a saida do conteúdo para o formato XML
    header( ‘Content-type: text/xml’ );

    # Imprime os dados armazenados
    print $xml->outputMemory(true);

    # Salvando o arquivo em disco
    # retorna erro se o header foi definido
    # retorna erro se outputMemory já foi chamado
    #$file = fopen(‘foo.xml’,'w+’);
    $file = fopen(‘auto.xml’,'w+’);
    fwrite($file,$xml->outputMemory(true));
    fclose($file);
    ?>

    E nada acontece.
    Desculpe pelo incômodo. Sou nova em php.
    Obrigada.

  5. Mônica disse:

    Apesar de não aparecer no código acima tem o extract($_POST) e a Instancia do objeto XMLWriter
    $xml = new XMLWriter;

    Obrigada.

    • Rafael Clares disse:

      Mônica, olha só ou você imprime na tela ou salva em disco, entendeu ? os 2 não vai rolar, ao menos não nessa ordem.
      Se você precisa salvar em disco, basta fazer:


      <?
      extract($_POST);
      $xml = new XMLWriter;
      $xml->openMemory();
      $xml->startDocument( '1.0' , 'iso-8859-1' );
      $xml->startElement("Automovel");
      $xml->writeElement("modelo", "$modelo");
      $xml->writeElement("cor", "$cor");
      $xml->writeElement("fabricante", "$fabricante");
      $xml->writeElement("ano", "$ano");
      $xml->endElement();
      //header( 'Content-type: text/xml' );
      //print $xml->outputMemory(true);
      $file = fopen('auto.xml','w+');
      fwrite($file, $xml->outputMemory(true));
      fclose($file);
      ?>

      Se quer exibir na tela:

      <?
      extract($_POST);
      $xml = new XMLWriter;
      $xml->openMemory();
      $xml->startDocument( '1.0' , 'iso-8859-1' );
      $xml->startElement("Automovel");
      $xml->writeElement("modelo", "$modelo");
      $xml->writeElement("cor", "$cor");
      $xml->writeElement("fabricante", "$fabricante");
      $xml->writeElement("ano", "$ano");
      $xml->endElement();
      header( 'Content-type: text/xml' );
      print $xml->outputMemory(true);
      ?>

      Testei os 2 com e funcionou corretamente, não se esqueça que para gravar no disco precisa da permissão de gravação no diretório.

      Te mandei meu exemplo por email, mas por favor não faça perguntas por email, assim talvez possamos ajudar outras pessoas.

      obs: os 2 não dá certo porque quando ocorre a primeira vez o $xml->outputMemory(true) ele libera da memória o conteúdo.
      abraços

  6. Mônica disse:

    Funcionou certinho como vc falou.

    Muito obrigada.

  7. Mônica disse:

    Rafael,

    Tenho a seguinte situação:

    Na página de ação (resultado.php) preciso exibir os dados digitados no form e depois gerar o xml com estes dados. Como não conheço muito PHP, pensei em fazer isso:
    Sei que ainda vou precisar muito da sua ajuda mas não vou desistir de forma alguma!

    Obrigada.

    • Rafael Clares disse:

      Mônica, o ideal é que o arquivo que gera o xml faça apenas isso, porque a saída dele é em XML e qualquer outra coisa irá atrapalhar a saída…
      Evite colocar aqui nos comentários as tags < e > porque além de não aparecer acaba bagunçando o resto, não entendi o problema ainda,
      vamos fazer assim, eu acredito que você esteja tentando de toda forma mas vamos abstrair algumas informações ok.

      Então, você tem um formulário e quer que seja exibido seu conteúdo (digitado pelo usuário) e em seguida seja gravado no XML, é isso ?
      O cara tem que confirmar após ser mostrado na tela ou ao mesmo tempo que mostra também grava o arquivo ?
      O que você está fazendo é gravar o arquivo ou exibir? Se for exibir, o conteúdo deve ser exclusivamente o XML, se colocar outra coisa junto invalidará o XML.

      • Mônica disse:

        Tenho um form (com um action=resultado.php) chamado cadastro.html com os campos: modelo, cor, fabricante e ano.
        Após o seu correto preenchimento e clicar no botão Enviar sou direcionada a página resultado.php onde tenho que fazer duas coisas:

        1) Exibir os dados digitados no form (cadastro.html);
        2) Gravar estes dados num arquivo xml qualquer.

        O usuário pode ou não confirmar a gravação, tanto faz. A ordem é o que interessa. Primeiro visualizo os dados e depois gravo no XML.

        A minha dúvida é: Como fazer essas duas coisas?

        Mais uma vez muito obrigada.

    • Rafael Clares disse:

      Vê se é isso que quer fazer:

      <?php

      extract($_POST);

      print "Modelo: $modelo <br />";
      print "Cor: $cor <br />";
      print "Ano: $ano <br />";
      print "Fabricante: $fabricante <br />";

      $xml = new XMLWriter;
      $xml->openMemory();
      $xml->startDocument( '1.0' , 'iso-8859-1' );
      $xml->startElement("Automovel");
      $xml->writeElement("modelo", "$modelo");
      $xml->writeElement("cor", "$cor");
      $xml->writeElement("fabricante", "$fabricante");
      $xml->writeElement("ano", "$ano");
      $xml->endElement();
      //header( 'Content-type: text/xml' );
      //print $xml->outputMemory(true);
      $file = fopen('auto.xml','w+');
      fwrite($file, $xml->outputMemory(true));
      fclose($file);
      ?>

  8. Mônica disse:

    É exatamente isso!

    O meu erro foi ter colocado a exibição dos dados dentro de uma table.

    Espero que a minha dúvida possa ajudar outras pessoas.

    Mais uma vez muito obrigada.

  9. Monica disse:

    Bom dia Rafael,

    Tenho mais uma dúvida a respeito do que trocamos idéia ontem.
    Meu XML tem que gerar a data em que o arquivo foi criado.

    ex.

    O que coloco em que posição no código????

    • Rafael Clares disse:

      Onde vai ter a data, no XML mesmo ou no nome do arquivo ? ex: auto_10_10_2010.xml
      Mesmo pq se 2 pessoas cadastrarem ao mesmo tempo vai dar erro por que cada um estará criando o mesmo arquivo,
      pense nisso, a data atual é:
      $data = date(‘d/m/Y’); // reproduz 13/10/2010
      $data = date(‘d-m-Y’); // reproduz 13-10-2010
      Bem, acho que entendeu, você pode utilizar qualquer caracter para separar os números ali em date.

  10. Monica disse:

    Bom dia Rafael,

    A data tem que constar na página XML gerada pelo preenchimento do cadastro.
    Portanto se entendi tenho que inserir essa linha dentro do código da página resultado.php que vc passou acima.

    Vc poderia me dizer onde devo colocá-la? Já fiz alguns testes e deu erro.

    Desculpe ficar te alugando mais estou mais acostumada com ASP e estou tendo dificuldade para fazer esse código no PHP.

    Mais uma vez agradeço a força.

    [ ]‘s

    • Rafael Clares disse:

      Mônica, sei que está sendo o mais direta possível mas confesso que ainda não sei onde você quer colocar esse valor, por isso fica difícil eu dizer onde deve colocar o código.
      Se a data vai no XML, logo, você precisa de mais um elemento no XML, assim como tem o fabricante, ano, modelo, teria o data também.
      Se a data não precisa ir no xml e você precisa saber quando o arquivo foi gerado, você pode colocar a data no nome do arquivo, assim irá armazenar os arquivos sem que sejam substituidos.
      ex: na linha que grava o xml:
      $file = fopen(‘auto.xml’,'w+’);

      você pode alterar o nome colocando a data:
      $nomeDoXML = date(‘dmY’).”.xml”;
      $file = fopen(“$nomeDoXML”,’w+’);

      assim, você terá os arquivos com nome dessa forma: 15102010.xml (15/10/2010);

      tchau

  11. Alysson disse:

    Rafael, Boa tarde.
    Precisava de um código que permita editar um registro de um arquivo xml, eu seleciono o item e os valores ficariam disponíveis em um form para edição…
    Vc pode indicar alguma referência?
    Obrigado.

    • Rafael Clares disse:

      Alysson, me desulpe não poder ajuda-lo com este código mas confesso que há algum tempo já que venho ensaiando pra escrever esse código,. infelizmente estou sem tempo e talvez no começo do ano eu o faça.; abs

  12. Carlos Sá disse:

    Bom dia, estou tendo dificuldade ao criar o xml pois apresenta um erro , na qual estou pesquisando e gosaria de uma ajuda de vocês.
    Segue abaixo o código com o erro.

    # Instancia do objeto XMLWriter
    $xml = new XMLWriter;
    # Cria memoria para armazenar a saida
    $xml->openMemory();
    # Inicia o cabeçalho do documento XML
    $xml->startDocument( ’1.0′ ,’iso-8859-1′);
    $xml->setIndent(true);
    # Adiciona/Inicia um Elemento / Nó Pai
    $xml->startElement(“EMPRESA”);
    $xml->writeElement(“CODIGO_EMPRE”,’254′);
    $xml->writeElement(“CODIGO_AGENTE”,’356′);
    $xml->writeElement(“DATA_CADASTRO”,’04/2011′);
    $xml->writeElement(“OBSEMP”,’O processo de licenciamento ambiental das obras foi solicitado em 22/03/2010, sendo o termo não liberado’);
    $xml->endElement();
    $file = fopen(‘../Img/xml/teste1.xml’,'w+’);
    fwrite($file,$xml->outputMemory(true));
    fclose($file);

    Apos executar aparece este erro:
    Warning: XMLWriter::outputMemory() [xmlwriter.outputmemory]: output conversion failed due to conv error, bytes 0xE3 0x6F 0×20 0x6C
    Quando retirei a metade do campo OBSEMP ele rodou , ou seja eu acho que o problema seja no tamnanho da string do $xml , gostaria de uma ajuda de vocês para resolver este problema.

    • Rafael Clares disse:

      Faça um teste retirando palavras com acentos e me retorne para eu poder te ajudar.
      Abs

      • Carlos Sá disse:

        Obrigado pela ajuda, realmente era os acentos.
        Os detalhes fazem a diferença.

      • Rafael Clares disse:

        Carlos, mas você precisa do texto com acento, não é ?

        Altere a linha:
        $xml->startDocument( ’1.0′ ,’iso-8859-1′);

        Para:
        $xml->startDocument( ’1.0′ ,’utf-8′);

        E faça um teste para ver se irá gravar corretamente, o correto seria com iso-8859-1 mas não custa nada tentar!
        abs

  13. Bruno Melo disse:

    Pessoal,

    estou com uma dificuldade, estou gerando o xml como vocês estavam falando acima, mais só que se eu acessar o sistema de outra maquina e tentar gerar o xml ele gera mais não me dar a opção de salvar no meu pc só salva no servidor e pronto. Como eu faço para poder salvar no servidor e fazer o download do xml de outro pc.

  14. Bruno Melo disse:

    estou usando no final do arquivo o seguinte:

    header(‘Content-Description: File Transfer’);
    header(‘Content-Disposition: attachment; filename=”‘.$nome_xml.’”‘);
    header(‘Content-Type: application/octet-stream’);

    header(‘Content-Transfer-Encoding: binary’);
    header(‘Content-Length: ‘ . filesize($arquivoLocal));
    header(‘Cache-Control: must-revalidate, post-check=0, pre-check=0′);
    header(‘Expires: 0′);

    // Envia o arquivo para o cliente
    readfile($arquivoLocal);

    na maquina que o sistema se encontra funciona mais acessando de outro maquina não funciona

    • Rafael Clares disse:

      Bruno faça o seguinte:

      $fileName = “foo.xml”;
      $handler = fopen(“$fileName”,”w+”);
      fwrite($handler,$xml->outputMemory(true));
      header(“Pragma: public”);
      header(“Expires: 0″);
      header(“Cache-Control: must-revalidate, post-check=0, pre-check=0″);
      header(“Cache-Control: private”,false);
      header(“Content-type: application/force-download”);
      header(“Content-Disposition: attachment; filename=\”$fileName\”");
      header(“Content-Transfer-Encoding: binary”);
      readfile(“$fileName”);

      Teste em:
      http://clareslab.com.br/learn/phptoxml/download.php

      Mandei o arquivo no seu email :
      Obs: não respondo dúvidas por email, na verdade, nem as leio.
      Abraços

  15. tchelosrpMarcelo disse:

    Bom dia,

    Eu preciso armazenar uns dados de um form, está gravando certinho no xml, porem, cada vez que eu salvo um dado diferente, ele sobrescreve o antigo.

    Como eu faço pra ele ir armazenando em sequencia?

    Obrigado.

    • Rafael Clares disse:

      Marcelo, o ideal é usar o XML para armazenar o resultado de um consulta e poder utiliza-lo para transportar dados de uma aplicação para outra ou algo do tipo.;
      Utilizar o XML como banco de dados é possível e também complexo, não tenho como escrever a aplicação para você mas segue a dica:
      1 – você lê o XML atual
      2 – transforma os dados do XML em array (procure no google XML2Array)
      3 – adiciona a nova informação/registro no array
      4 – salva os dados do array no XML

      Seria básicamente isso!

  16. Carlos Sá disse:

    Novamente venho pedir a ajuda, o problema relatado antes foi resolvido colocando o $xml->startDocument( ’1.0′ ,’utf-8′), mais preciso gerar em iso-8859-1, alguém sabe o porque não está gerando com acentos ???

    # Instancia do objeto XMLWriter
    $xml = new XMLWriter;
    # Cria memoria para armazenar a saida
    $xml->openMemory();
    # Inicia o cabeçalho do documento XML
    $xml->startDocument( ’1.0′ ,’iso-8859-1′);
    $xml->setIndent(true);
    # Adiciona/Inicia um Elemento / Nó Pai
    $xml->startElement(“EMPRESA”);
    $xml->writeElement(“CODIGO_EMPRE”,’254′);
    $xml->writeElement(“CODIGO_AGENTE”,’356′);
    $xml->writeElement(“DATA_CADASTRO”,’04/2011′);
    $xml->writeElement(“OBSEMP”,’O processo de licenciamento ambiental das obras foi solicitado em 22/03/2010, sendo o termo não liberado’);
    $xml->endElement();
    $file = fopen(‘../Img/xml/teste1.xml’,’w+’);
    fwrite($file,$xml->outputMemory(true));
    fclose($file);

    Apos executar aparece este erro:
    Warning: XMLWriter::outputMemory() [xmlwriter.outputmemory]: output conversion failed due to conv error, bytes 0xE3 0x6F 0×20 0x6C

  17. Mozart disse:

    Excelente post! Ajudou muito, obrigadão!

  18. Jonatas disse:

    Boa noite Rafael,
    Parabéns pelo post, me ajudou muito, mas ainda me resta uma dúvida.
    Como faço para editar este xml, incluir um novo nó ou remover?
    Abçs

  19. Boa noite, estou precisando de uma ajuda, preciso montar uma agenda de serviços no meu site onde eu tenho um calendário anual e gostaria que meus clientes ao clicar no dia desejado pudesse marcar o serviço com nome, telefone, dia ou semana, e o serviço (os) solicitados, e que caso queiram possam efetuar o pagamento do serviço (os) antecipadamente.
    Att Mauricio Campos

    • Rafael Clares disse:

      Mauricio, se procurar no google por “PHP calendar” verá que já existem diversas soluções prontas com a maioria das características que mencionou!
      Talvez você possa alterar/incluir mais recursos em uma delas. Fazer do zero talvez não seja a melhor opção no seu caso se você não quer ter gastos com o sistema!

  20. geovanek disse:

    Muito excelente esse tópico…

    Só uma perguntinha, tem como eu colocar uma quebra de linha ou algo do tipo?
    No caso, estou criando esse nó.
    # –
    $xml->writeElement(“fonts”, ‘
    ‘);

    E o resultado dele fica assim:

    Mas eu gostaria de que ele ficasse assim:

    Tem como?

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Sair / Alterar )

Imagem do Twitter

You are commenting using your Twitter account. Sair / Alterar )

Foto do Facebook

You are commenting using your Facebook account. Sair / Alterar )

Connecting to %s