Home >
Flex XML Quick Tip
Here's a quick tip when working with XML in Flex. E4X is great in most scenarios, it allows you to easily traverse and filter XML-based data structures, and in most cases it is your friend. However, one area where E4X struggles is if you have an XML structure where a node name contains a dash "-" character.
The Flex compiler will not allow you to access xml data in E4X notation, such as:
The compiler will interpret the dashes as subtraction operators, and you'll get compiler errors that might not make any sense. Luckily, you can still access the XML data; you'll just need to deviate from the E4X syntax. Treat the xml object as an associative array, where the property name is a string, and it will return the data value back to you. An example of this is shown below.
Even though the syntax is different, you can still perform E4X operations on the data. The following statement would filter an XML data source and return all "data-one" xml nodes that have a "name" attribute value "Name 1.1".
Here's an example in action... Click on the buttons to toggle between different data sets within the XML. Each button corresponds to a different set of nodes within an xml object.
... and here's the code that makes it all work.
___________________________________
Andrew Trice
Principal Architect
Cynergy Systems
http://www.cynergysystems.com
The Flex compiler will not allow you to access xml data in E4X notation, such as:
dg.dataProvider = xmlDataSource.data-one;
dg.dataProvider = xmlDataSource["data-one"];
dg.dataProvider = xmlDataSource["data-one"].(@name=="Name 1.1");
... and here's the code that makes it all work.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
creationComplete="onCreationComplete()">
<mx:XML id="xmlDataSource">
<data>
<data-one name="Name 1.0" value="100" />
<data-one name="Name 1.1" value="101" />
<data-one name="Name 1.2" value="102" />
<data-one name="Name 1.3" value="103" />
<data-one name="Name 1.4" value="104" />
<data-one name="Name 1.5" value="105" />
<data-one name="Name 1.6" value="106" />
<data-one name="Name 1.7" value="107" />
<data-one name="Name 1.8" value="108" />
<data-one name="Name 1.9" value="109" />
<data-two name="Name 2.0" value="200" />
<data-two name="Name 2.1" value="201" />
<data-two name="Name 2.2" value="202" />
<data-two name="Name 2.3" value="203" />
<data-two name="Name 2.4" value="204" />
<data-two name="Name 2.5" value="205" />
<data-two name="Name 2.6" value="206" />
<data-two name="Name 2.7" value="207" />
<data-two name="Name 2.8" value="208" />
<data-two name="Name 2.9" value="209" />
<data-three name="Name 3.0" value="300" />
<data-three name="Name 3.1" value="301" />
<data-three name="Name 3.2" value="302" />
<data-three name="Name 3.3" value="303" />
<data-three name="Name 3.4" value="304" />
<data-three name="Name 3.5" value="305" />
<data-three name="Name 3.6" value="306" />
<data-three name="Name 3.7" value="307" />
<data-three name="Name 3.8" value="308" />
<data-three name="Name 3.9" value="309" />
</data>
</mx:XML>
<mx:Script>
<![CDATA[
import mx.events.ItemClickEvent;
private function onCreationComplete() : void
{
dg.dataProvider = xmlDataSource["data-one"];
toggleButtonBar.selectedIndex = 0;
}
private function onItemClick( event : ItemClickEvent ) : void
{
switch ( event.index )
{
case 0:
dg.dataProvider = xmlDataSource["data-one"];
break;
case 1:
dg.dataProvider = xmlDataSource["data-two"];
break;
case 2:
dg.dataProvider = xmlDataSource["data-three"];
break;
}
}
private function gridLabelFunction( item : *, column : * ) : String
{
if ( item is XML )
return XML( item ).name().toString();
return item.toString();
}
]]>
</mx:Script>
<mx:ApplicationControlBar dock="true">
<mx:ToggleButtonBar
id="toggleButtonBar"
dataProvider="[ 'One', 'Two', 'Three' ]"
itemClick="onItemClick(event)"/>
</mx:ApplicationControlBar>
<mx:DataGrid
id="dg"
top="10" bottom="10"
left="10" right="10">
<mx:columns>
<mx:Array>
<mx:DataGridColumn headerText="Name" dataField="@name" />
<mx:DataGridColumn headerText="Value" dataField="@value" />
<mx:DataGridColumn headerText="XML Node" labelFunction="gridLabelFunction" />
</mx:Array>
</mx:columns>
</mx:DataGrid>
</mx:Application>
___________________________________
Andrew Trice
Principal Architect
Cynergy Systems
http://www.cynergysystems.com




Facebook Application Development
Nice article Andrew. I actually faced a similar scenario and I encountered it by storing my XML into an ArrayCollection of objects. It also enabled me to change my XML schema without worrying about the Views but it involved the cost of parsing XML and storing it into an ArrayCollection.
The same is for attribute names which are AS keywords, like "class".
E.g. xml.@class will result in a compiler error, xml.attribute("class") won't.
The same is for attribute names which are AS keywords, like "class".
E.g. xml.@class will result in a compiler error, xml.attribute("class") won't.
Amazing tip specially when working with Rails and can't pass dasherize=>false for to_xml method in Rails controllers.
I was trying this only yesterday - the solution I came up with was a string.split("-").replace("_") on my XML - not the best solution I'll wager though.
This is also valid:
dg.dataProvider = xmlDataSource.elements("data-one");
For attributes, there's a similar function:
var values:XMLList = xmlDataSource.elements("data-one").attribute("value");
Folks, do you have any other interesting resource about Flex? I would really like to learn this stuff.
Mike - the chicago storage unit consultant.
Very nice tip man! That issue was driving me crazy, I was about to have all the XML parsed out and re-written (with the dashes replaced by underscores) but this solution works perfectly. It would have been nice if Adobe included this tip in the docs as it was not very easy to find this solution using google.
This is a great solution when working on the area.
But I haven't found a way of escaping the '-' outside the script area.
A have an xml with a "data-set" element that looks like this:
...
This is my datagrid definition:
Where srv is just an mx:HTTPService that retrieves the xml.
I'm getting the "Error: Access of undefined property set."
I've tried several combination of quotes, backslashes but have not succeeded.
I hope somebody has an idea on how to accomplish this.
Oh and no, the xml element cannot be changed to just "dataset" :(
Thank you