View comments | RSS feed

The E4X approach to XML processing

The ECMAScript for XML specification defines a set of classes and functionality for working with XML data. These classes and functionality are known collectively as E4X. ActionScript 3.0 includes the following E4X classes: XML, XMLList, QName, and Namespace.

The methods, properties, and operators of the E4X classes are designed with the following goals:

NOTE

 

There was an XML class in ActionScript 2.0. In ActionScript 3.0 it has been renamed XMLDocument, so that it does not conflict with the ActionScript 3.0 XML class that is part of E4X. In ActionScript 3.0, the legacy classes--XMLDocument, XMLNode, XMLParser, and XMLTag--are included in the flash.xml package primarily for legacy support. The new E4X classes are core classes; you need not import a package to use them. This chapter does not go into detail on the legacy ActionScript 2.0 XML classes. For details on these, see the flash.xml package in the ActionScript 3.0 Language and Components Reference.

Here is an example of manipulating data with E4X:

var myXML:XML = 
    <order>
        <item id='1'>
            <menuName>burger</menuName>
            <price>3.95</price>
        </item>
        <item id='2'>
            <menuName>fries</menuName>
            <price>1.45</price>
        </item>
    </order>

Often, your application will load XML data from an external source, such as a web service or a RSS feed. However, for clarity, the examples in this chapter assign XML data as literals.

As the following code shows, E4X includes some intuitive operators, such as the dot (.) and attribute identifier (@) operators, for accessing properties and attributes in the XML:

trace(myXML.item[0].menuName); // Output: burger
trace(myXML.item.(@id==2).menuName); // Output: fries
trace(myXML.item.(menuName=="burger").price); // Output: 3.95

Use the appendChild() method to assign a new child node to the XML, as the following snippet shows:

var newItem:XML = 
    <item id="3">
        <menuName>medium cola</menuName>
        <price>1.25</price>
    </item>

myXML.appendChild(newItem);

Use the @ and . operators not only to read data, but also to assign data, as in the following:

myXML.item[0].menuName="regular burger";
myXML.item[1].menuName="small fries";
myXML.item[2].menuName="medium cola";

myXML.item.(menuName=="regular burger").@quantity = "2";
myXML.item.(menuName=="small fries").@quantity = "2";
myXML.item.(menuName=="medium cola").@quantity = "2";

Use a for loop to iterate through nodes of the XML, as follows:

var total:Number = 0;
for each (var property:XML in myXML.item)
{
    var q:int = Number(property.@quantity);
    var p:Number = Number(property.price);
    var itemTotal:Number = q * p;
    total += itemTotal;
    trace(q + " " + property.menuName + " $" + itemTotal.toFixed(2))
}
trace("Total: $", total.toFixed(2));

Flash CS3


Comments


JAXIMFLASH said on Jul 27, 2007 at 9:06 AM :
If you use an expression to find a value, make sure the expression is applicable to all of the nodes or else you will get an error.

For example, let me modifiy the above XML example so one of the nodes does NOT have an "id" attribute:
<order>
<item>
<menuName>burger</menuName>
<price>3.95</price>
</item>
<item id='2'>
<menuName>fries</menuName>
<price>1.45</price>
</item>
</order>

The following line would then produce an error and NOT output "fries"

trace(myXML.item.(@id==2).menuName);

Error produced...
ReferenceError: Error #1065: Variable @id is not defined.


You would think that since the first "item" doies not have an ID, the above trace statement would ignore the first node and find the node where (@id ==2), but that's not the case. Becasue the 1st "item" does not have an id, it produces an error. It would seem that all "item"s would require the "id" attribute for the expression to work.

If anyone knows of a workaround this problem, please respond.
CapiRight said on Oct 30, 2007 at 7:41 AM :
to the guy above me: I would probably do an if statement, or a more brutal way is to catch this exception and ignore it.

my question is how to traverse my xml looking for a random attribute and getting the node back (like XPath query)?
.//*[@name='capi'] will return in XPath all the nodes under the root that have an attribute named name with a value of 'capi' in them. how do I convert that to E4X style?
candor100 said on Jan 2, 2008 at 7:13 PM :
See Mike Morearty's blog on this at http://www.morearty.com/blog/2006/11/01/e4x-tip-and-quiz-writing-expressions-to-test-attributes-that-may-not-exist/

His suggestion is to replace .@year with .attribute("year") for any attribute that you don't know for sure will be present. This uses the http://livedocs.adobe.com/flex/2/langref/XML.html#attribute(). It worked well for me.

 

RSS feed | Send me an e-mail when comments are added to this page | Comment Report

Current page: http://livedocs.adobe.com/flash/9.0/main/00000124.html