I am putting together an ActionScript 2 class to represent and parse Atom feeds. I have put together an early alpha version of the class, but wanted to get some feedback on it before I continue work on it.
Alpha .22: (Feb.12 2004)
- Refactored to make it easier to extend and add support for custom namespaces
- User cannot add nodes
- tag attributes are now placed in attributes object for element.
- TODO: check case sensitivity in switch statements
- TODO: check if namespace is added tags : atom:element
- TODO: optimize parse functions
- TODO: document api
- TODO: wrap in MXP file for distribution
Alpha .20:
- Should parse all elements and attributes described in the Atom .03 spec.
- Does not currently support non-atom namespaces.
- Utilizes the W3CDateTime class
Alpha .10:
- Does not parse all Atom elements.
- Only parses elements included in default Movable Type atom feed. Specifically, my Atom feed.
- Cannot yet add nodes
- Dates are not supported yet. Need to make a date class for the date types used by Atom
- This is a super early version, and the code will probably drastically change.
Before I finish up adding support for all of Atom, I wanted to get some input on the class, and how I make the Atom dom avaliable. Please post any suggestions in the comments.
One quick comment (and my personal opinion), thus far, Atom has been a pure joy to work with. It is so nice have a structured format to work with. I love what RSS enables, but with all of the different versions, and permutations, it is a huge hassle to work with.
Anyways, here is the class (v .20):
[code]/*Atom.asMike Chambersmesh@macromedia.comClass that represents an Atom XML document.You can find more information on Atom at:http://www.atomenabled.orgVersion Alpha .22-user cannot yet add nodes-check case sensitivity in switch statements-check if namespace is added tags : atom:element-optimize parse functions*/import mx.events.EventDispatcher;import com.macromedia.date.W3CDateTime;class com.macromedia.data.Atom extends XML{private var dispatchEvent:Function;public var addEventListener:Function;public var removeEventListener:Function;private var feed:Object;private var entriesArray:Array;private var ignoreWhite:Boolean = true;public function Atom(xmlSource:String){super(xmlSource);mx.events.EventDispatcher.initialize(this);}private function onLoad(success:Boolean):Void{if(!success){//throw errortrace("xml did not load");return;}parseFeedTags();dispatchEvent({type:"onAtomLoad", target:this});}//need a way to reparse if user manually adds nodesprivate function parseFeedTags(Void):Void{feed = parseFeedElement();//should this be in info, or in feed//feed.info = parseFeedElement();var nodes:Array = firstChild.childNodes;var len:Number = nodes.length;var node:XMLNode;for(var i:Number = 0; i< len; i++){node = nodes[i];//do we need to worry about case sensitivity?switch(node.nodeName){case "entry":{break;}case "title":{feed.title = parseFeedTitle(node);break;}case "author":{feed.author = parseFeedAuthor(node);break;}case "contributor":{feed.contributor = parseFeedContributor(node);break;}case "tagline":{feed.tagline = parseFeedTagline(node);break;}case "copyright":{feed.copyright = parseFeedCopyright(node);break;}case "generator":{feed.generator = parseFeedGenerator(node);break;}case "info":{feed.info = parseFeedInfo(node);break;}case "id":{feed.id = parseFeedId(node);break;}case "link":{feed.link = parseFeedLink(node);break;}case "modified":{feed.modified = parseFeedModified(node);break;}default:{parseFeedDefault(node);break;}}}}private function parseFeedTitle(node:XMLNode):Object{var obj:Object = new Object();obj.value = node.firstChild.nodeValue;return obj;}private function parseFeedAuthor(node:XMLNode):Object{var obj:Object = parsePersonConstruct(node);return obj;}private function parseFeedContributor(node:XMLNode):Object{var obj:Object = parsePersonConstruct(node);return obj;}private function parseFeedTagline(node:XMLNode):Object{var obj:Object = new Object();obj.value = node.firstChild.nodeValue;return obj;}private function parseFeedCopyright(node:XMLNode):Object{var obj:Object = new Object();obj.value = node.firstChild.nodeValue;return;}private function parseFeedGenerator(node:XMLNode):Object{var obj:Object = new Object();obj.value = node.firstChild.nodeValue;var genAtts:Object = node.attributes;obj.url = genAtts.url;obj.version = genAtts.version;return obj;}private function parseFeedInfo(node:XMLNode):Object{var obj:Object = new Object();obj.value = node.firstChild.nodeValue;return obj;}private function parseFeedId(node:XMLNode):Object{var obj:Object = new Object();obj.value = node.firstChild.nodeValue;return;}private function parseFeedLink(node:XMLNode):Object{var obj:Object = parseLinkConstruct(node);return obj;}private function parseFeedModified(node:XMLNode):Object{var obj:Object = new Object();obj.value = W3CDateTime.parseString(node.firstChild.nodeValue);return obj;}private function parseFeedDefault(node:XMLNode):Object{return undefined;}private function parseLinkConstruct(node:XMLNode):Object{var feedAtts:Object = node.attributes;var link:Object = new Object();link.attributes = new Object();link.attributes.rel = feedAtts.rel;link.attributes.type = feedAtts.type;link.attributes.href = feedAtts.href;link.attributes.title = feedAtts.title;return link;}private function parseFeedElement(Void):Object{var feedInfo:Object = new Object();feedInfo.attributes = new Object();var feedAttributes:Object = firstChild.attributes;feedInfo.attributes.version = feedAttributes.version;feedInfo.attributes["xml:lang"] = feedAttributes["xml:lang"];return feedInfo;}//need a way to reparse if user manually adds nodesprivate function parseEntries(Void):Void{entriesArray = new Array();var nodes:Array = firstChild.childNodes;var len:Number = nodes.length;var node:XMLNode;var tempEntry:Object;for(var i:Number = 0; i< len; i++){node = nodes[i];if(node.nodeName == "entry"){tempEntry = parseEntry(node);entriesArray.push(tempEntry);}}}private function parseEntry(node:XMLNode):Object{if(node == undefined){return;}var entryElements:Array = node.childNodes;var elementLen:Number = entryElements.length;var entry:Object = new Object();var entryElement:XMLNode;for(var k:Number = 0; k < elementLen; k++){entryElement = entryElements[k];switch(entryElement.nodeName){case "title":{entry.title = parseEntryTitle(entryElement);break;}case "link":{entry.link = parseEntryLink(entryElement);break;}case "modified":{entry.modified = parseEntryModified(entryElement);break;}case "issued":{entry.issued = parseEntryIssued(entryElement);break;}case "id":{entry.id = parseEntryId(entryElement);break;}case "created":{entry.created = parseEntryCreated(entryElement);break;}case "summary":{entry.summary = parseEntrySummary(entryElement);break;}case "author":{entry.author = parseEntryAuthor(entryElement);break;}case "contributor":{entry.contributor = parseEntryContributor(entryElement);break;}case "content":{entry.content = parseEntryContent(entryElement);break;}default:{//pass this to a parse default functionbreak;}}}return entry;}private function parseEntryTitle(node:XMLNode):Object{var obj:Object = new Object();obj.value = node.firstChild.nodeValue;return obj;}private function parseEntryLink(node:XMLNode):Object{var obj:Object = parseLinkConstruct(node);return obj;}private function parseEntryModified(node:XMLNode):Object{var obj:Object = new Object();obj.value = W3CDateTime.parseString(node.firstChild.nodeValue);return obj;}private function parseEntryIssued(node:XMLNode):Object{var obj:Object = new Object();obj.value = W3CDateTime.parseString(node.firstChild.nodeValue);return obj;}private function parseEntryId(node:XMLNode):Object{var obj:Object = new Object();obj.value = node.firstChild.nodeValue;return obj;}private function parseEntryCreated(node:XMLNode):Object{var obj:Object = new Object();obj.value = W3CDateTime.parseString(node.firstChild.nodeValue);return obj;}private function parseEntrySummary(node:XMLNode):Object{var obj:Object = new Object();obj.value = node.firstChild.nodeValue;obj.type = node.attributes.type;var childNodes:Array = node.childNodes;var childNodesLen:Number = childNodes.length;var childNode:XMLNode;//TODO: test this with a summary tag//find out if there is a created nodefor(var z:Number = 0; z < childNodesLen; z++){childNode = childNodes[z];if(childNode.nodeName == "created"){obj.created = new Object();obj.created.value =W3CDateTime.parseString(childNode.firstChild.nodeValue);break;}}return obj;}private function parseEntryAuthor(node:XMLNode):Object{var obj:Object = parsePersonConstruct(node);return obj;}private function parseEntryContributor(node:XMLNode):Object{var obj:Object = parsePersonConstruct(node);return obj;}private function parseEntryContent(node:XMLNode):Object{var obj:Object = new Object();obj.attributes = new Object();var atts:Object = node.attributes;obj.attributes.mode = atts.mode;obj.attributes.type = atts.type;obj.value = node.firstChild.nodeValue;return obj;}private function parsePersonConstruct(node:XMLNode):Object{var author:Object = new Object();var children:Array = node.childNodes;var len:Number = children.length;var tempNode:Object;var tempName:String;for(var i:Number = 0; i < len; i++){tempNode = children[i];tempName = tempNode.nodeName;switch(tempName){case "name":{//fall through}case "url":{//fall through}case "email":{author[tempName] = new Object();author[tempName].value = tempNode.firstChild.nodeValue;break;}}}return author;}/**************** Public API / Getters *******************///TODO: make sure we have getters for all of the top level feed elementspublic function getFeedTitle(Void):String{return feed.title.value;}public function getFeedModified(Void):Date{return feed.modified.value;}public function getFeedLink(Void):Object{return feed.link;}public function getFeedId(Void):String{return feed.id.value;}public function getFeedGenerator(Void):String{return feed.generator.value;}public function getFeedCopyright(Void):String{return feed.copyright.value;}public function getFeedTagline(Void):String{return feed.tagline.value;}//TODO : should this be a property?public function getFeed(Void):Object{return feed;}public function get entries ():Array{if(entriesArray == undefined){parseEntries();}return entriesArray;}}[/code]

Just curious Mike, why the use of actual getxxx() rather than using properties?Preference or reason?
To be honest, this is something that I have still not settled on. I may still change it.The main reason that most are getters, is that what I am used to doing.entries is a property, because that felt like a dataProvider.Anyways, it might change, I am still trying to figure out when to use which.Any suggestions?mike chambersmesh@macromedia.com
I dunno, I’m not an actionscript junkie (but heading there).I use properties for any get/set scenario unless the class HAS to follow an interface and the get itself is part of the ‘contract’. It’s a rare occurance so something not to hold on to.In ColdFusion there isn’t a concept of properties per se (not in this context) so I use getxxx() out of habit, I was really just feeling out to see if it was performance/preference based or habit.Properties are pretty sultry, but getxxx() is pretty direct on what is being done.In the end it just might be preference.
One could potentially use this with blogger couldn’t they!I’ve been searching for this for a while… thanks for the idea.
This might be a dumb question: where do you put this?I have saved it as Atom.as.I have worked created a doc using tree comp named treeXMLI thought it needed to go in the classes/mx/data directory but my Flash file isn’t seeing this.
Do you know how one could use it with Flex?how would you initialize it on a result event from an httpService?Would I have to modify the constructor?Regards,pim
How do you connect? Any scripts on WSSE
Basically Im trying to do something with flash that I think you have either accomplished, or are trying to do.I want to place in its own layer, any kind of component that will allow me to pull in a xml file (atom.xml) which is a blog feed. I want to pull it into flash instead of having to put it in an html page.If you want to see the idea that I want to use, just check out this link ( http://www.he-ekklesia.org) I want to do the exact same thing, I want the blog to be right on top of the first page.The only problem is, I can not figure out how to get flash to import the atom.xml feed into a component.Thanks for your time-Jasen BurkettYhwh Design