我是 writing a Stack Overflow API wrapper , 目前在 http://soapidotnet.googlecode.com/ .我有几个关于解析 SO RSS 提要的问题。
我已选择使用 RSS.NET 来解析 RSS,但我对我的代码有一些疑问(我已在本文中进一步提供)。
我的问题:
首先,我是否正确解析了这些属性?我有一个名为 Question 的类,它具有这些属性。
接下来,我如何解析 <re:rank>
RSS 属性(用于# of votes)?我不确定 RSS.NET 如何让我们做到这一点。据我了解,它是一个具有自定义命名空间的元素。
最后,我是否必须手动添加所有属性,就像目前在我的代码中一样?它们是我可以使用的某种反序列化吗?
代码:
下面是我当前用于解析最近问题提要的代码:
/// <summary>
/// Utilises recent question feeds to obtain recently updated questions on a certain site.
/// </summary>
/// <param name="site">Trilogy site in question.</param>
/// <returns>A list of objects of type Question, which represents the recent questions on a trilogy site.</returns>
public static List<Question> GetRecentQuestions(TrilogySite site)
{
List<Question> RecentQuestions = new List<Question>();
RssFeed feed = RssFeed.Load(string.Format("http://{0}.com/feeds",GetSiteUrl(site)));
RssChannel channel = (RssChannel)feed.Channels[0];
foreach (RssItem item in channel.Items)
{
Question toadd = new Question();
foreach(RssCategory cat in item.Categories)
{
toadd.Categories.Add(cat.Name);
}
toadd.Author = item.Author;
toadd.CreatedDate = ConvertToUnixTimestamp(item.PubDate).ToString();
toadd.Id = item.Link.Url.ToString();
toadd.Link = item.Link.Url.ToString();
toadd.Summary = item.Description;
//TODO: OTHER PROPERTIES
RecentQuestions.Add(toadd);
}
return RecentQuestions;
}
这是 SO RSS 提要的代码:
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:re="http://purl.org/atompub/rank/1.0">
<title type="text">Top Questions - Stack Overflow</title>
<link rel="self" href="http://stackoverflow.com/feeds" type="application/atom+xml" />
<link rel="alternate" href="http://stackoverflow.com/questions" type="text/html" />
<subtitle>most recent 30 from stackoverflow.com</subtitle>
<updated>2009-11-28T19:26:49Z</updated>
<id>http://stackoverflow.com/feeds</id>
<creativeCommons:license>http://www.creativecommons.org/licenses/by-nc/2.5/rdf</creativeCommons:license>
<entry>
<id>http://stackoverflow.com/questions/1813483/averaging-angles-again</id>
<re:rank scheme="http://stackoverflow.com">0</re:rank>
<title type="text">Averaging angles... Again</title>
<category scheme="http://stackoverflow.com/feeds/tags" term="algorithm"/><category scheme="http://stackoverflow.com/feeds/tags" term="math"/><category scheme="http://stackoverflow.com/feeds/tags" term="geometry"/><category scheme="http://stackoverflow.com/feeds/tags" term="calculation"/>
<author><name>Lior Kogan</name></author>
<link rel="alternate" href="http://stackoverflow.com/questions/1813483/averaging-angles-again" />
<published>2009-11-28T19:19:13Z</published>
<updated>2009-11-28T19:26:39Z</updated>
<summary type="html">
<p>I want to calculate the average of a set of angles.</p>
<p>I know it has been discussed before (several times). The accepted answer was <strong>Compute unit vectors from the angles and take the angle of their average</strong>.</p>
<p>However this answer defines the average in a non intuitive way. The average of 0, 0 and 90 will be <strong>atan( (sin(0)+sin(0)+sin(90)) / (cos(0)+cos(0)+cos(90)) ) = atan(1/2)= 26.56 deg</strong> </p>
<p>I would expect the average of 0, 0 and 90 to be 30 degrees.</p>
<p>So I think it is fair to ask the question again: How would you calculate the average, so such examples will give the intuitive expected answer.</p>
</summary>
</entry>
等等
这是我的问题类,如果有帮助的话:
/// <summary>
/// Represents a question.
/// </summary>
public class Question : Post //TODO: Have Question and Answer derive from Post
{
/// <summary>
/// # of favorites.
/// </summary>
public double FavCount { get; set; }
/// <summary>
/// # of answers.
/// </summary>
public double AnswerCount { get; set; }
/// <summary>
/// Tags.
/// </summary>
public string Tags { get; set; }
}
/// <summary>
/// Represents a post on Stack Overflow (question, answer, or comment).
/// </summary>
public class Post
{
/// <summary>
/// Id (link)
/// </summary>
public string Id { get; set; }
/// <summary>
/// Number of votes.
/// </summary>
public double VoteCount { get; set; }
/// <summary>
/// Number of views.
/// </summary>
public double ViewCount { get; set; }
/// <summary>
/// Title.
/// </summary>
public string Title { get; set; }
/// <summary>
/// Created date of the post (expressed as a Unix timestamp)
/// </summary>
public string CreatedDate
{
get
{
return CreatedDate;
}
set
{
CreatedDate = value;
dtCreatedDate = StackOverflow.ConvertFromUnixTimestamp(StackOverflow.ExtractTimestampFromJsonTime(value));
}
}
/// <summary>
/// Created date of the post (expressed as a DateTime)
/// </summary>
public DateTime dtCreatedDate { get; set; }
/// <summary>
/// Last edit date of the post (expressed as a Unix timestamp)
/// </summary>
public string LastEditDate
{
get
{
return LastEditDate;
}
set
{
LastEditDate = value;
dtLastEditDate = StackOverflow.ConvertFromUnixTimestamp(StackOverflow.ExtractTimestampFromJsonTime(value));
}
}
/// <summary>
/// Last edit date of the post (expressed as a DateTime)
/// </summary>
public DateTime dtLastEditDate { get; set; }
/// <summary>
/// Author of the post.
/// </summary>
public string Author { get; set; }
/// <summary>
/// HTML of the post.
/// </summary>
public string Summary { get; set; }
/// <summary>
/// URL of the post.
/// </summary>
public string Link { get; set; }
/// <summary>
/// RSS Categories (or tags) of the post.
/// </summary>
public List<string> Categories { get; set; }
}
提前致谢! 顺便说一句,请为图书馆项目做出贡献! :)
最佳答案
首先,我从未使用过 RSS.NET,但我想知道您是否意识到 .NET 框架在 System.ServiceModel.Syncidation
命名空间中拥有自己的 RSS api。 SyndicationFeed
类是这方面的起点。
为了解决您的问题,我编写了一个小示例,该示例采用该问题的提要并写出标题、作者、id 和 rank(您感兴趣的扩展元素)到控制台。这应该有助于向您展示此 API 有多么简单以及如何访问排名。
// load the raw feed
using (var xmlr = XmlReader.Create("https://stackoverflow.com/feeds/question/1813559"))
{
// get the items within a feed
var feedItems = SyndicationFeed
.Load(xmlr)
.GetRss20Formatter()
.Feed
.Items;
// print out details about each item in the feed
foreach (var item in feedItems)
{
Console.WriteLine("Title: {0}", item.Title.Text);
Console.WriteLine("Author: {0}", item.Authors.First().Name);
Console.WriteLine("Id: {0}", item.Id);
// the extensions assume that there can be more than one value, so get
// the first or default value (default == 0)
int rank = item.ElementExtensions
.ReadElementExtensions<int>("rank", "http://purl.org/atompub/rank/1.0")
.FirstOrDefault();
Console.WriteLine("Rank: {0}", rank);
}
}
上面的代码导致以下内容被写入控制台...
Title: .NET/C#: Using RSS.NET with Stack Overflow Feeds: How To Handle Special Properties of RSS Items
Author: Maxim Z.
Id: .NET/C#: Using RSS.NET with Stack Overflow Feeds: How To Handle Special Properties of RSS Items?
Rank: 0
有关 SyndicationFeed 类的更多信息,请转到此处...
http://msdn.microsoft.com/en-us/library/system.servicemodel.syndication.syndicationfeed.aspx
有关从 RSS 提要读取和写入扩展值的一些示例,请转到此处...
http://msdn.microsoft.com/en-us/library/bb943475.aspx
关于创建您的 Question 实例,我不确定序列化是否可以快速取胜。我可能会像这样编写您的代码...
var questions = from item in feedItems
select
new Question
{
Title = item.Title.Text,
Author = item.Authors.First().Name,
Id = item.Id,
Rank = item.ElementExtensions.ReadElementExtensions<int>(
"rank", "http://purl.org/atompub/rank/1.0").FirstOrDefault()
};
...但它几乎在做同样的事情。
以上内容需要安装 .NET 3.5 库。以下不是,但需要 C# 3.5(它将创建面向 .NET 2.0 的程序集)
我建议您考虑一件事 - 不要创建自定义类型,而是为 SyndicationItem 类型编写扩展方法。如果您让您的用户处理 SyndicationType(一种受支持、理解、记录等的类型),但添加扩展方法以使访问 SO 特定属性更容易,那么您会让用户的生活更轻松,并且当您所以扩展不会做他们想做的事。因此,例如,如果您编写了这个扩展方法...
public static class SOExtensions
{
public static int Rank(this SyndicationItem item)
{
return item.ElementExtensions
.ReadElementExtensions<int>("rank", "http://purl.org/atompub/rank/1.0")
.FirstOrDefault();
}
}
...您可以像这样访问 SyndicationItem 的排名...
Console.WriteLine("Rank: {0}", item.Rank());
... 并且当 SO 将一些其他扩展属性添加到您未满足 API 用户需求的提要时,可以退回到查看 ElementExtensions 集合。
最后更新...
我没有使用过 Rss.NET 库,但我已经通读了在线文档。从这些文档的初步阅读来看,我建议没有一种方法可以获取您尝试访问的扩展元素(项目的等级)。如果 RSS.NET API 允许访问给定 RssItem 的 xml(我不确定是否允许),那么您可以使用扩展方法机制来扩充 RssItem 类。
我发现 SyndicationFeed API 非常强大并且很容易掌握,所以如果您可以选择使用 .NET 3.5,那么我会朝这个方向努力。
关于c# - .NET/C# : Using RSS. NET 与堆栈溢出源 : How To Handle Special Properties of RSS Items?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1813559/