bool Downloader::ParseRSS(xmlDocPtr doc) { xmlXPathContextPtr xp_ctx = xmlXPathNewContext(doc); xmlXPathObjectPtr xpath_obj = xmlXPathEvalExpression(BAD_CAST "/rss/channel/item", xp_ctx); bool ok = false; if (xpath_obj->nodesetval) { wxDateTime time; wxString md5; wxString version; wxString url; for (int i = 0; i < xpath_obj->nodesetval->nodeNr; i++) { wxDateTime itime; if (parse_rss_item(xpath_obj->nodesetval->nodeTab[i], url, version, md5, itime) && (!time.IsValid() || itime > time)) { m_url = url; m_version = version; m_md5 = md5; time = itime; ok = true; } } } xmlXPathFreeObject(xpath_obj); xmlXPathFreeContext(xp_ctx); return ok; }
static TotemPlParserResult parse_rss_items (TotemPlParser *parser, const char *uri, xml_node_t *parent) { const char *title, *language, *description, *author; const char *contact, *img, *pub_date, *copyright; xml_node_t *node; title = language = description = author = NULL; contact = img = pub_date = copyright = NULL; /* We need to parse for the feed metadata first, then for the items */ for (node = parent->child; node != NULL; node = node->next) { if (node->name == NULL) continue; if (g_ascii_strcasecmp (node->name, "title") == 0) { title = node->data; } else if (g_ascii_strcasecmp (node->name, "language") == 0) { language = node->data; } else if (g_ascii_strcasecmp (node->name, "description") == 0 || g_ascii_strcasecmp (node->name, "itunes:subtitle") == 0) { description = node->data; } else if (g_ascii_strcasecmp (node->name, "author") == 0 || g_ascii_strcasecmp (node->name, "itunes:author") == 0 || (g_ascii_strcasecmp (node->name, "generator") == 0 && author == NULL)) { author = node->data; } else if (g_ascii_strcasecmp (node->name, "webMaster") == 0) { contact = node->data; } else if (g_ascii_strcasecmp (node->name, "image") == 0) { img = node->data; } else if (g_ascii_strcasecmp (node->name, "itunes:image") == 0) { const char *href; href = xml_parser_get_property (node, "href"); if (href != NULL) img = href; } else if (g_ascii_strcasecmp (node->name, "lastBuildDate") == 0 || g_ascii_strcasecmp (node->name, "pubDate") == 0) { pub_date = node->data; } else if (g_ascii_strcasecmp (node->name, "copyright") == 0) { copyright = node->data; } } /* Send the info we already have about the feed */ totem_pl_parser_add_uri (parser, TOTEM_PL_PARSER_FIELD_IS_PLAYLIST, TRUE, TOTEM_PL_PARSER_FIELD_URI, uri, TOTEM_PL_PARSER_FIELD_TITLE, title, TOTEM_PL_PARSER_FIELD_LANGUAGE, language, TOTEM_PL_PARSER_FIELD_DESCRIPTION, description, TOTEM_PL_PARSER_FIELD_AUTHOR, author, TOTEM_PL_PARSER_FIELD_PUB_DATE, pub_date, TOTEM_PL_PARSER_FIELD_COPYRIGHT, copyright, TOTEM_PL_PARSER_FIELD_IMAGE_URI, img, TOTEM_PL_PARSER_FIELD_CONTACT, contact, NULL); for (node = parent->child; node != NULL; node = node->next) { if (node->name == NULL) continue; if (g_ascii_strcasecmp (node->name, "item") == 0) parse_rss_item (parser, node); } totem_pl_parser_playlist_end (parser, uri); return TOTEM_PL_PARSER_RESULT_SUCCESS; }
static GList* feed_rss_handler_parse (FeedHandler *self, GrssFeedChannel *feed, xmlDocPtr doc, gboolean do_items, GError **error) { gchar *tmp; gboolean rdf; time_t now; GList *items; xmlNodePtr cur; GrssFeedItem *item; FeedRssHandler *parser; items = NULL; rdf = FALSE; now = time (NULL); parser = FEED_RSS_HANDLER (self); cur = xmlDocGetRootElement (doc); while (cur && xmlIsBlankNode (cur)) cur = cur->next; if (!xmlStrcmp (cur->name, BAD_CAST"rss")) { cur = cur->xmlChildrenNode; rdf = FALSE; } else if (!xmlStrcmp (cur->name, BAD_CAST"rdf") || !xmlStrcmp (cur->name, BAD_CAST"RDF")) { cur = cur->xmlChildrenNode; rdf = TRUE; } else if (!xmlStrcmp (cur->name, BAD_CAST"Channel")) { rdf = FALSE; } else { g_set_error (error, FEED_RSS_HANDLER_ERROR, FEED_RSS_HANDLER_PARSE_ERROR, "Could not find RDF/RSS header!"); return NULL; } while (cur && xmlIsBlankNode (cur)) cur = cur->next; while (cur) { if (!cur->name) { g_warning ("invalid XML: parser returns NULL value -> tag ignored!"); cur = cur->next; continue; } if ((!xmlStrcmp (cur->name, BAD_CAST"channel")) || (!xmlStrcmp (cur->name, BAD_CAST"Channel"))) { parse_channel (parser, feed, doc, cur); if (rdf == FALSE) cur = cur->xmlChildrenNode; break; } cur = cur->next; } /* For RDF (rss 0.9 or 1.0), cur now points to the item after the channel tag. */ /* For RSS, cur now points to the first item inside of the channel tag */ /* This ends up being the thing with the items, (and images/textinputs for RDF) */ /* parse channel contents */ while (cur) { if (cur->type != XML_ELEMENT_NODE || NULL == cur->name) { cur = cur->next; continue; } /* save link to channel image */ if ((!xmlStrcmp (cur->name, BAD_CAST"image"))) { if (NULL != (tmp = parse_image (cur))) { grss_feed_channel_set_image (feed, tmp); g_free (tmp); } } else if (do_items == TRUE && (!xmlStrcmp (cur->name, BAD_CAST"items"))) { /* RSS 1.1 */ xmlNodePtr iter = cur->xmlChildrenNode; while (iter) { item = parse_rss_item (parser, feed, doc, iter); if (item != NULL) { if (grss_feed_item_get_publish_time (item) == 0) grss_feed_item_set_publish_time (item, now); items = g_list_append (items, item); } iter = iter->next; } } else if (do_items == TRUE && (!xmlStrcmp (cur->name, BAD_CAST"item"))) { /* RSS 1.0, 2.0 */ item = parse_rss_item (parser, feed, doc, cur); if (item != NULL) { if (grss_feed_item_get_publish_time (item) == 0) grss_feed_item_set_publish_time (item, now); items = g_list_append (items, item); } } cur = cur->next; } grss_feed_channel_set_format (feed, "application/rss+xml"); if (items != NULL) items = g_list_reverse (items); return items; }