Mapping WordPress RSS Feed
Hello,
We have a requirement to import a WordPress blog. I have setup a SF feed to read the WordPress RSS feed and import it as a SF blog post. Everything is working fine, except that the content of the actual blog is being mapped incorrectly.
The WordPress RSS has two nodes for each blog post:
<description> which contains the post summary and
<content:encoded> which contains the full post.
Right now, SF is mapping the <description> field to it's blog content field. I want to instead map it to the summary field, and map the <content:encoded> field to the SF blog content field.
I see the mapping options, can't seem to make sense of it. Thanks for the help.
Hi Amir,
You need to inherit RSSInboudPipe class and override virtual method ConvertToWraperObject, which is used when syndication items are being build.
An example how to replace an existing pipe can be found here:
http://www.sitefinity.com/devnet/kb/sitefinity-4-x/page-re-indexing-issue-in-build-4-2-1650-0.aspx
Let us know if you find any difficulties with provided solution. Thanks!
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>
Milena,
Thank you, but really? I have to implement a whole custom module for simply wanting to map one field to another from the RSS? Seems a bit much. If that's the only way, then I guess I have to do it, but I figured with all the "mapping" options, there would be something simpler. Thank you.
Hello Amir,
A custom module is just a possible option.
You can replace the pipe at Global.asax ASP.NET application file for example.
Let me know if you find any difficulties! Thanks!
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>
Milena,
Are you able to provide an example the most efficient way to achieve the scenario I've described? Thank you.
Hi Amir,
Here are concrete 3 steps that need to be done in order to implement custom rss pipe:
1) Inherit RSSInboundPipe and override method ConvertToWraperObject. Here you need to set values of contentText and summaryText from your WordPress RSS.
public
class
RSSInboundPipeCustom : RSSInboundPipe
public
override
Telerik.Sitefinity.Publishing.WrapperObject ConvertToWraperObject(System.ServiceModel.Syndication.SyndicationItem item)
WrapperObject obj =
new
WrapperObject(
null
);
obj.MappingSettings =
this
.PipeSettings.Mappings;
obj.Language =
this
.PipeSettings.LanguageIds.FirstOrDefault();
var feedItem = item
as
SyndicationItem;
obj.AddProperty(PublishingConstants.FieldTitle, feedItem.Title.Text);
obj.AddProperty(PublishingConstants.FieldPublicationDate, feedItem.PublishDate.UtcDateTime);
string
contentText =
null
;
//RSS items don't have expiration
string
summaryText =
null
;
// TODO: Grab <content:encoded> which contains the full post and set it to contentText variable
if
(feedItem.Content !=
null
)
var content = feedItem.Content
as
TextSyndicationContent;
if
(content !=
null
)
contentText = content.Text;
// TODO: Grab <description> which contains the post summary and set it to summaryText variable
if
(feedItem.Summary !=
null
)
summaryText = feedItem.Summary.Text;
obj.AddProperty(PublishingConstants.FieldContent, contentText);
obj.AddProperty(PublishingConstants.FieldSummary, summaryText);
string
backLink =
""
;
if
(feedItem.Links.Count > 0)
backLink = feedItem.Links[0].Uri.AbsoluteUri;
obj.AddProperty(PublishingConstants.FieldLink, backLink);
if
(feedItem.Authors.Count > 0)
var author = feedItem.Authors[0];
obj.AddProperty(PublishingConstants.FieldOwnerEmail, author.Email);
obj.AddProperty(PublishingConstants.FieldOwnerLastName, author.Name);
obj.AddProperty(PublishingConstants.FieldItemHash, GenerateItemHash(feedItem,
this
.RssPipeSettings.UrlName));
return
obj;
public
static
void
RegisterRSSInboundCustomPipe()
//Remove the default Rss inbound pipe
PublishingSystemFactory.UnregisterPipe(RSSInboundPipe.PipeName);
//This code will add the RSSInboundPipe to the registered pipes with the original inbound rss pipe name
//so when the publishing system try's to use the rss pipe will use the new one
PublishingSystemFactory.RegisterPipe(RSSInboundPipe.PipeName,
typeof
(RSSInboundPipeCustom));
protected
void
Application_Start(
object
sender, EventArgs e)
Bootstrapper.Initialized -= Bootstrapper_Initialized;
Bootstrapper.Initialized += Bootstrapper_Initialized;
protected
void
Bootstrapper_Initialized(
object
sender, Telerik.Sitefinity.Data.ExecutedEventArgs args)
RegisterRSSInboundCustomPipe();
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>
Is it possible to do this without code? The mapping options that are available when editing a feed source seem to imply that one could simply align one field from the source to a different destination field.
Hello Eric,
At the moment it is not possible to achieve this without code. You should inherit and replace the RssInbound pipe. I've found some sample code that shows how to retrieve the content:encoded property of the syndication item:
StringBuilder sb = new StringBuilder();
foreach (SyndicationElementExtension extension in item.ElementExtensions)
XElement ele = extension.GetObject<XElement>();
if (ele.Name.LocalName == "encoded" && ele.Name.Namespace.ToString().Contains("content"))
sb.Append(ele.Value + "<br/>");
Let me know if you have any difficulties with extending the rss inbound pipe.
How would I do this for a specific News provider? For example, let's say I have the OOTB News provider, and I have another one defined called ExternalNews. Now I want to override the OOTB RSSInboundPipe with my own, because I want to map things differently between the feed and the ExternalNews content type. For example, I'm going to parse the content of the feed to get an email address, which I want to set to a custom property of my ExternalNews content type.
Since the administration back end for Feeds and Notifications only allows me to choose a certain set of providers, how do I associate my customizes RSSInboundPipe with a different provider?
Thanks,
Mike
Hello Mike,
At the moment our RSS inbound pipes can work with one pipe at a time. This means that you will have to substitute the built in one as describe earlier in this post.
Kind regards,Sorry, I guess I wasn't clear.
I've already customized the inbound pipe, but how do I associate the outbound pipe with a specific provider? In the Admin back end, under feeds and notifications, I can choose News, but what if I have more than one type of news? It seems like the feeds and notifications configuration should let me specify. I don't want the RSS feed in my normal news, but rather in the special one I have created for it.
I guess I'm missing something fundamental. So, here's the basic conceptual model:
Inbound Pipe ==> Publishing Point ==> Content Outbound Pipe
Let's say I want to create a new custom ContentOutboundPipe, which I will then connect up with the content from my RSS feed. I know that I would create a new class, inherit from ContentOutboundPipe and then set up the outbound pipe to map to whatever fields I wanted.
But when I'm using a customized persistent outbound pipe, where/how do I set which provider I'm using? Lets say I created a special module using your modulebuilder. How do I point the data coming from my InboundRssCustomPipe to my custom ContentOutboundCustomPipe to this new module? I imagine it has something to do with PipeSettings, but I don't see any examples that do other than the default action in the Feeds and Notifications.
Thanks,
Mike
Hello Mike,
Thank you for the clarification. At the moment the UI does not support this. However you can do this through code. Lets say that I have registered a new news provider. Then I create a content insert pipe. Before I run the pipe to import content I can use the bellow code to set the provider name:
PublishingManager manager = PublishingManager.GetManager();
var bbcInboundPipeSettings = manager.GetPipeSettings().Where(p => p.PipeName ==
"ContentOutboundPipe"
).FirstOrDefault()
as
SitefinityContentPipeSettings;
if
(bbcInboundPipeSettings !=
null
)
bbcInboundPipeSettings.ProviderName =
"SecondaryProvider"
;
manager.SaveChanges();
Hi guys,
I'm using SF 7.1.How can I set custom field values? Like I have Category, Tags, Yes / No, and Image field.
I tried to set my custom fields like this but it didn't work.
obj.SetOrAddProperty(
"MyBooleanField"
,
true
);
var tags =
new
Collection<SyndicationCategory>();
var tagElements = item.ElementExtensions.Select(i => i.GetObject<XElement>()).Where(i => i.Name.LocalName ==
"tag"
);
if
(tagElements !=
null
)
foreach
(var tag
in
tagElements)
tags.Add(
new
SyndicationCategory(tag.Value));
obj.AddProperty(PublishingConstants.FieldTags, tags);