blob: 778e4dc98dd58aef4bf42540ec179e0216d61ca9 [file] [log] [blame]
/*
* Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
*
* 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 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 Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "RSS20Parser.h"
#include "BlackBerryPlatformAssert.h"
#include "libxml/parser.h"
#include "libxml/xmlwriter.h"
namespace WebCore {
RSS20Parser::RSS20Parser()
{
}
bool RSS20Parser::parseBuffer(const char* buffer, int length, const char* url, const char* encoding)
{
return parseXmlDoc(xmlReadMemory(buffer, length, url, encoding, XML_PARSE_NOBLANKS | XML_PARSE_NONET));
}
bool RSS20Parser::parseXmlDoc(xmlDocPtr doc)
{
if (!doc)
return false;
xmlNode* node = xmlDocGetRootElement(doc);
if (!node) {
xmlFreeDoc(doc);
return false;
}
for (; node; node = node->next) {
String name(reinterpret_cast<const char*>(node->name));
name.makeLower();
if (name == "rss") {
xmlNode* channel = node->children;
if (channel->type == XML_ELEMENT_NODE) {
name = reinterpret_cast<const char*>(channel->name);
name.makeLower();
if (name == "channel")
m_root = parseFeed(channel->children);
}
break;
}
}
xmlFreeDoc(doc);
return m_root;
}
bool RSS20Parser::parseItemBaseAttribute(RSSItemBase* item, const String& name, xmlNode* node)
{
if (name == "link")
item->m_link = textFromXMLNode(node);
else if (name == "title")
item->m_title = textFromXMLNode(node);
else if (name == "description")
item->m_description = textFromXMLNode(node);
else if (name == "pubdate")
item->m_pubDate = textFromXMLNode(node);
else
return false;
return true;
}
RSSItem* RSS20Parser::parseItem(xmlNode* node)
{
BLACKBERRY_ASSERT(node);
RSSItem* item = new RSSItem();
for (; node; node = node->next) {
String name(reinterpret_cast<const char*>(node->name));
name.makeLower();
if (parseItemBaseAttribute(item, name, node))
continue;
if (name == "author")
item->m_author = textFromXMLNode(node);
else if (name == "creator") {
if (item->m_author.isEmpty())
item->m_author = textFromXMLNode(node);
} else if (name == "category")
item->m_categories.append(textFromXMLNode(node));
else if (name == "comments")
item->m_comments = textFromXMLNode(node);
else if (name == "enclosure") {
// Right now we assume there is only one enclosure per item, and we handle only
// the first enclosure if there are multiple ones.
// Reference: http://www.rssboard.org/rss-profile#element-channel-item-enclosure
if (!item->m_enclosure)
item->m_enclosure = parseEnclosure(node);
}
}
return item;
}
RSSFeed* RSS20Parser::parseFeed(xmlNode* node)
{
BLACKBERRY_ASSERT(node);
RSSFeed* feed = new RSSFeed();
for (; node; node = node->next) {
String name(reinterpret_cast<const char*>(node->name));
name.makeLower();
if (parseItemBaseAttribute(feed, name, node))
continue;
if (name == "item")
feed->m_items.append(parseItem(node->children));
else if (name == "language")
feed->m_language = textFromXMLNode(node);
else if (name == "ttl")
feed->m_ttl = textFromXMLNode(node);
}
return feed;
}
RSSEnclosure* RSS20Parser::parseEnclosure(xmlNode* node)
{
BLACKBERRY_ASSERT(node);
RSSEnclosure* enclosure = new RSSEnclosure();
for (xmlAttr* attr = node->properties; attr; attr = attr->next) {
String name(reinterpret_cast<const char*>(attr->name));
name.makeLower();
if (name == "url")
enclosure->m_url = textFromXMLAttr(attr);
else if (name == "type")
enclosure->m_type = textFromXMLAttr(attr);
else if (name == "length")
enclosure->m_length = textFromXMLAttr(attr);
}
return enclosure;
}
} // namespace WebCore