Sometimes, when working with XML from webservices or public APIs, you will encounter certain elements or attributes in namespaces. For instance, the Yahoo! Weather RSS Feed has a yweather
namespace that adds certain new elements to the feed that aren’t part of the regular RSS standard. To use E4X with complex XML like this, you’ll need to know a couple of things to make this namespaced data accessible.
For the following examples, I will be using the Yahoo! Weather feed for Sunnyvale, CA. It is available at the following URL:
There are two ways to use namespaces in your E4X statements. You can reference the namespace directly in your query, or you can declare the namespace available for use globally. Regardless of which method you use, you’ll need to declare the namespace first. Notice that it is defined by a URL. I’ve taken this value directly from its declaration in the RSS feed itself.
namespace yweather = "http://xml.weather.yahoo.com/ns/rss/1.0";
First, let’s access the current temperature using the namespace inline:
var temp:int = rss.channel.item.yweather::condition.@temp;
It’s simple, but as you can probably imagine, a complex query will require too many references to the namespace. Alternatively, if you don’t want to litter your queries references to yweather::
, you can tell the compiler to use this namespace globally.
use namespace yweather;
Now, we can write a simpler E4X query without the need to worry about our namespace:
var temp:int = rss.channel.item.condition.@temp;
Now, let’s look at the condition
element in the feed a little bit differently. For debug purposes, let’s trace a few values to the console. Notice that we can get the string representation of the attribute’s name very easily through, you guessed it, the name()
function.
var attributes:XMLList = rss.channel.item.condition.attributes(); var count:int = attributes.length(); for( var i:int = 0; iYou can see that when you access an attribute from an element, you're actually getting a new XML object. When most people think of objects of this type, they expect to see an element, but it can hold many different forms of XML data. If you'd like to learn more, check out the documentation for the XML class, and its
nodeKind()
function in particular. You'll discover that an XML object can hold simple text, comments (<!-- comment -->
), attributes, elements, and processing instructions.Let's finish up with the sample XHTML document that I referenced in my second post about E4X.
var html:XML = <html> <body> <ul class="links"> <li><a href="http://www.yahoo.com/" class="josh">Yahoo!</a></li> <li><a href="http://www.adobe.com/">Adobe</a></li> <li><a href="http://joshblog.net/" class="josh">Josh's Blog</a></li> </ul> <div id="intro"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> </div> <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> </body> </html>;I recently discovered that if you try to reference an attribute that doesn't exist, you'll get a runtime error. For example, try to get the all the anchors (links) in the above document with a class named "josh". It doesn't work (without some extra massaging, as you'll see below) because the link to Adobe doesn't have a class attribute at all.
var anchors:XMLList = html.body..a.(@["class"] == "josh"); //errorWhat you can do to get around this problem is to use the
hasOwnProperty()
function available to all Objects. This will allow us to first check to see if the class attribute exists, and if it doesn't, it will skip that particular anchor thanks to the short-circuiting of the&&
operator.var anchors:XMLList = html.body..a.(hasOwnProperty("@class") && @["class"] == "josh");I expected that my first two posts about E4X (1, 2) would cover most of the important details. However, only a couple days after I finished the second one, I had already started remembering more features to explore and share. Will there be more? I don't have anything planned, but I won't be surprised if I discover a couple cool new techniques eventually. 🙂