XmlProcessor o el procesamiento recursivo de XML

Estos días debido a una conversación por mail con Bill Drol surgió, de manera colateral al tema que tratabamos, un ejemplo con una clase suya para procesar documentos XML. Está solución es una evolución de la versión que aparecia en su libro Object Oriented Macromedia Flash MX pero para Flash MX 2004.

El caso es que esta solución ya la conocía de otras charlas con Bill de cuando apareció el nuevo Flash MX 2004 y ya en su momento me pareció un método muy sencillo y organizado para tratar con XML. Por eso en varias ocasiones se me ocurrio pedirle su publicación en este blog(en caso de que el no lo hiciese en su web). Ahora y debido a esta última conversación, me animé a pedirle permiso para hacerlo. Bill además de ser un genio, es una fantástica persona y no solo me ha dado el permiso sino que además me ha animado ha hacerlo. Gracias Bill :).

La solución se basa en un procesamiento recursivo del documento XML mediante la clase XMLProcessor. Esta extiende de XML y se apoya en el manejador de eventos de Flash MX 2004 mx.events.EventDispatcher. Esta clase despacha el evento xmlProcessorReady cuando el XML está cargado. El resto de eventos utilizados dependen del documento procesado y serán siempre una cadena del tipo “node<nombre del nodo actual>”. Seguidamente la clase XmlProcessor:

// AUTHOR    Bill Drol (http://www.billdrol.com)
// FILE      XmlProcessor.as
// VERSION   1.0 (compatible with Flash MX 2004)
// MODIFIED  30 May 2004
// SUMMARY   Recurses an XML document and dispatches events for external processing

import mx.events.EventDispatcher;

class com.billdrol.xml.XmlProcessor extends XML {
        //----- Declare mix-in functions for EventDispatcher
        public var initialize:Function;
        public var dispatchEvent:Function;
        public var addEventListener:Function;
        
        public function XmlProcessor() {
                ignoreWhite = true;
                EventDispatcher.initialize(this);
        }
        
        public function begin() : Void {
                recurse(this);
        }
        
        private function onLoad(success:Boolean) : Void {
                if(success)
                dispatchEvent({type:"xmlProcessorReady"});
        }
        
        private function recurse(node:XMLNode) : Void {
                for(var i:Number = 0; i < node.childNodes.length; i++) {
                        //---- Dispatch event for current node
                        var currentNode:XMLNode = node.childNodes[i];
                        dispatchEvent({type:"node" + currentNode.nodeName, node:currentNode});
                        
                        //----- Process child nodes
                        if(currentNode.childNodes.length > 0)
                        recurse(currentNode);
                }
        }
}

Seguidamente la clase de ejemplo, Test. En ella tenemos que definir los métodos que responderán a los eventos. Siempre habrá un método xmlProcessorReady más las métodos corresponedientes según los nodos de nuestro XML que queramos procesar. En nuestro caso nodeExample1, nodeExample2 y nodeExample3. También observad como se añade esta clase como escuchadora de dichos eventos.

// AUTHOR    Bill Drol (http://www.billdrol.com)
// FILE      Test.as
// VERSION   1.0 (compatible with Flash MX 2004)
// MODIFIED  30 May 2004
// SUMMARY   A test class to demonstrate the XML processor

import com.billdrol.xml.XmlProcessor;
import mx.events.EventDispatcher;

class com.billdrol.Test {
        private var processor:XmlProcessor;
        
        public function Test(XMLDocumentName:String) {
                //----- Load XML document into the processor
                processor = new XmlProcessor();
                processor.addEventListener("xmlProcessorReady", this);
                processor.load(XMLDocumentName);
        }
        
        public function xmlProcessorReady() : Void {
                //----- XML data is available now
                processor.addEventListener("nodeExample1", this);
                processor.addEventListener("nodeExample2", this);
                processor.addEventListener("nodeExample3", this);
                processor.begin();
        }
        
        public function nodeExample1(eventObj:Object) : Void {
                //----- The name of this node in the XML document is Example1.
                //----- eventObj.node is used to access the XMLNode object
                //----- so if you wanted to get the value of an attribute
                //----- named MyAttribute inside this node, you would use
                //----- the following:
                
                var attributeValue = eventObj.node.attributes["MyAttribute"];
                trace(eventObj.node.nodeName + " > " + attributeValue);
                
                //----- If the XML is 
                 output would be 'attribute from example1'
        }
        
        public function nodeExample2(eventObj:Object) : Void {
                //----- The name of this node in the XML document is Example2.
                var attributeValue = eventObj.node.attributes["MyAttribute"];
                trace(attributeValue);
        }
        
        public function nodeExample3(eventObj:Object) : Void {
                //----- The name of this node in the XML document is Example3.
                var attributeValue = eventObj.node.attributes["MyAttribute"];
                trace(attributeValue);
        }
}

Para probar este ejemplo debeis crearos un sencillo XML de prueba llamado xmldoc.xml con nodos Example1, Example2 y Example3. Y poner las siguientes dos lineas en el primer fotograma de un documento Flash MX 2004 como era de esperar:

import com.billdrol.Test;
myTest = new Test("xmldoc.xml");

Además esta versión al ser para Flash MX 2004 os asegura de que no vais a tener el problema que se daba en versiones anteriores del player (6 y anteriores), donde si vuestro documento XML era demasiado largo (a partir de 150 o 200kb), aparecía el molesto Alert aquel que decía “A script in this movie is causing Flash Player to run slowly […]”. Este problema ya está arreglado en el Flash Player 7. Aquel mensaje podría hacernos pensar que nuestro código es incorrecto, pero no hay nada de malo en usar recursión. Hoy día dicho Alert esta obsoleto en ciertas ocasiones como la tratada aquí y es bueno que Macromedia lo haya retocado para hacer nuestro player más funcional. Con esta clase podeis procesar documentos muy largos y la clase responderá…eso si cuanto más largo sea el documento más tardará.

Nuevamente quiero darle las gracias a Bill Drol por esta fantástica clase que amplia las posibilidades en que podemos tratar con nuestros documentos XML. Espero que os sea de utilidad.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *