tutorials flash e4x_01

E4x – Change in XML format in AS3

General information

XML (Extensible Markup Language) has become impossible to ignore. It is a W3C standard and its use is based on a text format primarily using tags currently allowing numerous developers to structure database formats which allow them to extend the dynamic possibilities of their applications.

I will skip quickly onto the presentation of this “tool” and I will avoid discussing my thoughts on the interest of using this format compared to a format closer to the ECMAScript language used in ActionScript… despite everything, AS3 and its innovations have a more standard approach to E4X, an extension of the ECMAScript language using the ECMA 357 357 standard. We can say that this technique is closer to object oriented programming and makes it possible to more finely appreciate the use of the XML format.

It should be noted that for the rest of the article, I am using the following XML document:

<root>
 
	<!-- An E4x test -->
 
	<?config url="config/config.eden" type="eden" ?>
 
	<?locale path="locale/" default="fr" type="eden" ?>
 
	<users project="solo" url="http://www.solo.burrrn.com" description="solo is an application framework for ECMAScript 4" >
 
		<user pseudo="ekameleon">
			<age>29</age>
			<url>http://www.ekameleon.net</url>
		</user>
 
		<user pseudo="iteratif">
			<age>29</age>
			<url>http://iteratif.free.fr/blog</url>
		</user>
 
		<user pseudo="shaoken">
			<age>23</age>
			<url>http://weblog.shaoken.be</url>
		</user>
 
		<user pseudo="philippe">
			<age>29</age>
			<url>http://philippe.elsass.free.fr</url>
		</user>
 
		<user pseudo="zwetan">
			<age>32</age>
			<url>http://www.zwetan.com</url>
		</user>
 
	</users>
 
	<blackList>
		<user pseudo="ekameleon"/>
	</blackList>
 
</root>

In AS1 and AS2 we had XMLNode and XML classes but their use was often long-winded. In AS3 these classes are replaced by the classes XML, XMLList, QName, and namespace.

It should be noted that the old XML class is always present in AS3 but Adobe have decided to re-name this XMLDocument class. We can find it in the flash.xml package of the AS3 framework with the XMLNode, XMLParser and XMLTag classes.

Declaration of an instance of the XML class

The biggest innovation in XML based E4X is the possibility of using tags directly in the code without having to use a character string to format the XML DOM. Let us see how to declare a simple XML object type in AS3:

1 - creation of a simple instance by using the constructor of the XML class.
var xml:XML = new XML() ;
trace(xml) ;
2 - creation of an instance with a String type parameter (as in AS1 and AS2).
var xml:XML = new XML( "<item>test2</item>" ) ;
trace(xml) ;
3 - creation of an instance by directly using an XML type parameter !
var xml:XML = new XML(<item>test3</item>) ;
trace(xml) ;
4 - creation of an instance by not using the constructor, just the native XML object type.
var xml:XML = <item>test4</item> ;
trace(xml) ;

The 4th syntax is much simpler than those above it. The E4X as you can see can integrate a new native XML object type which is flexible to use but be aware that its direct use can present minor problems… not a huge deal… just a small error in the colour syntax highlighting in Flex2 if you use special characters like comments or quotation marks which indicate the start of a character string… It may be better to illustrate this display bug with an example:

var xml:XML ;
 
xml = <item>http://www.google.fr</item> ;
trace(xml) ;
 
xml = <item>be aware of the character ' or ".</item>
trace(xml) ;

Of course this isn’t a compiler error, but a complete chaos to the presentation of your code! I personally solve this problem by adding the value via an external variable and the appendChild method or otherwise by using the old notation with a constructor using a String type parameter, like this:

var content:String = "http://www.google.fr" ;
 
var xml:XML ;
 
xml = <url/>
xml.appendChild(content) ;
 
trace(xml) ; // output : http://www.google.fr
 
xml = new XML("http://www.google.fr") ; // no problem either
trace(xml) ;

It is inevitably a little less flexible than the direct use but at least I have no more problems on the colour highlighting of my code… I fully understand that Adobe have not planned an escape character for native XML objects but I think that a glance at the algorithm of the colour syntax highlighting for this situation would be a good idea! :)

You have probably noticed that when you trace () an XML object type you have a direct access, using the toString () method, to the content of the principal node of the XML object type whereas in AS1 or AS2 you had the entirety of DOM XML. In the root object of the E4X your instance replaces the first node contained in your file or your XML document. If you wish to recover the true name of the principal node it is necessary to use the new localName () method. It is otherwise possible to use the new toXMLString () method which will return the entirety of the XML document in the form of a character string.

var xml:XML = <item>Mon Texte...</item> ;
 
trace("> xml.locaLName() : " + xml.localName()) ; // sortie : item
trace("> toString : " + xml) ;
trace("> toXMLString : " + xml.toXMLString()) ;

Dynamic loading of an external XML document

Another important innovation of AS3 is externalising the loading of external data with the flash.net.UR LLoader class which replaces both LoadVars and XML involved in the loading of a text-based data structure or based on variables encoded in HTML format. This class also allows the loading of binary data. The URLLoader class has a complete event-driven system which allows the notification of several types of events (Event.COMPLETE, ProgressEvent.PROGRESS, etc)

To load an external XML structure we will therefore use the flash.net.UR LLoader class and the new flash.net.UR LRequest class used by the URLLoader to define all of the information useful in managing external loading.

package
{
 
	import flash.display.Sprite;
 
	import flash.net.URLLoader ;
	import flash.net.URLRequest ;
 
	import flash.events.Event ;
 
	public class TestXML extends Sprite
	{
 
		// ----o Constructor
 
		public function TestXML()
		{
 
			// XML.ignoreComments = false ;
			// XML.ignoreProcessingInstructions = false ;
			// XML.ignoreWhitespace = true ;
 
			var url:String = "xml/test.xml" ; // file encoded in UTF8 containing XML defined at the beginning of this tutorial.
 
			var request:URLRequest = new URLRequest( url ) ;
 
			loader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onComplete);
			loader.load( request ) ;
 
		}
 
		// ----o Public Properties
 
		public var loader:URLLoader ;
		public var xml:XML ;
 
		// ----o Public Methods
 
		public function onComplete(e:Event):void
		{
 
			xml = new XML( loader.data ) ;
 
			try
			{
 
				trace( "loading of xml finished : " + xml ) ;
 
			}
			catch(e:Error)
			{
				trace( e.toString() ) ;			
			}
 
 
		}
 
	}
}

You have probably noticed that I use an exception with a try..catch to intercept errors in the event of problem during the use of the XML variable once the loading of the external file has finished. Indeed, in AS3 there is no longer the “status” property as in AS1 or AS2 to determine whether the XML is valid or not. AS3 now uses internal errors to inform about the status of the data structure. I advise that in the event of a problem it is better to work using a try..catch instruction to avoid cuts in the code during your application debug, it is then simpler to correct whatever is wrong.

Types of tags

If you are somewhat accustomed to the XML format you will probably easily recognise the difference between a tag containing text, containing attributes, containing comments, containing CDATA type tags etc… In the example shown at the start of the tutorial you can see various types of tags. I have mainly emphasised 2 important types of tag, the “Comments” and “Processing” type. Let’s look at these two a little closer:

<root>
 
	<!-- An E4x test -->
 
	<?config url="config/config.eden" type="eden" ?>
 
	<?locale path="locale/" default="fr" type="eden" ?>
 
        etc...

The <!– –> tags are tags which make it possible to define comments in XML documents. These tags could be used internally in a document without being interpreted by the E4x parser.

The <? ?> tags are processing tags used for launching precise instructions while travelling through the XML document. We can regard them as initialisation tags which can be personalised and which enable you to define any kind of functionality (for example to define the style sheet to be loaded to display the text content of the XML document, to initialize and configure the application, to draw up a localisation protocol etc). For the moment I think that it would be totally possible to use traditional tags to define this kind of information but the interest here is the same as the comments tags because it is indeed possible to prevent the compiler from interpreting these kinds of tags.

To control the use of these tags there are 3 new static properties related to the XML class which will enable you at any time to define the way in which you want to interpret your XML document:

  • XML.ignoreComments:Boolean : allows you to ignore (or not) the comments in an XML document.
  • XML.ignoreProcessingInstructions:Boolean : allows you to ignore (or not) processing type instructions contained in an XML document.
  • XML.ignoreWhiteSpace:Boolean : replaces the old XML class property (AS1 and AS2) ignoreWhite. Here the change comes from the appearance of a static property and is no longer linked directly to instances.

In the example of the URLLoader class above, I suggest that you remove the comments in the TestXML class constructor to therefore test in more detail the new static properties defined above.

It should be noted thereafter that once the XML document has loaded, that it is possible to use the comments () and processingInstructions () methods respectively to recover the XMLLists of the “comments” and “processing” type tags.

trace("xml.comments : " + xml.comments()) ;
 
 
trace("------- Processing Instructions") ;
 
var allPI:XMLList = xml.processingInstructions() ;
 
trace("count Processing Instructions in xml : " + allPI.length() ) ; // number of “processing” type tags
 
trace("xml.processingInstructions('config') : " + xml.processingInstructions("config")) ; // to obtain the "processing" tag with the name 'config'
 
trace("xml.processingInstructions('local') : " + xml.processingInstructions("local")) ; // to obtain the "processing" tag with the name 'local'

Beware that the use of a trace () on the allPI variable above sends no message in the output panel, even if the list contains several tags. I have not yet really understood why - it is a little strange to have an output like this for the start to this type of tag.

Note: Make sure you correctly initialise the XML.ignoreComments and XML.ignoreProcessingInstructions properties (false for accessing tags).

Display and debug of an XML object type

Another innovation exists in the debugging of an XML object type with the appearance of the static properties XML.prettyIndent and XML.prettyPrinting.

  • XML.prettyIndent:int : allows one to define via an integer, the indentation between each level in the structure of an XML document.
  • XML.prettyPrinting:Boolean : allows one to apply formatting (or not) to the XML document during the use of a toString () method or a toXMLString () method.
XML.prettyIndent = 2 ;
trace(xml) ;
 
trace("----") ;
 
XML.prettyIndent = 2 ;
trace(xml) ;
 
trace("----") ;
 
XML.prettyPrinting = false ;
trace(xml) ;

Here is another improvement with the appearance of the XML.defaultSettings () method which returns an object containing default properties for XML.

var defaultString:Object = XML.defaultSettings () ;
 
for (var prop:String in defaultString)
{
      trace( " > " + prop + " : " + defaultString[prop]) ;
}
 
/* Sortie :
 
 > prettyPrinting : true
 > prettyIndent : 2
 > ignoreComments : true
 > ignoreProcessingInstructions : true
 > ignoreWhitespace : true
 
*/

What is interesting is that it is possible to create one’s own profile to define the XML class properties and to change them at any time using the XML.setSettings() method. The XML.settings() method returns the object containing the current properties of the XML class. If you want at any time to return to the default properties, you just need to write it in your code:

XML.setSettings(XML.defaultSettings());

Recovering the data contained in an XML document

As I have already said, E4X proposes a more intuitive object-oriented approach to quickly scan the contents of an XML document and to recover the contents. Now let us look in more detail at the key words and instructions which allow you to use your document as best as possible.

While looking closer at the structure of the XML provided at the beginning of this tutorial let us look at how we can recover the contents of the <age> tag of the first <user> contained in the XML document.

In AS2

var age:String = x.firstChild.firstChild.firstChild.firstChild.firstChild.nodeValue ;
trace("> " + age) ; // output : > 29

In AS3

var age:String = xml.users.user[0].age ;
trace("> " + age) ; // output : > 29

It is obvious that the syntax in AS3 is much more flexible than that in AS2 (or AS1).

The children nodes become properties of the parent node in AS3.

trace( xml.users.user ) ; // child user of the users node.

Here is a more extensive example:

trace("------ XMLList") ;
 
trace("> xml.users.user is XMLList : " + (xml.users.user is XMLList) ) ; 
/* exited 
 
	> xml.users.user is XMLList : true
 
*/
 
trace("> " + xml.users.user[0].age) ; // exited : > 29
 
trace("> All lists of age atgs contained in xml.users :\r" + xml.users.user..age) ; // use .. operator
/* output 
 
	All lists of age tags contained in xml.users :
	<age>29</age>
	<age>29</age>
	<age>23</age>
	<age>29</age>
	<age>32</age>
 
*/
 
trace(">All lists of age tags contained in xml.users :\r" + xml.users.*) ; // use * operator
/* exited 
 
	All lists of age tags contained in xml.users :
	<user pseudo="ekameleon"><age>29</age><url>http://www.ekameleon.net</url></user>
	<user pseudo="iteratif"><age>29</age><url>http://iteratif.free.fr/blog</url></user>
	<user pseudo="shaoken"><age>23</age><url>http://weblog.shaoken.be</url></user>
	<user pseudo="philippe"><age>29</age><url>http://philippe.elsass.free.fr</url></user>
	<user pseudo="zwetan"><age>32</age><url>http://www.zwetan.com</url></user>
*/
 
trace("> List of users between the ages of 24 and 31 :\r" + xml.users.user.(age|> > 23 && age < 32) ) ;
/* exited
 
	> List of users between the ages of 24 and 31:
	<user pseudo="ekameleon"><age>29</age><url>http://www.ekameleon.net</url></user>
	<user pseudo="iteratif"><age>29</age><url>http://iteratif.free.fr/blog</url></user>
	<user pseudo="philippe"><age>29</age><url>http://philippe.elsass.free.fr</url></user>
 
*/
 
trace("------ attributes") ;
 
// use the keyword @ and call the attribute directly.				
trace("xml.users.@project : " + xml.users.@project) ; // direct syntax.
 
// use the keyword @ and the syntax between square brackets.
trace("xml.users.@url : " + xml.users.@["url"]) ; // syntax between square brackets.
 
// use the attribute method.
trace("xml.users.attribute('description') : " + xml.users.attribute("description")) ; // 
 
trace("------ method children()") ;
 
// Number of nodes in the users node.
 
trace( "xml.users.children().length() : " + xml.users.children().length() ) ;

It is really interesting to note the appearance of a search across the nodes of the XML document (with the contains() method or with the syntax between brackets as I have done in the example above). By supplementing this search with regular expressions, it is now possible to recover, as in a search engine, the nodes that you want according to precise criteria!

As you can see the possibilities therefore with E4X are numerous. In my opinion, the ideal for understanding this class (like many others) is that you take the time to read the language reference and to supplement that with all that I have just written by applying each example contained in the help facility to each method.

I think that I will stop here for the moment on the description of the functionalities in this new XML class. I will get back to you soon about, amongst other things, the namespace and all that seems useful about it. I have not yet really been able to appreciate all of the possibilities of XML in AS3 and I would like to take a step back to find out more and to compare it with the EDEN format.

More on this subject

About

By ALCARAZ Marc aka EKAMELEON (2006). You can view this tutorial and its comments on my blog.








Adobe Training center


Mediabox Training Centre © 2000 - 2008 All rights reserved.
Adobe Authorized Training Centre. State convention under number 25 14 02167 14.
Mediabox : SARL au capital de 62.000€ - Activity number: 25 14 02167 14 - SIRET : 493 716 468 00027
MEDIABOX, 102 Avenue des Champs Elysées, 75008 PARIS - Tel. +33(0)2.31.91.96.89 - Fax. +33(0)2.72.68.56.42