Avg. Rating 4.7

Problem

I need to insert maximum number of commands in to the one cycle, while working with XML tree.

Solution

I will use E4X filters to work with XML and to process its nodes.

Detailed explanation

For the next examples I will use test XML tree:


private var xml:XML = <root>
  <node name=" Alan " age=" 26 " ><address> <![CDATA[1 Fake address]]> </address></node>
  <node name=" Mike " age=" 31 " ><address> <![CDATA[2 Fake address]]> </address></node>
  <node name=" Greg " age=" 28 " ><address> <![CDATA[3 Fake address]]> </address></node>
  <node name=" Bret " age=" 21 " ><address> <![CDATA[4 Fake address]]> </address></node>
  <node name=" Mike " age=" 32 " ><address> <![CDATA[2 Fake address]]> </address></node>
  <node name=" Greg " age=" 22 " ><address> <![CDATA[3 Fake address]]> </address></node>
  <node name=" Alan " age=" 26 " ><address> <![CDATA[1 Fake address]]> </address></node>
  <node name=" Mike " age=" 34 " ><address> <![CDATA[2 Fake address]]> </address></node>
</root> ;


And simple value object class:


class User extends Object{
      public var name:String = '' ;
      public var age:uint = 0;
      public var address:String = '' ;
      function User(name:String, age:uint): void {
            super ();
            this .name = name;
            this .age = age;
      }
      public function toString():String{
            return '[User(name="' + this .name+ '", age="' + this .age+ '", address="' + this .address+ '")]' ;
      }
}


Any E4X filter should be located inside the round brackets and inside this brackets you can execute any commands separated by commas. First example will use filter to convert XML nodes into value objects:


private function simpleFilter(): void {
      var items:Array = [];
      xml.node.(items.push( new User(@name, uint(@age))));
      trace (items.join( '\n' ));
}
/* trace output
[User(name="Alan", age="26", address="")]
[User(name="Mike", age="31", address="")]
[User(name="Greg", age="28", address="")]
[User(name="Brett", age="21", address="")]
[User(name="Mike", age="32", address="")]
[User(name="Greg", age="22", address="")]
[User(name="Alan", age="26", address="")]
[User(name="Mike", age="34", address="")]
*/


As you can see, all objects created inside E4X filter's body. This example can be rewritten without E4X syntax using cycle:


private function simpleXMLCycle(): void {
      var items:Array = [];
      var xlist:XMLList = xml.node;
      var length:int = xlist.length();
      for ( var i:int=0; i<length; i++){
            var node:XML = xlist[i];
            with (node){
                  items.push(
                        new User(@name, uint(@age))
                  );
            }
      }
      trace (items.join( '\n' ));
}


This example will return the same result as previous. But this example do not display all power of E4X filters. Next example will show you how to use couple expressions inside one filter:


private function separatedFilter(): void {
      var items:Array = [];
      var item:User;
      xml.node.(
            items.push(item = new User(@name, uint(@age))),
            item.address = address[0].toString()
      );
      trace (items.join( '\n' ));
}
/* trace output
[User(name="Alan", age="26", address="1 Fake address")]
[User(name="Mike", age="31", address="2 Fake address")]
[User(name="Greg", age="28", address="3 Fake address")]
[User(name="Brett", age="21", address="4 Fake address")]
[User(name="Mike", age="32", address="2 Fake address")]
[User(name="Greg", age="22", address="3 Fake address")]
[User(name="Alan", age="26", address="1 Fake address")]
[User(name="Mike", age="34", address="2 Fake address")]
*/


Next example contains two filters, one of them - just condition, usual for E4X:


private function multipleFilter(): void {
      trace ( 'multipleFilter' );
      var items:Array = [];
      var item:User;
      xml.node.(int(@age)>30).(
            items.push(item = new User(@name, uint(@age))),
            item.address = address[0].toString()
      );
      trace (items.join( '\n' ));
}
/* trace output
[User(name="Mike", age="31", address="2 Fake address")]
[User(name="Mike", age="32", address="2 Fake address")]
[User(name="Mike", age="34", address="2 Fake address")]
*/


In this example, filters have shared responsibilities - the first filters the data, and the second converts passed data. But the two filters are equal to two cycles, which perform common tasks and the second depends on the outputs of the first cycle. So I 'll rewrite this example using a single filter :


xml.node.(
      // ?: condition
      int(@age)>30 ? (
            // if condition equals TRUE actions, separated by commas
            item = new User(@name, uint(@age)),
            items.push(item),
            item.address = address[0].toString()
      ) : false // if condition equals FALSE actions
);
 

Example.zip
[Examples used in topic]
Report abuse

Related recipes