RssXml.cpp

/****************************************************************************/

/**                                                                        **/

/** Copyright (c) 2005 Diodia Software          (http://www.diodia.com/)   **/

/**                                                                        **/

/** Use in any form with or without modification for commercial and non-   **/

/** commercial purposes is permitted.                                      **/

/**                                                                        **/

/****************************************************************************/

#include "stdafx.h"

 

#include "XmlHelpers.h"

#include "RssHelpers.h"

#include "RssFeedC.h"

 

static bool IsElementNode(IXMLDOMNode *FeedNode);

static bool IsRdfTagName(const char *TagName);

static bool IsRssTagName(const char *TagName);

static bool UpdateRss10Feed(RssFeedC *Feed, IXMLDOMNode *FeedNode);

static bool UpdateRss20Feed(RssFeedC *Feed, IXMLDOMNode *FeedNode);

 

/****************************************************************************/

/*

/* DESCRIPTION : Update RSS feed.

/*

/* RETURN VALUE: true - if OK

/*               false - if error

/*

/****************************************************************************/

bool UpdateRssFeed(RssFeedC *Feed)

{

   IXMLDOMDocument *XmlDoc;

   IXMLDOMNode *DocNode;

   IXMLDOMNode *FeedNode;

   IXMLDOMNode *TmpNode;

   std::string  TagName;

   int          Idx;

   HRESULT      Result;

   bool         Res;

 

   for (Idx = 0; Idx < Feed->GetNoOfItems(); Idx++)

      Feed->GetNthItem(Idx)->SetIsOld(true);

 

   XmlDoc = CreateXmlDocument(false, L"");

   if (!XmlDoc)

      return false;

 

   if (!ReadXmlDocument(XmlDoc, Feed->GetUrl()))

   {

      XmlDoc->Release();

      return false;

   }

 

   DocNode = SelectXmlNode(XmlDoc, "/");

   if (!DocNode)

   {

      XmlDoc->Release();

      return false;

   }

 

   Result = DocNode->get_firstChild(&FeedNode);

   DocNode->Release();

   if (FAILED(Result) || !FeedNode)

   {

      XmlDoc->Release();

      return false;

   }

 

   TagName = GetXmlNodeTagName(FeedNode);

   while(!IsElementNode(FeedNode) || (!IsRdfTagName(TagName.c_str()) && !IsRssTagName(TagName.c_str())))

   {

      FeedNode->get_nextSibling(&TmpNode);

      FeedNode->Release();

      if (FAILED(Result) || !TmpNode)

      {

         XmlDoc->Release();

         return false;

      }

      FeedNode = TmpNode;

      TagName = GetXmlNodeTagName(FeedNode);

   }

 

   if (IsRdfTagName(TagName.c_str()))

   {

      SetXmlXPathSelections(XmlDoc, L"xmlns:rss='http://purl.org/rss/1.0/' xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:ms='urn:schemas-microsoft-com:xslt'");

      Res = UpdateRss10Feed(Feed, FeedNode);

   }

   else

   {

      Res = UpdateRss20Feed(Feed, FeedNode);

   }

 

   FeedNode->Release();

   XmlDoc->Release();

 

   Feed->DeleteOldItems();

 

   return Res;

}

 

/****************************************************************************/

/*

/* DESCRIPTION : Check if node type is "element".

/*

/* RETURN VALUE: true - if it is

/*               false - otherwise

/*

/****************************************************************************/

static bool IsElementNode(IXMLDOMNode *Node)

{

   DOMNodeType  Type;

   HRESULT      Result;

 

   Result = Node->get_nodeType(&Type);

   if (FAILED(Result) || Type != NODE_ELEMENT)

      return false;

 

   return true;

}

 

/****************************************************************************/

/*

/* DESCRIPTION : Check if tag name is "rdf".

/*

/* RETURN VALUE: true - if it is

/*               false - otherwise

/*

/****************************************************************************/

static bool IsRdfTagName(const char *TagName)

{

   CString      LowerName = TagName;

   int          Pos;

 

   LowerName.MakeLower();

   Pos = LowerName.ReverseFind(':');

 

   if (Pos >= 0)

      return strcmp(LowerName.Right((int) strlen(LowerName) - Pos - 1), "rdf") == 0;

 

   return strcmp(LowerName, "rdf") == 0;

}

 

/****************************************************************************/

/*

/* DESCRIPTION : Check if tag name is "rss".

/*

/* RETURN VALUE: true - if it is

/*               false - otherwise

/*

/****************************************************************************/

static bool IsRssTagName(const char *TagName)

{

   CString      LowerName = TagName;

   int          Pos;

 

   LowerName.MakeLower();

   Pos = LowerName.ReverseFind(':');

 

   if (Pos >= 0)

      return strcmp(LowerName.Right((int) strlen(LowerName) - Pos - 1), "rss") == 0;

 

   return strcmp(LowerName, "rss") == 0;

}

 

/****************************************************************************/

/*

/* DESCRIPTION : Update RSS 1.0 feed.

/*

/* RETURN VALUE: true - if OK

/*               false - if error

/*

/****************************************************************************/

static bool UpdateRss10Feed(RssFeedC *Feed, IXMLDOMNode *FeedNode)

{

   IXMLDOMNodeList *ItemNodes;

   IXMLDOMNode *ChannelNode;

   IXMLDOMNode *TitleNode;

   IXMLDOMNode *LinkNode;

   IXMLDOMNode *DescriptionNode;

   IXMLDOMNode *ItemNode;

   IXMLDOMNode *DateNode;

   RssItemC    *Item;

   long         Index;

   long         Length;

   HRESULT      Result;

 

   ChannelNode = SelectXmlNode(FeedNode, "child::rss:channel[position()=1]");

   if (!ChannelNode)

      return false;

 

   TitleNode = SelectXmlNode(ChannelNode, "child::rss:title[position()=1]");

   if (TitleNode)

   {

      Feed->SetTitle(GetXmlNodeText(TitleNode).c_str());

      TitleNode->Release();

   }

 

   LinkNode = SelectXmlNode(ChannelNode, "child::rss:link[position()=1]");

   if (LinkNode)

   {

      Feed->SetLink(GetXmlNodeText(LinkNode).c_str());

      LinkNode->Release();

   }

 

   DescriptionNode = SelectXmlNode(ChannelNode, "child::rss:description[position()=1]");

   if (DescriptionNode)

   {

      Feed->SetDescription(GetXmlNodeText(DescriptionNode).c_str());

      DescriptionNode->Release();

   }

 

   ItemNodes = SelectXmlNodes(FeedNode, "child::rss:item", &Length);

   if (ItemNodes)

   {

      for (Index = 0; Index < Length; Index++)

      {

         ItemNode = NULL;

 

         Result = ItemNodes->get_item(Index, &ItemNode);

         if (FAILED(Result) || !ItemNode)

            continue;

 

         TitleNode = SelectXmlNode(ItemNode, "child::rss:title[position()=1]");

         if (!TitleNode)

         {

            ItemNode->Release();

            continue;

         }

 

         if (GetXmlNodeText(TitleNode).empty())

         {

            TitleNode->Release();

            continue;

         }

 

         Item = Feed->AddItem(NormalizeText(GetXmlNodeText(TitleNode)).c_str());

         TitleNode->Release();

 

         LinkNode = SelectXmlNode(ItemNode, "child::rss:link[position()=1]");

         if (LinkNode)

         {

            Item->SetLink(GetXmlNodeText(LinkNode).c_str());

            LinkNode->Release();

         }

 

         DescriptionNode = SelectXmlNode(ItemNode, "child::rss:description[position()=1]");

         if (DescriptionNode)

         {

            if (GetXmlNodeText(DescriptionNode).empty())

               Item->SetDescription(Item->GetTitle());

            else

               Item->SetDescription(GetXmlNodeText(DescriptionNode).c_str());

            DescriptionNode->Release();

         }

         else

         {

            Item->SetDescription(Item->GetTitle());

         }

 

         DateNode = SelectXmlNode(ItemNode, "child::dc:date[position()=1]");

         if (DateNode)

         {

            Item->SetDate(GetXmlNodeText(DateNode).c_str());

            DateNode->Release();

         }

 

         ItemNode->Release();

      }

 

      ItemNodes->Release();

   }

 

   ChannelNode->Release();

 

   return true;

}

 

/****************************************************************************/

/*

/* DESCRIPTION : Update RSS 2.0 feed.

/*

/* RETURN VALUE: true - if OK

/*               false - if error

/*

/****************************************************************************/

static bool UpdateRss20Feed(RssFeedC *Feed, IXMLDOMNode *FeedNode)

{

   IXMLDOMNodeList *ItemNodes;

   IXMLDOMNode *ChannelNode;

   IXMLDOMNode *TitleNode;

   IXMLDOMNode *LinkNode;

   IXMLDOMNode *DescriptionNode;

   IXMLDOMNode *ItemNode;

   IXMLDOMNode *DateNode;

   RssItemC    *Item;

   long         Index;

   long         Length;

   HRESULT      Result;

 

   ChannelNode = SelectXmlNode(FeedNode, "child::channel[position()=1]");

   if (!ChannelNode)

      return false;

 

   TitleNode = SelectXmlNode(ChannelNode, "child::title[position()=1]");

   if (TitleNode)

   {

      Feed->SetTitle(GetXmlNodeText(TitleNode).c_str());

      TitleNode->Release();

   }

 

   LinkNode = SelectXmlNode(ChannelNode, "child::link[position()=1]");

   if (LinkNode)

   {

      Feed->SetLink(GetXmlNodeText(LinkNode).c_str());

      LinkNode->Release();

   }

 

   DescriptionNode = SelectXmlNode(ChannelNode, "child::description[position()=1]");

   if (DescriptionNode)

   {

      Feed->SetDescription(GetXmlNodeText(DescriptionNode).c_str());

      DescriptionNode->Release();

   }

 

   ItemNodes = SelectXmlNodes(ChannelNode, "child::item", &Length);

   if (ItemNodes)

   {

      for (Index = 0; Index < Length; Index++)

      {

         ItemNode = NULL;

 

         Result = ItemNodes->get_item(Index, &ItemNode);

         if (FAILED(Result) || !ItemNode)

            continue;

 

         TitleNode = SelectXmlNode(ItemNode, "child::title[position()=1]");

         if (!TitleNode)

         {

            ItemNode->Release();

            continue;

         }

 

         if (GetXmlNodeText(TitleNode).empty())

         {

            ItemNode->Release();

            TitleNode->Release();

            continue;

         }

 

         Item = Feed->AddItem(GetXmlNodeText(TitleNode).c_str());

         TitleNode->Release();

 

         LinkNode = SelectXmlNode(ItemNode, "child::link[position()=1]");

         if (LinkNode)

         {

            Item->SetLink(GetXmlNodeText(LinkNode).c_str());

            LinkNode->Release();

         }

 

         DescriptionNode = SelectXmlNode(ItemNode, "child::description[position()=1]");

         if (DescriptionNode)

         {

            if (GetXmlNodeText(DescriptionNode).empty())

               Item->SetDescription(Item->GetTitle());

            else

               Item->SetDescription(GetXmlNodeText(DescriptionNode).c_str());

            DescriptionNode->Release();

         }

         else

         {

            Item->SetDescription(Item->GetTitle());

         }

 

         DateNode = SelectXmlNode(ItemNode, "child::pubDate[position()=1]");

         if (DateNode)

         {

            Item->SetDate(GetXmlNodeText(DateNode).c_str());

            DateNode->Release();

         }

 

         ItemNode->Release();

      }

 

      ItemNodes->Release();

   }

 

   ChannelNode->Release();

 

   return true;

}





Source Files
   Commands.cpp
   Context.cpp
   CreatePath.cpp
   DateParser.cpp
   DlgEditFeedC.cpp
   DlgManageFeedsC.cpp
   Hook.cpp
   Iso8601.cpp
   MsXmlMisc.cpp
   MsXmlSelect.cpp
   RegistryNotify.cpp
   RegistryUtil.cpp
   RSS.cpp
   RSS.def
   RSS.idl
   RssAction.cpp
   RssDownloader.cpp
   RssFeed.cpp
   RssHelpers.cpp
   RssInit.cpp
   RssItem.cpp
   RssMultiFeed.cpp
   RssTimer.cpp
   RssXml.cpp
   StdAfx.cpp

Header Files
   Commands.h
   ContextC.h
   DateParser.h
   DlgEditFeedC.h
   DlgManageFeedsC.h
   Helper.h
   HookC.h
   RegistryNotify.h
   RegistryNotifyC.h
   Resource.h
   RssDownloaderC.h
   RssFeedC.h
   RssHelpers.h
   RssItemC.h
   RssMultiFeedC.h
   StdAfx.h
   ThreadObject.h
   XmlHelpers.h

Resource Files
   about.htm
   DiodiaLogoSmall.gif
   logo.bmp
   manifest.xml
   read.bmp
   RSS.rc
   RSS.rgs
   ToolBandLayout.xml
 

© 2002-2008 Diodia Software