E4X:El nuevo enfoque XML para AS3.0

La nueva especificación de Ecmascript introduce por primera vez herramientas para trabajar de forma nativa y standard con datos XML. Este conjunto de herramientas o core clases se conoce como E4X o EcmaScript for XML.

Por su naturaleza, el formato XML se ha convertido en un standard, tanto para la definición, como para el intercambio de datos: RSS, Web services, Base de datos, ficheros de configuración, etc

Como desarrolladores RIA, es imperativo tener soltura y experiencia en el manejo de este tipo de datos y es objetivo de este tutorial el abordar, de la forma más práctica posible, su uso dentro de Actionscript 3.0 y Flex 2.0.

También quiero resaltar que este tutorial está centrado en este nuevo enfoque que ofrece E4X para XML y no en soluciones anteriores para trabajar con este tipo de datos.

Definir datos XML

Hay diferentes formas de definir objetos XML en AS 3.0:

  1. Definición directa
  2. Generación mediante constructores: appendchild, suma de listas, a partir
    de Strings, etc
  3. Carga desde un fichero externo
  4. Los datos vienen de un servicio remoto: web service, remote object, http service, etc

El objetivo de este tutorial no es el de estudiar las diferentes formas de definir estos objetos sino ver cómo se trabajan los datos XML con E4X; así que optaremos por una definición directa de un ejemplo sencillo sobre el que trabajaremos a lo largo del tutorial.

Utilizamos la clase XML para definir un objeto XML a partir de un XML literal:

[ftf w=”400″ h=”300″]private var myXml: XML =
Pedro
Decora tu casa 62
Carlos
Cocina para todos 39.90
[/ftf]

Que sería lo mismo que cargar esos mismos datos desde un fichero XML externo:

[ftf w=”400″ h=”60″][/ftf]

Acceder a los datos XML

Utilizaremos los operadores de las clases XML y XMLList para acceder a los elementos del objeto XML:

El operador “.” se refiere a hijos directos y el operador “..” a descendientes a cualquier profundidad y ambos siempre retornan un objeto XMLList.

myXml..libros nos devolverá:

[ftf w=”400″ h=”210″]// XMLList Pedro
Decora tu casa 62
Carlos
Cocina para todos 39.90
[/ftf]

Extendiendo un poco más la consulta, podemos utilizar el símbolo “@” para acceder a los atributos de los elementos y utilizar expresiones condicionales entre paréntesis:

myXml..libro.( @id_producto < 106 ) devuelve: [ftf w="400" h="130"]// XMLList Pedro
Decora tu casa 62
[/ftf]

Notad que el Flash Player mostraría un error si alguno de los libros no tuviera definido alguno de los atributos que utilizamos en comparaciones como, en este caso, “id_producto”. Para esquivar esto, debemos asegurarnos antes que el atributo existe (con libro.attribute( “id_producto”) != undefined en cualquier bucle que recorra la estructura).

Rizando el rizo podemos hasta utilizar expresiones regulares para seleccionar ciertos elementos del objeto XML:

Eg: Cuánto me costarían todos los libros que traten de cocina cuyo precio sea menor de 40?

[ftf w=”400″ h=”200″]// Definimos una expresión regular para realizar la búsqueda de la palabra “cocina”
var palabracocina: RegExp = new RegExp( “cocina”, “gi” );

// Seleccionamos los libros que verifiquen esa expresión regular y además valgan menos de 40
var librosCocina: XMLList =
myXml..libro.( palabracocina.test( titulo.toString() ) && precio < 40 ); // Recorremos la XMLList evaluando cada nodo XML ( cada libro ) y acumulando el total en una variable local var total: Number = 0; for each ( var propiedad: XML in librosCocina ) { total += Number( propiedad.precio ); } // total = 39.9[/ftf]

Modificar datos XML

Además de consultar y recorrer el objeto XML también podemos alterarlo como queramos. Para insertar o eliminar un nodo de objeto XML primero hemos de localizar exactamente el punto de actuación, en este caso un nodo de referencia para insertar delante o detrás y un XML padre para este tipo de nodos dentro de nuestro XML global.

Por ejemplo, si queremos insertar un nodo libro después del libro con id_producto=106:

[ftf w=”400″ h=”200″]// Nodo de referencia para la inserción dentro de la lista de nodos que devuelve “..”
var nodoActuacion: XML = myXml..libro.( @id_producto == “106” )[0];

