Terça-feira, 17 de outubro de 2006 às 11h42

Recebendo XML no Flash

Faltam -1 dias! Inscreva-se agora! O maior encontro de profissionais web da américa latina.

Receber dados externos usando LoadVars é fácil, mas receber em XML é mais organizado e fácil de ser padronizado. A exemplo disso, temos o RSS, que nada mais é do que um formato padrão de organizar informações em XML de forma que qualquer outro sistema que reconheça este padrão possa exibi-lo corretamente. Por essa razão, vamos aprender como receber um XML no Flash, mas vamos usar um formato mais simples para analisar do que o formato RSS.

Para compreender melhor este artigo, é necessário que já se tenha um conhecimento considerável de Array e Object, caso contrário se preferir uma boa opção é usar o LoadVars para receber dados no Flash, que apesar de usar um objeto ainda assim é bem mais simples.

Agora, digamos então que carregamos um XML para um objeto XML no Flash, que o chamaremos de meuXML, no qual para exibir um único valor, temos de usar uma pequena linha como esta:

meuXML.firstChild.childNodes[1].childNodes[1].childNodes[2].childNodes[0].nodeValue

Dá vontade de desistir antes mesmo de começar, afinal isso não faz lá muito sentido, não é? O fato é que só recebemos os dados assim porque, com o tempo, percebemos que é uma das formas mais práticas de se fazer isso. Por um momento, vamos esquecer o XML e analisar tratamento de string abaixo:

// Definimos o valor para uma variável.
var palavra:String = "Flash;Css;Php;Ajax;Linux";
trace("palavra: " + palavra);
// Agora queremos colocar tudo em caixa alta, ou seja, em letras maiúsculas.
var caixaAlta:String = palavra.toUpperCase();
trace("caixaAlta: " + caixaAlta);
// Já que estão todos separados por ponto-e-vírgula, vamos usar isso como um separador e organizar tudo em um Array.
var meu_array:Array = caixaAlta.split(';');
trace("meu_array: " + meu_array);
// Por fim, queremos exibir apenas o primeiro item do Array.
var item:String = meu_array[0];
trace("item: " + item);

Agora, se já sabemos que vamos colocar todo o texto em caixa alta, separá-lo em um Array e por fim exibir o primeiro elemento do Array, então podemos simplificar um pouco assim:

var meu_array2:Array = String("Flash;Css;Php;Ajax;Linux").toUpperCase().split(";");
trace(meu_array2[0]);

Como podem ver, não precisamos colocar o retorno de um método em uma variável para usar outro método; o Flash compreende que, como nos exemplos acima, o retorno de um dos métodos é uma string, então podemos continuar usando métodos referentes ao tipo de retorno até acharmos necessário. No exemplo do meuXML, cada um daqueles métodos continuavam a nos retornar um outro objeto XML, então fomos usando os métodos que manipulam XML até chegar ao childNodes que acesse o nó que queríamos.

Entendendo o XML

Vamos, então, montar uma estrutura XML para enviar para o Flash, salvando-o como dados.xml:

<?xml version="1.0" encoding="iso-8859-1"?>
<MeuSite>
    <TopicoNoticias>
        <Registro id="1">
            <Titulo>Recebendo dados no Flash</Titulo>
            <Descricao>Como receber dados externos no Flash usando LoadVars...</Descricao>
            <Link>http://www.imasters.com.br/artigo/4351/flash/recebendo_dados_no_flash/</Link>
            <Fonte><![CDATA[IMasters > http://www.imasters.com.br ]]></Fonte>
        </Registro>
        <Registro id="2">
            <Titulo>Extensão PHP Debugger para o Dreamweaver</Titulo>
            <Descricao>Abordarei, neste artigo, a extensão PHP Debugger...</Descricao>
            <Link>http://www.imasters.com.br/artigo/4131/dreamweaver/extensao_php_de...</Link>
            <Fonte><![CDATA[IMasters > http://www.imasters.com.br ]]></Fonte>
        </Registro>
        <Registro id="3">
            <Titulo>Usando MXML</Titulo>
            <Descricao>Nesse artigo você vai aprender como usar o MXML...</Descricao>
            <Link>http://www.imasters.com.br/artigo/4131/dreamweaver/extensao_php_deb...</Link>
            <Fonte><![CDATA[IMasters > http://www.imasters.com.br ]]></Fonte>
        </Registro>
    </TopicoNoticias>
    <UltimasForum>
        <Registro id="1">
            <Titulo>Como localizar apenas o que se quer na consulta</Titulo>
            <SubTitulo>Estou com problemas para a consulta retornar apenas o que foi pedido</SubTitulo>
            <Link>http://forum.imasters.com.br/index.php?showtopic=195667</Link>
            <Fonte><![CDATA[Fórum IMasters > http://forum.imasters.com.br ]]></Fonte>
        </Registro>
        <Registro id="2">
            <Titulo>Firefox não está lendo posição bottom</Titulo>
            <SubTitulo>background-position:bottom - erro</SubTitulo>
            <Link>http://forum.imasters.com.br/index.php?showtopic=195687</Link>
            <Fonte><![CDATA[Fórum IMasters > http://forum.imasters.com.br ]]></Fonte>
        </Registro>
        <Registro id="3">
            <Titulo>servidor DNS em rede Wi-Fi</Titulo>
            <SubTitulo>Servidor DNS não inicia... será culpa do Wi-Fi??</SubTitulo>
            <Link>http://forum.imasters.com.br/index.php?showtopic=194194</Link>
            <Fonte><![CDATA[Fórum IMasters > http://forum.imasters.com.br ]]></Fonte>
        </Registro>
    </UltimasForum>
</MeuSite>

Agora vamos interpretar este XML. Na primeira linha, colocamos a versão do XML, a sua codificação e, em seguida, temos o primeiro nó que definimos como meuSite. Os nós tem propriedades, iniciam e terminam exatamente como na maioria das tags HTML: <nome_do_nó propriedade="valor"> outros nós ou valores </nome_do_nó>.

Em uma estrutura XML, podemos praticamente colocar o que quisermos para definir os nomes dos nós, propriedades e seus valores, é quase como um HTML personalizado. Para interpretar sua hiearrquia de estrutura, podemos dizer que: MeuSite é o nó pai de todos os nós dentro dele, assim como o nó TopicoNoticia também é o nó pai de todos os que estiverem dentro dele, mas é nó filho de MeuSite.

Quando chegarmos ao fim de nossa estrutura, não colocaremos mais nós dentro de nós mas sim textos para que esses nós sejam como varáveis e para que possamos acessar estes textos. Este é o caso dos nós filhos do nó Registro que possuem apenas textos dentro deles:

- <Registro id="1">
    <Titulo>Recebendo dados no Flash</Titulo>
    <Descricao>Como receber dados externos no Flash usando LoadVars...</Descricao>
    <Link>http://www.imasters.com.br/artigo/4351/flash/recebendo_dados_no_flash/</Link>
    <Fonte><![CDATA[IMasters > http://www.imasters.com.br ]]></Fonte>
</Registro>

Pode ser que tenhamos que colocar sinais como "<" ou ">" no texto; neste caso, podemos deixar o texto assim:

<Fonte><![CDATA[ IMasters > http://www.imasters.com.br ]]></Fonte>

O CDATA permite que coloquemos qualquer informação dentro dele sem que seja interpretado pelo XML, como no caso dos sinais de ">" e "<", que para o XML representam o fechamento e a abertura de um nó.

Recebendo o XML no Flash

Tendo o XML pronto, vamos colocar o script que carregará os dados para o Flash:

System.useCodepage = true;
var MeuXML:XML = new XML();
// Ignoramos todas as quebras de linhas e espaços entre os nós para não atrapalhar na interpretação do XML.
MeuXML.ignoreWhite = true;
// Este método será executado ao fim do carregamento dos dados ou em caso de erro.
MeuXML.onLoad = function($sucesso){
if($sucesso){ // Em caso de sucesso
// Vejamos, então, qual é o primeiro nó deste objeto XML.
trace(MeuXML.childNodes[0].nodeName); // MeuSite
// Vejamos os objetos que estão dentro dele.
trace(MeuXML.firstChild.childNodes[0].nodeName); // TopicoNoticias
trace(MeuXML.firstChild.childNodes[1].nodeName); // UltimasForum
// Sabemos que o primeiro nó é único, não pode haver outros com ele; então, podemos usar o firstChild, que é exatamente a mesma coisa que usar childNodes[0], entre um e o outro não há diferenças.
// Vamos acessar o 3º nó dentro de TopicoNoticias.
trace(MeuXML.firstChild.firstChild.childNodes[2].nodeName); // Registro
// Lembram-se de que colocamos uma propriedade id para os nós de Registro? Vamos verificar se estamos mesmo acessando o terceiro registro.
// Este é um dos casos de objeto dentro de objeto, pois attributes é um objeto que conterá todas as propriedades do nó correspondente.
trace(MeuXML.firstChild.firstChild.childNodes[2].attributes.id); // 3
// Agora, dentro de registros, colocamos nós apenas com alguns valores; então, vamos exibí-los
// Acessamos o nó Titulo e exibimos seu valor.
trace(MeuXML.firstChild.firstChild.childNodes[2].childNodes[0].firstChild.nodeValue);
// Acessamos o nó Descricao e exibimos seu valor.
trace(MeuXML.firstChild.firstChild.childNodes[2].childNodes[1].firstChild.nodeValue);
// Acessamos o nó Link e exibimos seu valor.
trace(MeuXML.firstChild.firstChild.childNodes[2].childNodes[2].firstChild.nodeValue);
// Acessamos o nó Fonte e exibimos seu valor.
trace(MeuXML.firstChild.firstChild.childNodes[2].childNodes[3].firstChild.nodeValue);
// Perceba que, apesar de não termos colocado nenhum nó dentro deles temos de acessar seus valores como se os valores estivessem dentro de um último nó.
}else{ // Em caso de erro
trace($sucesso);
trace("Ocorreu algum erro ao carregar os dados.");
}
}
// Carregar dados do XML.
MeuXML.load("dados.xml");

Perceberam como acessamos os nós do XML? Uma vez carregado para o objeto XML do Flash, a estrutura não é acessada da forma como a vemos no navegador; se fôssemos exibir a estrutura na tela depois de recebida pelo Flash, ela teria outra aparência. Veja, se visualizarmos uma parte da estrutura XML é vista assim no navegador:

<?xml version="1.0" encoding="iso-8859-1" ?>
- <MeuSite>
    - <TopicoNoticias>
        + <Registro id="1">
        + <Registro id="2">
        + <Registro id="3">
    </TopicoNoticias>
    - <UltimasForum>
        + <Registro id="1">
        + <Registro id="2">
        + <Registro id="3">
    </UltimasForum>
</MeuSite>

Já para o Flash, esta mesma estrutura seria exibida assim:

MeuXML
- [0] {nodeName:MeuSite,[0]{nodeValue:exibe o texto dentro do nó}}
    - [0] {nodeName:TopicoNoticias,[0]{nodeValue:exibe o texto dentro do nó}}
        + [0] {nodeName:Registro,attributes{id},[0]{nodeValue:exibe o texto dentro do nó}}
        + [1] {nodeName:Registro,attributes{id},[0]{nodeValue:exibe o texto dentro do nó}}
        + [2] {nodeName:Registro,attributes{id},[0]{nodeValue:exibe o texto dentro do nó}}
    - [1] {nodeName:UltimasForum,[0]{nodeValue:exibe o texto dentro do nó}}
        + [0] {nodeName:Registro,attributes{id},[0]{nodeValue:exibe o texto dentro do nó}}
        + [1] {nodeName:Registro,attributes{id},[0]{nodeValue:exibe o texto dentro do nó}}
        + [2] {nodeName:Registro,attributes{id},[0]{nodeValue:exibe o texto dentro do nó}}

Em outras palavras, para o objeto XML no Flash cada nó é um Array que pode ser acessado pelo método childNodes e dentro destes Array há mais Array que continuam sendo acessadas pelo método childNodes e objetos dentro de objetos que podem ser acessados por propriedades predefinidos como nodeValue e nodName, entre outros.

É importante que, quando fizerem algum tipo listagem de dados em XML, não mudemos a ordem em que os nós estão colocados. Exemplo:

- <Registro id="1">
    <Titulo>Recebendo dados no Flash</Titulo>
    <Descricao>Como receber dados externos no Flash usando LoadVars...</Descricao>
    <Link>http://www.imasters.com.br/artigo/4351/flash/recebendo_dados_no_flash/</Link>
    <Fonte><![CDATA[IMasters > http://www.imasters.com.br ]]></Fonte>
</Registro>

- <Registro id="2">
    <Descricao>Como receber dados externos no Flash usando LoadVars...</Descricao>
    <Titulo>Recebendo dados no Flash</Titulo>
    <Fonte><![CDATA[IMasters > http://www.imasters.com.br ]]></Fonte>
    <Link>http://www.imasters.com.br/artigo/4351/flash/recebendo_dados_no_flash/</Link>
</Registro>

Uma estrutura assim, quando recebida pelo Flash: no primeiro nó, Descricao está no índice 1 (lembrando que os nós são interpretados como Array e começam pelo índice 0) e, no segundo nó, ele está no índice 2, o que tornaria mais trabalhoso manipular os dados, uma vez que não podemos acessá-los diretamente pelos nomes.

Uma consulta pelo nome até poderia ser feita, mas seria necessário um tratamento trabalhoso que, principalmente no caso de quem está começando, seria melhor evitar. Porém, isso pode não ser mais um problema; pelo que já temos na versão alpha do ActionScript 3, será possível acessar os nós diretamente pelos seus nomes.

Finalmente, vamos montar um script para que possamos listar todos os dados, mas aqui vamos listá-los na janela de saída.

System.useCodepage = true;
var MeuXML:XML = new XML();
// Ignoramos todas as quebras de linhas e espaços entre os nós para não atrapalhar na interpretação do XML.
MeuXML.ignoreWhite = true;
// Este método será carregado ao fim do carregamento dos dados ou em caso de erro.
MeuXML.onLoad = function($sucesso){
// Declarando as variáveis dentro de uma função, elas só existirão dentro da função, sem influenciar externamente. O uso do $ é uma preferência minha, para identificar variáveis que são feitas só para as funções.
var $i, $x, $y, $nome, $valor;
if($sucesso){
// Já sabemos qual é o primeiro elemento; vamos, então, listar a partir do segundo.
trace("- " + MeuXML.firstChild.nodeName) // Meusite
// Enquanto $i for menor que o total de nós dentro do primeiro nó, vamos continuar este loop.
for($i=0; $i<MeuXML.firstChild.childNodes.length; $i++){
// MeuXML.firstChild.childNodes[$i] representa um dos nós de MeuSite.
trace("  - " + MeuXML.firstChild.childNodes[$i].nodeName);
// Agora mais um loop for dentro deste nó que foi encontrado, isso é necessário para podermos listar os nós dentro dele.
for($x=0; $x<MeuXML.firstChild.childNodes[$i].childNodes.length; $x++){
// Vamos, ver então, que nó estamos acessando agora. No caso do nosso XML estaremos acessando um dos nós que definimos como Registro.
trace("    - " + MeuXML.firstChild.childNodes[$i].childNodes[$x].nodeName);
// Está ficando cansado de loops? Calma, este será o último. Acessamos agora todos os nós dentro do nó Registro, lembre-se para cada grupo temos três nós de Registro.
for($y=0; $y<MeuXML.firstChild.childNodes[$i].childNodes[$x].childNodes.length; $y++){
// Finalmente, vamos exibir o nome destes últimos nós, porém vamos exibir seu valor também.
$nome = MeuXML.firstChild.childNodes[$i].childNodes[$x].childNodes[$y].nodeName;
// Para pegar o valor, apesar de não haver um nó dentro deles, apenas textos, temos que acessá-lo como se houvesse um nó, então podemos até usar o firstChild.
$valor = MeuXML.firstChild.childNodes[$i].childNodes[$x].childNodes[$y].firstChild.nodeValue;
trace("      - " + $nome + ": " + $valor);
// Terminado aqui, vamos para o próximo valor.
}
// Terminado aqui, vamos para o próximo Registro.
}
// Terminado aqui, vamos para o próximo nó dentro do nó MeuSite.
}
}else{
trace($sucesso);
trace("Ocorreu algum erro ao carregar os dados.");
}
}
// Carregar dados do XML.
MeuXML.load("dados.xml");

Então, aqui temos loop, dentro de loop, dentro de loop, mas infelizmente é necessário para que possamos acessar os dados do XML, que é o ponto comentado no início deste artigo: é preciso acessar nível após nível nos nós do XML para que possamos chegar ao nosso objetivo final, por ter de usar uma longa linha para este acesso.

Lembrem-se, o uso do XML é por uma questão de padronização e organização das informações, pois o uso do LoadVars pode ser simples porém, é mais complicado para ser interpretado por teceiros e depois de um certo tempo, fica complicado até mesmo para aqueles que criaram a estruturas de dados.

Clique aqui para baixar todos os arquivos deste artigo.

Até a próxima.

10 comentários

 Fernando Pires
17/10/2006 13h51

Muito Boa

essas informaçõe são muito úteis... principalmente pra mim .. que um dia desses precisei exatamente disso, e foi díficil encotrar informãções sobre XML - Flash... muito fácil de entender .. flw

 Geraldo Gomes
20/10/2006 16h45

Ótima matéria

Finalmente eu ENTENDI como navegar por um XML.

E acabo concluindo que o firstChild não serve pra nada já que existe childNodes[0] hehehe

 Saulo Gomes
14/12/2006 11h14

Exelente matéria

Parabéns, esta otima a matéria e otima explicações.

 guilherme karan barbosa
20/02/2007 11h55

Excelente

Cra muito boa materia, so que tenho dificuldades para fazer o seguinte, preciso carregar asinformaçoes de um banco de dados ja fui no forum e consegui quase oq eu qria, estou gerando um xml atraves de um php q faz a consulta no banco e gera um xml soh q estou tendo dificuldades para carregar essas informaçoes no flash no caso sao fotos,por exempli foto1,foto2, foto3... para carrega-lás dentro do flahs precisaria criar um movieclip? pois soh o ac nao carrega nada agora talves eue steje errado se tiveralgum tutorial ai explicando como fazer para buscar imagens do mysql por favor cara passa ae para mim grande abraço a e essa materia eh muito boa

 Helen Fernanda Alves Martins
16/04/2007 10h52

Não entendi!

Não entendi onde devo colocar cada código e os arquivos ".fla" zipados não abriram na minha máquina, mesmo depois que descompactei. :(

 Paullo Norato
07/04/2009 15h51

Muuito bom!

adorei esta ajuda, porem gostaria de saber como faço para o XML aparecer em uma DYNAMIC TEXT, ao inves de TRACE!
agradeço se puder ajudar.

 Max Oliveira
11/04/2009 17h35

Paullo

Para aparecer no dynamic text faz assim:
campo_texto.text = $nome + ": " + $valor;

 Plinio de Andrade
03/07/2009 16h28

Não consegui usar isso

Boa tarde. Não consegui fazer funcionar. Eu baixe o pacote todo, descompactei, mas qualquer flash que abro só aparece uma tela em branco. Mesmo jogando no servidor. Como faço para funcionar pelo menos o exemplo? obrigado

 Renato Pacheco
04/07/2009 14h36

Isso por que não há nada nos arquivos, só scripts pois todos os resultados são exibidos na janela de Output.

Att

 Triplo Xxx
30/10/2009 17h02

Botões hover no flash

Excelente!
Mas como faço para os botões ficarem em modo hover durante a transição, tanto clicando com o mouse ou deixando rodar sozinho?

Obrigado.

Cancelar resposta

Qual a sua opinião?

Faça login abaixo ou cadastre-se rapidamente.


Patrocínio:
Sobre o Autor
Renato Pacheco é programador e desenvolve projetos se utilizando de banco de dados, PHP, Asp, XML e, principalmente, trabalhando com Flash tanto para multimídia quanto web.

2001 - iMasters FFPA Informática Ltda - Todos os direitos reservados.