No artigo anterior, vimos as vantagens em usarmos um documento XML para transferir dados pra o Flash, e fizemos um simples exemplo para entender a relação entre eles.
Agora, conheceremos mais dois "itens" de um documento XML: os atributos e as seções CDATA. Cada elemento pode ter uma ou mais propriedades, chamadas de atributos. Os atributos podem ser usados para descrever um elemento ou para adicionar informações a ele. Cada atributo tem um nome único e um valor de zero ou mais caracteres.
-
<?xml version="1.0" encoding="utf-8"?>
-
<root>
-
<elemento atributo="valor do atributo">
-
<!-- Todo elemento tem que ter uma tag de abertura e fechamento. No caso de elementos vazios, deve-se colocar uma barra (/) de fechamento da tag. É o mesmo que ocorre com a tag <br /> no HTML. -->
-
<subelemento atributo="valor" />
-
</elemento>
-
</root>
Em alguns casos, necessitamos inserir tags HTML em um texto de um elemento, mas não daria certo, uma vez que o parser interpretaria as tags HTML como sendo tags XML, causando erros ou resultados indesejados. A solução para isso é usar seções CDATA.
Seções CDATA iniciam com uma cadeia de caracteres <![CDATA[ e terminam com uma cadeia de caracteres ]]>. Toda e qualquer tag que for colocada em uma seção CDATA será interpretada como texto, e não como tag.
-
<?xml version="1.0" encoding="utf-8"?>
-
<root>
-
<elemento atributo="valor do atributo">
-
<subelemento atributo="valor">
-
<![CDATA[Aqui vem o nosso texto que pode conter <b>tags</b> HTML, sem problemas.]]>
-
</subelemento>
-
</elemento>
-
</root>
Vamos fazer um pequeno tour pelos métodos, eventos e propriedades da classe XML e XMLNode, e ver qual a finalidade de cada um deles:
- Método getBytesLoaded:Number - Retorna o número de bytes carregados do arquivo XML.
- Método getBytesTotal:Number - Retorna o número total de bytes do arquivo XML.
- Propriedade ignoreWhite:Boolean - Os text nodes que contenham apenas espaços em branco são descartados se definido como true. O padrão é false. Comentamos sobre essa propriedade no artigo anterior.
- Método load:Boolean - Carrega um documento XML da URL especificada no parâmetro.
- Propriedade loaded:Boolean - Propriedade que indica se o documento XML foi carregado.
- Evento onData(String) - Invocado quando o documento XML foi completamente carregado, ou quando um erro ocorre. Este evento é invocado antes do XML ser parseado pelo Flash. Você pode usar esse evento caso deseje usar uma rotina de parser customizada.
- Evento onLoad(Boolean) - Invocado quando o documento XML foi completamente carregado, fornece um parâmetro com valor Booleano que indica se o documento foi ou não carregado.
- Propriedade status:Number - Automaticamente define ou retorna um valor numérico, que indica quando o documento XML foi parseado com sucesso no objeto XML. Você pode conferir os valores que esta propriedade pode conter no Help do Flash.
- Propriedade attributes:Object - Um objeto contendo todos os atributos da instância XML especificada. Contém uma variável para cada atributo.
- Propriedade childNodes:Array - Uma propriedade contendo os nós filhos do objeto XMLNode.
- Propriedade firstChild:XMLNode - Uma propriedade contendo uma referência ao primeiro nó filho do objeto XMLNode.
- Método hasChildNodes:Boolean - Especifica se o objeto XMLNode contém filhos ou não.
- Propriedade lastChild:XMLNode - Uma propriedade contendo uma referência ao último nó filho do objeto XMLNode.
- Propriedade nextSibling:XMLNode - Faz referência ao próximo nó XML. Se não existir nenhum próximo nó, o valor é null.
- Propriedade nodeName:String - Nome do nó do objeto XMLNode. Se o objeto for um elemento XML (nodeType == 1), nodeName será o nome da tag que representa o nó. Se o objeto for um text node (nodeType == 3), o valor de nodeName é null.
- Propriedade nodeType:Number - Valor numérico com o tipo do nó, 1 para um elemento XML e 3 para um text node. Existem outros valores, mas o Flash Player suporta apenas esses dois. Essa numeração é feita de acordo com as recomendações do W3C (http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html).
- Propriedade nodeValue:String - Valor do nó do objeto XMLNode. Se o objeto é um text node (nodeType == 3) o valor é o texto do nó. Se o objeto for um elemento (nodeType == 1) o valor é null e somente leitura.
- Propriedade parentNode:XMLNode - Uma referência ao nó pai do objeto XMLNode. Se não existir um nó pai, retorna null.
- Propriedade previousSibling:XMLNode - Faz referência ao nó XML anterior. Se não existir nenhum nó anterior, o valor é null.
Não falei de tudo nem de todos, mas mostrei os principais. Falaremos dos restantes mais tarde, em outra ocasião (parte 3). Para os que não entenderam lendo apenas, vou mostrar alguns exemplos básicos, focando certos métodos e propriedades, e depois embarcamos para um exemplo um pouco maior
Começando por nodeType, nodeValue. Como vimos, o Flash tem 2 tipos de nó, elemento e texto. Digamos que você tenha o seguinte documento XML:
-
<elementNode>textNode</elementNode>
Um XML bem simples, temos 1 tag (nó, elemento, XMLNode) com um valor (text node). Agora vamos ao Flash:
-
// Objeto XML
-
var oXML:XML = new XML();
-
// Evento onLoad
-
oXML.onLoad = function(){
-
// Objeto XMLNode. Primeiro nó do documento XML.
-
var elementNode:XMLNode = this.firstChild;
-
// Mostra na janela de saída o nodeValue de elementNode.
-
trace(elementNode.nodeValue); // null
-
/* O conteúdo de elementNode é um elemento independente, por isso
-
a necessidade do firstChild, ou seja, o primeiro nó de elementNode
-
é o seu conteúdo. Se fizermos isso, obteremos o valor do nó. Na verdade o que vemos
-
é um objeto com um método toString(), o que faz com que o valor correto
-
seja exibido, mas o gasto de memória é maior. */
-
trace(elementNode.firstChild); // textNode
-
// Mostrando o nodeType
-
trace(elementNode.nodeType); // 1 == ELEMENT_NODE
-
/* Objeto XMLNode. O conteúdo de elementNode é um elemento independente,
-
por isso podemos criar um objeto de referência a ele.*/
-
var textNode:XMLNode = elementNode.firstChild;
-
// Agora sim, mostra o valor do nó, sem gastos de memória desnecessários.
-
trace(textNode.nodeValue); // textNode
-
// Aqui acontece o mesmo que o elementNode.firstChild
-
trace(textNode); // textNode
-
// Mostrando o nodeType
-
trace(textNode.nodeType); // 3 == TEXT_NODE
-
}
-
oXML.load("arquivo.xml");
Agora, vamos dar uma olhadinha no nextSibling e previousSibling. Usaremos o seguinte XML e AS:
-
<rootNode>
-
<primeiroNo>Primeiro</primeiroNo>
-
<segundoNo>Segundo</segundoNo>
-
<terceiroNo>Terceiro</terceiroNo>
-
<quartoNo>Quarto</quartoNo>
-
<quintoNo>Quinto</quintoNo>
-
<sextoNo>Sexto</sextoNo>
-
</rootNode>
-
// Objeto XML
-
var oXML:XML = new XML();
-
// Ignorando espaços em branco
-
oXML.ignoreWhite = true;
-
// Evento onLoad
-
oXML.onLoad = function(){
-
// Referência ao primeiro nó do documento.
-
var root:XMLNode = this.firstChild;
-
// Loop para cada elemento dentro de root.
-
for(var i = 0; i < root.childNodes.length; i++){
-
// Nó Filho de root.
-
var child:XMLNode = root.childNodes[i];
-
// Mostra o valor de child na janela de saída.
-
trace("Nó Atual: " + child);
-
// Mostra o valor de child na janela de saída.
-
trace("Valor do Nó Atual: " + child.firstChild.nodeValue);
-
// Próximo Nó
-
trace("Próximo nó: " + child.nextSibling);
-
// Nó Anterior
-
trace("Nó Anterior: " + child.previousSibling);
-
//
-
trace("----------------------\n");
-
}
-
}
-
oXML.load("arquivo.xml");
Agora que você entendeu o ABC do XML, vamos para um exemplo simples, mas que ajuda a praticar bastante. Vamos criar um pequeno sistema de notícias usando os componentes List e TextArea. Coloque um componente list no palco e dê instância de noticias_lst a ele, em seguida coloque um componente TextArea e dê instância de noticia_txt
Vamos criar a seguinte estrutura:
Passando isso pro XML:
-
<?xml version="1.0" encoding="utf-8"?>
-
<noticias>
-
<noticia>
-
<titulo>Quinta e Última Notícia</titulo>
-
<texto><![CDATA[Um texto de exemplo <i>aqui</i>. Esta é a <a href="#">notícia de número</a> <b>5</b>]]></texto>
-
<autor>Mozart Petter</autor>
-
<data>15/10/2005</data>
-
</noticia>
-
<noticia>
-
<titulo>Quarta Notícia</titulo>
-
<texto><![CDATA[Um texto de exemplo <i>aqui</i>. Esta é a <a href="#">notícia de número</a> <b>4</b>]]></texto>
-
<autor>Mozart Petter</autor>
-
<data>14/10/2005</data>
-
</noticia>
-
<noticia>
-
<titulo>Terceira Notícia</titulo>
-
<texto><![CDATA[Um texto de exemplo <i>aqui</i>. Esta é a <a href="#">notícia de número</a> <b>3</b>]]></texto>
-
<autor>Lucas Ferreira</autor>
-
<data>13/10/2005</data>
-
</noticia>
-
<noticia>
-
<titulo>Segunda Notícia</titulo>
-
<texto><![CDATA[Um texto de exemplo <i>aqui</i>. Esta é a <a href="#">notícia de número</a> <b>2</b>]]></texto>
-
<autor>Diogo Pitz</autor>
-
<data>12/10/2005</data>
-
</noticia>
-
<noticia>
-
<titulo>Primeira Notícia</titulo>
-
<texto>
-
<![CDATA[Um texto de exemplo <i>aqui</i>. Esta é a <a href="#">notícia de número</a> <b>1</b>]]>
-
</texto>
-
<autor>Mozart Petter</autor>
-
<data>11/10/2005</data>
-
</noticia>
-
</noticias>
A primeira coisa que você deve pensar é em como o aplicativo vai funcionar. Listaremos as notícias no componente List (noticias_lst) mostrando seus títulos. Ao clicar em um título a notícia é mostrada no componente TextArea (noticia_txt), exibindo título, texto, data e autor.
No Flash, temos que carregar o XML, popular o componente List, fazer com que quando um item seja clicado o conteúdo referente a ele seja exibido no TextArea e pronto. Basicamente seria isso. Agora podemos começar a produzir:
-
// Objeto XML
-
var oXML:XML = new XML();
-
// Ignorando espaços em branco
-
oXML.ignoreWhite = true;
-
-
// Nossa função que listará os títulos no componente List
-
function listaTitulos():Void{
-
}
-
-
// Nossa função que irá mostrar a notícia no componente TextArea.
-
// Ela recebe um parâmetro id do tipo Number que será o identificador da notícia.
-
function mostraNoticia(id:Number){
-
}
-
-
// Evento onLoad
-
oXML.onLoad = function(success:Boolean):Void{
-
}
-
// Carregando o documento XML
-
oXML.load("noticias.xml");
O esqueleto do nosso aplicativo está aí. Criamos um objeto XML, ignoramos os espaços em branco, criamos a função listaTitulos e a função mostraNoticia. Elas ainda não fazem nada, mas é interessante criá-las antes para visualizar como o aplicativo irá funcionar. Depois temos o evento onLoad e o método load que carrega nosso documento XML. Próximo passo é definir o que vai acontecer quando o XML for carregado: listar as notícias:
-
// Nossa função que listará os títulos no componente List
-
function listaTitulos():Void{
-
// Nós de <noticias>
-
var childs:XMLNode = oXML.firstChild;
-
// Número total de nós
-
var childTotal:Number = childs.childNodes.length;
-
// Para cada nó em childs
-
for(var i = 0; i < childTotal; i++){
-
// Nó <noticia>
-
var nodeNoticia:XMLNode = childs.childNodes[i];
-
// Título
-
var nodeTitulo:XMLNode = nodeNoticia.childNodes[0];
-
// Valor do título
-
var titulo:String = nodeTitulo.firstChild.nodeValue;
-
// Adicionando item ao componente List. i será o id desta notícia.
-
noticias_lst.addItem({label:titulo, data:i});
-
}
-
// Selecionando o primeiro index, no caso, a última notícia
-
noticias_lst.selectedIndex = 0;
-
// Mostrando a última notícia
-
mostraNoticia(0);
-
}
-
-
// Evento onLoad
-
oXML.onLoad = function(success:Boolean):Void{
-
// Se carregar com sucesso
-
if(success){
-
// Se o status do XML for 0, ou seja, nenhum problema.
-
if(oXML.status == 0){
-
// Lista os títulos no componente List
-
listaTitulos();
-
}
-
// Fique à vontade para criar avisos no caso de erros.
-
}
-
}
Agora já temos a lista das notícias. Elas ainda não são mostradas no componente TextArea, e é essa a próxima parte.
-
// Nossa função que irá mostrar a notícia no componente TextArea.
-
// Ela recebe um parâmetro id do tipo Number que será o identificador da notícia.
-
function mostraNoticia(id:Number):Void{
-
// Nó Notícia referende ao id fornecido
-
var nodeNoticia:XMLNode = oXML.firstChild.childNodes[id];
-
// Título da notícia - noticia.titulo.conteudo.texto
-
var titulo:String = nodeNoticia.childNodes[0].firstChild.nodeValue;
-
// Texto da noticia - noticia.texto.conteudo(CDATA).texto
-
var texto:String = nodeNoticia.childNodes[1].firstChild.nodeValue;
-
// Autor da noticia
-
var autor:String = nodeNoticia.childNodes[2].firstChild.nodeValue;
-
// Data da noticia
-
var data:String = nodeNoticia.childNodes[3].firstChild.nodeValue;
-
// Mostrando os valores no componente TextArea
-
noticia_txt.text = "<font size='16'><b>" + titulo + "</b></font>";
-
noticia_txt.text += "<br />" + texto;
-
noticia_txt.text += "-------------------------------------------------------------------------------------";
-
noticia_txt.text += "<font size='10'>Publicado por " + autor + " em " + data + "</font>";
-
}
Pronto, agora a última notícia é mostrada quando o aplicativo é iniciado. Mas, falta ela mudar ao selecionar outro título no componente List. Para isso criaremos um EventListener change para o componente List:
-
// Objeto que será o listener do componente List
-
var evtList:Object = new Object();
-
/* Evento change. Toda vez que mudarmos o valor do componente, este evento é invocado.
-
Ele fornece um objeto que é uma referência ao evento, e contém o target e o type do evento,
-
no caso target vai ser o componente list e type será change. */
-
evtList.change = function(evt:Object):Void{
-
// Mostra a notícia selecionada
-
/* target.value contém o valor de data do item selecionado,
-
ou seja, o ID da notícia. */
-
mostraNoticia(evt.target.value);
-
}
-
// Adiciona o EventListener ao componente List
-
noticias_lst.addEventListener("change", evtList);
O resultado completo da aplicação:
-
// Objeto XML
-
var oXML:XML = new XML();
-
// Ignorando espaços em branco
-
oXML.ignoreWhite = true;
-
-
// Nossa função que listará os títulos no componente List
-
function listaTitulos():Void{
-
// Nós de <noticias>
-
var childs:XMLNode = oXML.firstChild;
-
// Número total de nós
-
var childTotal:Number = childs.childNodes.length;
-
// Para cada nó em childs
-
for(var i = 0; i < childTotal; i++){
-
// Nó <noticia>
-
var nodeNoticia:XMLNode = childs.childNodes[i];
-
// Título
-
var nodeTitulo:XMLNode = nodeNoticia.childNodes[0];
-
// Valor do título
-
var titulo:String = nodeTitulo.firstChild.nodeValue;
-
// Adicionando item ao componente List. i será o id desta notícia.
-
noticias_lst.addItem({label:titulo, data:i});
-
}
-
// Selecionando o primeiro index, no caso, a última notícia
-
noticias_lst.selectedIndex = 0;
-
// Mostrando a última notícia
-
mostraNoticia(0);
-
}
-
-
// Nossa função que irá mostrar a notícia no componente TextArea.
-
// Ela recebe um parâmetro id do tipo Number que será o identificador da notícia.
-
function mostraNoticia(id:Number):Void{
-
// Nó Notícia referende ao id fornecido
-
var nodeNoticia:XMLNode = oXML.firstChild.childNodes[id];
-
// Título da notícia - noticia.titulo.conteudo.texto
-
var titulo:String = nodeNoticia.childNodes[0].firstChild.nodeValue;
-
// Texto da noticia - noticia.texto.conteudo(CDATA).texto
-
var texto:String = nodeNoticia.childNodes[1].firstChild.nodeValue;
-
// Autor da noticia
-
var autor:String = nodeNoticia.childNodes[2].firstChild.nodeValue;
-
// Data da noticia
-
var data:String = nodeNoticia.childNodes[3].firstChild.nodeValue;
-
// Mostrando os valores no componente TextArea
-
noticia_txt.text = "<font size='16'><b>" + titulo + "</b></font>";
-
noticia_txt.text += "<br />" + texto;
-
noticia_txt.text += "-------------------------------------------------------------------------------------";
-
noticia_txt.text += "<font size='10'>Publicado por " + autor + " em " + data + "</font>";
-
}
-
-
// Objeto que será o listener do componente List
-
var evtList:Object = new Object();
-
/* Evento change. Toda vez que mudarmos o valor do componente, este evento é invocado.
-
Ele fornece um objeto que é uma referência ao evento, e contém o target e o type do evento,
-
no caso target vai ser o componente list e type será change. */
-
evtList.change = function(evt:Object):Void{
-
// Mostra a notícia selecionada
-
/* target.value contém o valor de data do item selecionado,
-
ou seja, o ID da notícia. */
-
mostraNoticia(evt.target.value);
-
}
-
// Adiciona o EventListener ao componente List
-
noticias_lst.addEventListener("change", evtList);
-
-
// Evento onLoad
-
oXML.onLoad = function(success:Boolean):Void{
-
// Se carregar com sucesso
-
if(success){
-
// Se o status do XML for 0, ou seja, nenhum problema.
-
if(oXML.status == 0){
-
// Lista os títulos no componente List
-
listaTitulos();
-
}
-
// Fique � vontade para criar avisos no caso de erros.
-
}
-
}
-
// Carregando o documento XML
-
oXML.load("noticias.xml");
Criamos um simples sistema de notícias que envolve alguns métodos e propriedades básicos da classe XML, mas que são bastante utilizados. Faça testes com esse exemplo, tente adicionar novas funcionalidades a ele.
Na próxima parte, veremos mais métodos e propriedades da classe. Vamos criar um modo de adicionar notícias ao nosso sistema, criando o XML no próprio Flash e gravando ele através do PHP.
Abraço
Comentários
enviar arquvo txt para o componente TextArea
Primeiramente parabéns pelo artigo. Foi um achado na net!
Segundamente preciso saber como enviar um arquivo de texto txt (ou qualquer outra extensão) para o componente TextArea, o invés de um texto definido no propio XML.
Agradeço de antemão pela força e conto com mais esta forcinha! rs
Raphael
Dúvidas em Interagindo Flash com XML
Estou com várias dúvidas em relação ao ActionScript 3.0, pois sou designer e não programador.
Acabei de ver que o artigo é de 2005. Como atualizá-lo para o ActionScript 3.0?
Vlw abs!