var nuevoLibro: XML = Alberto
Pintura avanzada 110.99

// XML donde están nuestros libros, en este caso el XML con root= var xmlActuacion: XML = myXml.productos.libros[0];

xmlActuacion.insertChildAfter( nodoActuacion, nuevoLibro );

// XML
Pedro
Decora tu casa 62
Carlos
Cocina para todos 39.90
Alberto
Pintura avanzada 110.99
[/ftf]

De igual forma existen métodos:

  • insertChildBefore (antes del nodo de referencia)
  • prependChild (al principio del bloque XML que especifiquemos)
  • appendChild (al final del XML que especifiquemos)

Vincular XML a componentes Flex

Como cualquier otro proveedor de datos (data provider), los objetos XML pueden ser vinculados a componentes visuales de Flex como DataGrid, List, Repeater, etc

Como ejemplo, vinculemos los libros de nuestro objeto XML a un Datagrid:

[ftf w=”400″ h=”60″][/ftf]

Conclusión

En este artículo hemos analizado las mejoras que la nueva especificación de Ecmascript ha incluido para el manejo de datos XML y que llevan como nombre E4X. Hemos repasado de forma práctica ejemplos para definir, modificar y utilizar estos datos dentro de ActionScript 3.0 y Flex 2.0. Lo interesante de este artículo es comprender el potencial que ofrece E4X y el uso de XML en cuanto a facilidad y rendimiento en comparación a recorrer, analizar o utilizar otro tipo de estructuras de datos con otro tipo de mecanismos.

Personalmente, trabajar con XML, E4X y Flex 2.0 me ha permitido, no sólo beneficiarme de todo eso a nivel abstracto ( o de datos ), sino a nivel visual, dándome la oportunidad de definir dinámicamente vistas, formularios, menús, etc. Espero poder tratar más en detalle estos temas en un futuro próximo.

Como apoyo a este tutorial, adjunto un fichero MXML donde se plasman la mayor parte de los ejemplos. Necesitaréis configurar el logger del flash player para ver la salida de los trace:

