summaryrefslogtreecommitdiff
path: root/bPod/php/cybozuLab/rssParser/ParsingRss.as
blob: bff21611549cd4e71fd0aa1240218a9e2f088e98 (plain)
1
/*
	Action script 2.0 RSS parser package
    Copyright (C) 2006 Cybozu Labs, Inc.
   
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.
   
    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.
   
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

/*
	class: com.cybozuLab.rssParser.ParsingRss
	version: 0.1
	Last-modified: 01/Feb/2006

	Parsing RSS 2.0 feed for Action Script 2.0
*/

import com.cybozuLab.rssParser.*;

class com.cybozuLab.rssParser.ParsingRss
{
	private static var DEBUG:Boolean = false;

	private var targetRssXml:XMLNode; //rss feed XML Node tree

	private var errorMessage:String;

	private var parsedRssObj:Object;
	private var parsedRssChannelObj:Object;
	private var parsedRssItemObj:Array;

	private var isInRssTag:Boolean;
	private var isInChannelTag:Boolean;
	private var isInItemTag:Boolean;
	private var currentChannelNum:Number;
	private var currentItemNum:Number;

	private var channelStackArray:Array;
	private var itemStackArray:Array;
	private var nodeObjStack:Array;

	/*
		function: ParsingRss
		constructor
	*/
	public function ParsingRss ( sourceData:XMLNode )
	{
		if( sourceData == undefined )
		{
			errorMessage = "Parsing Error : Called without source data.";
			throw new RssParserException( errorMessage );
		}

		targetRssXml = sourceData;
		isInRssTag = false;
		isInChannelTag = false;
		isInItemTag = false;
		currentItemNum = 0;
		channelStackArray = new Array();
		itemStackArray = new Array();

		parsedRssObj = new Object();
		parsedRssChannelObj = new Object();
		parsedRssItemObj = new Array();

		parseRss( targetRssXml );
		parsedRssObj["channel"] = parsedRssChannelObj;
		parsedRssObj["channel"]["item"] = parsedRssItemObj;
	}

	public function getRssObject():Object
	{
		return parsedRssObj;
	}
	
	public function traceRssObject():Void
	{
		Utils.traceObj( parsedRssObj );
	}
	
	private function parseRss( currentNode:XMLNode ):Void
	{
		for ( var aNode:XMLNode = currentNode; aNode != null; aNode = aNode.nextSibling )
		{
			if( isInItemTag )
			{
				itemStackArray.unshift( aNode.nodeName );
			}
			else if( isInChannelTag )
			{
				channelStackArray.unshift( aNode.nodeName );
			}

			/*
				Parse attributes.
			*/
			if( ! isInRssTag
			   && aNode.nodeName.toLowerCase() == "rss"
			   && Utils.countProperty( aNode.attributes ) >0 )
			{
				nodeObjStack = Array();
				appendAttribute( parsedRssObj, aNode.attributes );
			}
			else if( isInItemTag
				   && Utils.countProperty( aNode.attributes) >0 )
			{
				nodeObjStack = itemStackArray.slice( 0 );
				appendAttribute( parsedRssItemObj[ currentItemNum ], aNode.attributes );
			}
			else if( isInChannelTag
				   && Utils.countProperty( aNode.attributes ) >0 )
			{
				nodeObjStack = channelStackArray.slice( 0 );
				appendAttribute( parsedRssChannelObj, aNode.attributes );
			}

			/*
				Parse child node or data.
			*/
			if( ! isInRssTag
			   && aNode.nodeName.toLowerCase() == "rss" )
			{
				isInRssTag = true;
				parseRss(aNode.firstChild);
				isInRssTag = false;
			}
			else if( ! isInChannelTag
				  && aNode.nodeName.toLowerCase() == "channel" )
			{
				isInChannelTag = true;
				parseRss(aNode.firstChild);
				isInChannelTag = false;
				currentChannelNum++;
			}
			else if( ! isInItemTag
			   && channelStackArray.length == 1
			   && aNode.nodeName.toLowerCase() == "item" )
			{
				isInItemTag = true;
				parsedRssItemObj[ currentItemNum ] = new Object();
				parseRss(aNode.firstChild);
				isInItemTag = false;
				currentItemNum++;
			}
			else if( aNode.firstChild.nodeType == 1 )
			{
				parseRss( aNode.firstChild );
			}
			else if( aNode.firstChild.nodeType == 3 )
			{
				if( isInItemTag )
				{
					nodeObjStack = itemStackArray.slice( 0 );
					appendNodeValue( parsedRssItemObj[ currentItemNum ], aNode.firstChild.nodeValue );
				}
				else if( isInChannelTag )
				{
					nodeObjStack = channelStackArray.slice( 0 );
					appendNodeValue( parsedRssChannelObj, aNode.firstChild.nodeValue );
				}
				else
				{
					trace("no rss value : "+ aNode.firstChild.nodeValue);
				}
			}
			
			if( isInItemTag )
			{
				itemStackArray.shift( );
			}
			else if( isInChannelTag )
			{
				channelStackArray.shift( );
			}
		}  // close for loop
	}  // close function

	private function appendNodeValue( nodeObj:Object, nodeValue:String )
	{
		if( nodeObjStack.length > 0 )
		{
			var key = nodeObjStack.pop();
			if( nodeObj[ key ] == undefined )
			{
				nodeObj[ key ] = new Object();
				if( key != key.toLowerCase() )
				{
					nodeObj[ key.toLowerCase() ] = new Object();
				}
			}
			appendNodeValue(  nodeObj[ key ], nodeValue  );
			if( key != key.toLowerCase() )
			{
				appendNodeValue(  nodeObj[ key.toLowerCase() ], nodeValue  );
			}
		}
		else
		{
			nodeObj["value"] = nodeValue;
		}
	}

	private function appendAttribute( nodeObj:Object, attributes:Object )
	{
		if( nodeObjStack.length > 0 )
		{
			var key = nodeObjStack.pop();
			if( nodeObj[ key ] == undefined )
			{
				nodeObj[ key ] = new Object();
				if( key != key.toLowerCase() )
				{
					nodeObj[ key.toLowerCase() ] = new Object();
				}
			}
			appendAttribute(  nodeObj[ key ], attributes  );
			if( key != key.toLowerCase() )
			{
				appendAttribute(  nodeObj[ key.toLowerCase() ], attributes  );
			}
		}
		else
		{
			nodeObj["attrs"] = attributes;
		}
	}
}