16 Comentarios

  1. Pingback: Freddy Gálvez++++++++++++ » Se viene Actionscript 3 y de la mano llega E4X, mi salvación parece

  2. demian

    hola. me interesa el flex. especialmente el hecho de poder acceder tan facil a un xml externo. ahora tengo una pregunta y me encantaria que armaran un tutorial de lo siguiente. actualmente puedo hacer un datagrid y colocarle datos de un xml externo y ademas poder hacer q una columna tenga archivos .jpg. ahora lo q me gustaria es q en ves de ser un datagridel q tenga los archivos .jpg sea un componente image, es facil de hacerlo? porque no se me ocurre como. muchas gracias

  3. demian

    barbaro este articulo… podrias expresar como hacer para unir un image al xml? mi intencion es q de un datagrid. lo seleccione y se vea en grande en un componente image. gracias

  4. Borja

    Hola Alberto, muy bueno el artículo. Estoy realizando un proyecto con Flex 2 y necesito borrar un nodo de un XML, lo tengo ubicado y ya sólo queda eliminarlo, he probado con “delete” pero creo que solo sirve para atributos y el name.
    ¿Tienes alguna idea de cómo podría hacerlo?
    Gracias y saludos

  5. Alberto Albericio

    Hola Borja,

    Lo estás haciendo bien. No sé cómo estarás identificando el nodo a borrar pero yo he probado esto:

    private var myXml: XML =
    < root >
    < productos >
    < producto id="1" >
    < name >foo< /name >
    < /producto >
    < producto id="2" >
    < name>bar< /name >
    < /producto >
    < /productos >

    Obs: Perdona por ponerte un espacio despues y antes de “< " y ">” pero es que sino, no te salía el código xml.

    var nodes: XMLList = myXml.productos.producto.( name == “foo” );

    delete nodes[0];

    trace( “myXml ” + myXml );

    Y puedes ver como el nodo correspondiente ha desaparecido.

    Espero que te sirva de ayuda y confírmame que te ha funcionado.

    Saludos,

    Alberto

  6. Borja

    Gracias!! la sentencia delete la estaba haciendo bien, lo que no hacia bien era recuperar el nodo.
    Estoy haciendo un explorador de archivos y quería recuperar cierto nodo con cierto padre, de forma que no confunda dos archivos en diferentes directorios con el mismo nombre.
    Pensé que haciendo lo siguiente funcionaria:
    xmlArbol..node.(@label==padre).(@label==hijo)
    pero parece ser que no le gusta, así que de momento lo he dejado con el hijo solo y funciona.
    Gracias!!

  7. Alberto Albericio

    Borja,

    Los operadores “.” y “..” devuelven siempre una XMLList. Lo correcto sería siempre, como te he hecho en el ejemplo, definir una lista con tus filtros y, luego, seleccionar el nodo que quieras de esa lista.

    En tu caso sería algo como ( fíjate en los operadores ):

    var selectedNodes: XMLList = xmlArbol..node.( @label == “padre” || @label == “hijo” );

    Y luego trabajar con esta “lista de selectedNodes” para borrar los que quieras:

    delete selectedNodes[ i ];
    // i entre 0 y selectedNodes.length()

    Saludos,

    Alberto

  8. Ricardo

    estoy creando una aplicacion en flash con xml, pero al insertar el codigo que muestras arriba para realizar la insercion de datos en el XML me manda un error de “unexpected ‘
    dosismg
    dosisdia
    present
    presentml
    comerc
    cantidad
    ;

    Si alguien podria ayudarme a ver por donde esta el error se los agradeceria.

  9. Kokumo

    Muy claro y conciso… muchísimas gracias :mrgreen:
    Estoy trabajando en una web y decidí hacer su estructura en xml, de modo tal que andaba necesitando un tutorial con las características semejantes al tuyo.

    Saludos y gracias!

  10. Alan

    Hola Alberto muy buen tutorial, espero veas este mensaje soy novato en esto de flex yo manejo flash cs3 pero no habia usado flex baje el codigo que pusiste en este foro correo a la perfeccion pero no se como hacer que se conserven los cambios una ves que cierras la aplicacion swf o el main html espero me puedas orientar ya que es muy interesente poder manejar xml de esta manera
    saludos

  11. Daniel L.

    Hola Alberto y gracias x el tut.
    Aprovecho para consultarte. Yo tengo un datagrid con datos numericos cargados y necesito q en otra columna sume una celda de esa fila mas otra de la celda superior.
    Tambien si tienes alguna idea si en AS3 se puede hacer un contar.Si o sumar.Si como en excel.
    Gracias y cualquiera que pueda ayudarme sera bienvenido.

    Daniel
    dalobo@nulladinet.com.uy

  12. José Carlos

    Hola a todos, he comprobado el ejemplo de la búsqueda de la cadena “cocina” pero salta un warning 3594 diciendo que el método “test” no es un método reconocido de la clase dinámica RegExp. ¿Alguien tiene idea de por qué aparece este Warning? El ejemplo colgado ha sido probado en Flex 3.4 última versión.

  13. Skuarex

    Buenas,

    Estoy desarrollando aplicaciones con Adobe Flex Builder 3 y me gustaría crear un árbol (Tree) que pudiera representar un documento XML, lo que he visto es que por cada fichero XML que quiera representar necesito una aplicación Flex diferente ya que se le tienen que configurar antes las etiquetas del archivo XML.

    Lo he probado con archivos XML sencillos y me funciona bien, pero cuando pruebo de representar un archivo XML con una estructura más compleja me salen cosas raras en el árbol.

    Mi objetivo sería conseguir una aplicación flex que permitiera representar cualquier fichero XML en un árbol, y a poder ser, que no requiriera una aplicación para cada archivo XML.

    Muchas gracias por adelanto

    Saludos

Deja un comentario

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

Acerca de Made In Flex

Made In Flex es una comunidad de desarrolladores de Apache Flex creada en 2006.

Apache Flex, anteriormente conocido como Adobe Flex, es un SDK (kit de desarrollo de software) para crear aplicaciones enriquecidas - multiplataforma basadas en Adobe Flash donado por Adobe a la fundación Apache in 2011 y promocionado a proyecto de primer nivel en Diciembre de 2012.

Actualmente estamos cambiando muchos aspectos del sitio web para ofrecer un sitio útil para toda la comunidad que tenga en cuenta las necesidades actuales.

Últimas Fotos

Instalador de Apache Flex

Entrar o Registrase