本篇开始具体分析涨姿势UWP这个APP的代码,首先从数据的源头着手,即RSS feed的获取和解析,相关的类为RssReader,所有和数据相关的操作均放在里面。

  涨姿势网站提供的RSS feed地址为http://www.zhangzishi.cc/feed,在UWP中想要通过发送http request并从URI接受http response,最简单的方式就是使用HttpClient:

        public async Task<string> DownloadRssString()
{
var httpClient = new HttpClient();
var result = await httpClient.GetStringAsync(new Uri("http://www.zhangzishi.cc/feed"));
return result;
}

  通过上面这个方法,我们会获取到最新的涨姿势的数据源,并且是以XML格式组织的。头部是一些命名空间的定义,接下来的channel节点定义了一些title,description等信息,这里比较重要的是lastBuildDate,因为后面我们会根据这个字段来判断是否有新数据需要保存到本地,并刷姿势新闻列表。

<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
<channel>
<title>涨姿势</title>
<atom:link href="http://www.zhangzishi.cc/feed" rel="self" type="application/rss+xml" />
<link>http://www.zhangzishi.cc</link>
<description>骚年,来这里涨点姿势吧!</description>
<lastBuildDate>Sun, 17 Jul 2016 04:37:46 +0800</lastBuildDate>
</channel>
</rss>

  APP核心的新闻内容对应数据源中Item节点,每一个Item就对应一条涨姿势的新闻。整个XML文件中会存在几十个Item节点。对Item节点进行解析后,我们会创建一个Item对象的集合,映射到UI界面的ListView上,同时也要分析并保存每一个Item节点的详细信息,在用户点击ListView的具体ListViewItem时,打开详细页面填充内容。比如下图右侧的详细内容较为简单,仅仅是一副图片。

  

  我们来看一个Item节点的Sample:

    <item>
<title>日本某高校一男生在女生生日派对上公开表白,青春真好</title>
<link>http://www.zhangzishi.cc/20160717zh.html</link>
<comments>http://www.zhangzishi.cc/20160717zh.html#comments</comments>
<pubDate>Sun, 17 Jul 2016 04:37:46 +0800</pubDate>
<dc:creator><![CDATA[丁丁]]></dc:creator>
<category><![CDATA[世界观]]></category>
<guid isPermaLink="false">http://www.zhangzishi.cc/?p=178981</guid>
<description><![CDATA[日本某高校一男生在女生生日派对上公开表白。“在这个世界上我最喜欢的人是你,我会好好珍惜你的。”看得本公举全程一 […]]]></description>
<content:encoded>
<![CDATA[<p style="color: #444444;">日本某高校一男生在女生生日派对上公开表白。“在这个世界上我最喜欢的人是你,我会好好珍惜你的。”看得本公举全程一直傻笑,青春真好啊~</p>
<p><embed width="480" height="480" type="application/x-shockwave-flash" src="http://video.weibo.com/player/1034:7e3df996c2f5e9a1973974f0bb9e5e39/v.swf" allowscriptaccess="always" allowfullscreen="allowfullscreen" wmode="transparent" quality="high"></embed></p>
<p>视频链接:<a style="color: #428bca;" href="http://weibo.com/p/2304447e3df996c2f5e9a1973974f0bb9e5e39" target="_blank">http://weibo.com/p/2304447e3df996c2f5e9a1973974f0bb9e5e39</a><img src="http://cdnjp.zhangzishi.cc/wp-content/uploads/2016/05/024045ftw.jpg" alt="" class="alignnone size-medium wp-image-171793" /></p>
<p>微信订阅号 zhangzishi_weixin 合作请直接联系 tintin@zhangzishi.cc</p>
]]>
</content:encoded>
<wfw:commentRss>http://www.zhangzishi.cc/20160717zh.html/feed</wfw:commentRss>
<slash:comments>12</slash:comments>
</item>

  很容易就能分析出title,pubDate,description,category这些内容,我们会建立对应的Model对象来存储相关信息。同时我们也发现,详细内容放置在<content:encoded>节点,并加了<![CDATA[>>标签,包含在标签中的内容会被XML的解析器忽略,当作一般文本处理。所以你会看见content节点中包含了大量的HTML标签,这些HTML的内容会被作为整体的字符串存储在Item对象的ContentEncoded属性中。

    public class Item
{
public string Title { get; set; }
public Uri Link { get; set; }
public DateTime PublishedDate { get; set; }
public string Creator { get; set; }
public string Category { get; set; }
public string Description { get; set; }
public string ContentEncoded { get; set; }
public string CoverImageUri { get; set; }
}

  XML文件的处理,我这里选择来System.Xml.Linq命名空间下的XDocument类来处理。在获取rss这个根的XElement后,在channel节点找到Item节点的集合,对Item进行解析:

        private Item ParseItemNode(XElement itemNode)
{
var item = new Item();
item.Title = itemNode.Element("title").Value;
string uriString = itemNode.Element("link").Value;
if (string.IsNullOrEmpty(uriString) == false)
{
item.Link = new Uri(uriString);
}
item.PublishedDate = DateTime.Parse(itemNode.Element("pubDate").Value); XNamespace dc = XmlNameSpaceDic["dc"];
item.Creator = itemNode.Element(dc + "creator").Value;
item.Category = itemNode.Element("category").Value;
item.Description = itemNode.Element("description").Value;
XNamespace content = XmlNameSpaceDic["content"];
var contentEncoded = itemNode.Element(content + "encoded").Value; var allImageUri = GetAllImageUri(ref contentEncoded);
item.CoverImageUri = allImageUri.FirstOrDefault();
item.ContentEncoded = RemoveEmbedFlash(contentEncoded);
return item;
}

  这里稍微值得注意的是部分节点存在命名空间,在通过Element方法取值的时候,需要加上对应的命名空间才能成功。这里附上一个获取XML文件头部定义的命名空间的方法:

        private Dictionary<string, string> GetXmlNameSpaceDic(XElement rssNode)
{
var dic = new Dictionary<string, string>();
foreach (var attribute in rssNode.Attributes().Where(_ => _.IsNamespaceDeclaration))
{
dic.Add(attribute.Name.LocalName,attribute.Value);
} return dic;
}

  ParseItemNode方法中还做了一件特殊的事情,是去去正文中的图片地址,因为rss feed没有提供每条新闻的封面图片,我这里就通过正则表达式将正文的图片地址筛选出来,以第一张图片作为新闻的封面。正则表达式匹配项中有一个Group的概念,可以很好的选出img节点中的src属性,EditImageUri这个方法是为了给图片加上width和height更好的适应不同尺寸的屏幕:

        private List<string> GetAllImageUri(ref string content)
{
var matchList = new List<string>();
string pattern = "<img.+?src=[\"'](.+?)[\"'].*?>"; var regex = new Regex(pattern, RegexOptions.IgnoreCase);
foreach (Match match in regex.Matches(content))
{
var uri = EditImageUri(match.Value);
if (uri != match.Value)
{
matchList.Add(match.Groups[].Value);
content = content.Replace(match.Value, uri);
}
} return matchList;
}

  大体上RssReader这个类就分析完了,具体的代码有兴趣请去GitHub上查看,如果发现了bug还望不吝赐教,帮我提个pull request,万分感激。

  其实这个涨姿势UWP的APP属于闹着玩,网易云阅读WP版太简陋,看起来限制太多,思来想去自己动手丰衣足食,后面还会进一步补充功能,毕竟现在这个版本我用起来也不满意。

  GitHub:

https://github.com/manupstairs/ZhangZiShiRSSRead

  Windows Store:

https://www.microsoft.com/zh-cn/store/p/%e6%b6%a8%e5%a7%bf%e5%8a%bfuwp/9nblggh3zqd1

[UWP]涨姿势UWP源码——RSS feed的获取和解析的更多相关文章

  1. [UWP]涨姿势UWP源码——IsolatedStorage

    前一篇涨姿势UWP源码分析从数据源着手,解释了RSS feed的获取和解析,本篇则会就数据源的保存和读取进行举例. 和之前的Windows Runtime一样,UWP采用IsolatedStorage ...

  2. Spring源码情操陶冶-自定义节点的解析

    本文承接前文Spring源码情操陶冶-DefaultBeanDefinitionDocumentReader#parseBeanDefinitions,特开辟出一块新地来啃啃这块有意思的骨头 自定义节 ...

  3. Spring源码情操陶冶-ComponentScanBeanDefinitionParser文件扫描解析器

    承接前文Spring源码情操陶冶-自定义节点的解析,本文讲述spring通过context:component-scan节点干了什么事 ComponentScanBeanDefinitionParse ...

  4. Spring源码情操陶冶-AnnotationConfigBeanDefinitionParser注解配置解析器

    本文承接前文Spring源码情操陶冶-自定义节点的解析,分析spring中的context:annotation-config节点如何被解析 源码概览 对BeanDefinitionParser接口的 ...

  5. Spring源码情操陶冶-PropertyPlaceholderBeanDefinitionParser注解配置解析器

    本文针对spring配置的context:property-placeholder作下简单的分析,承接前文Spring源码情操陶冶-自定义节点的解析 spring配置文件应用 <context: ...

  6. Uboot中start.S源码的指令级的详尽解析

    Uboot中start.S源码的指令级的详尽解析 https://www.crifan.com/files/doc/docbook/uboot_starts_analysis/release/html ...

  7. spring IoC源码分析 (3)Resource解析

    引自 spring IoC源码分析 (3)Resource解析 定义好了Resource之后,看到XmlFactoryBean的构造函数 public XmlBeanFactory(Resource  ...

  8. [UWP]涨姿势UWP源码——极简的RSS阅读器

    涨姿势UWP,一个开源的RSS阅读器,一个纯粹的项目,一个有道德的APP,一个脱离了低级趣味的作者,一些有益于人民的代码.骚年,还等什么,来涨点姿势吧! 该项目代码可能会引起部分人群的不适,敏感人群请 ...

  9. [UWP]涨姿势UWP源码——Unit Test

    之前我们讨论了涨姿势UWP的RSS数据源获取,以及作为文件存储到本地,再将数据转化成Model对象.这部分非UI的内容非常适合添加Unit Test.不涉及UI的话,UT写起来简单高效,很是值得投入一 ...

随机推荐

  1. Python札记 -- 切片赋值

    一.疑惑    今天在看<Python Cookbook>第四章Python技巧的4.7小节时,发现一段初看起来让人疑惑的代码.该小节的任务是将一个包含列表(行)的列表,转换成一个新的列表 ...

  2. 【WEB】Tomcat基础使用知识

    由于当前项目性质原因,从开始到现在使用的WEB服务器都是WAS,而Tomcat的基础知识也慢慢地被遗忘.由于种种原因,让我参与到了另外一个全新的项目,使用的是Tomcat6.X,所以复习是必须的,而写 ...

  3. git版本管理策略及相关技巧(A)

    公司几乎所有的项目都是使用 git 仓库来管理代码,以前对 git 只有些肤浅的了解,每次提交代码或者上线的时候总是会提心吊胆,生怕出现一些未知的问题.经过三个月的踩坑和填坑, git 操作颇显成熟. ...

  4. [.net 面向对象编程基础] (10) 类的成员(字段、属性、方法)

    [.net 面向对象编程基础] (10) 类的成员(字段.属性.方法) 前面定义的Person的类,里面的成员包括:字段.属性.方法.事件等,此外,前面说的嵌套类也是类的成员. a.类的成员为分:静态 ...

  5. windows 8.1 试用感受:蛋疼感大幅降低

    众所周知windows 8 的最大使用感受就是蛋疼. 无论是微软MVP,还是我这样的万年不悔微软小白鼠,普通用户,小白用户,或多或少的都对这款操作系统感到蛋疼. 槽点太多,以至于大家都懒得批判了.好在 ...

  6. Windows上帝模式,上帝应该就是这样使用Windows的

    Windows上帝模式(Windows Master Control Panel)由来已久,最早是从Win7优化大湿里看到的一个选项,开启后在桌面生成一个图标,点进去后里面包含了几乎全部Windows ...

  7. Linux grep与正则表达式

    grep命令         格式:grep [-acinv] [--color=auto] '查找字符串' filename -a 将binary文件以text文件的 -c 计算找到 ‘查找字符串’ ...

  8. 知方可补不足~UPDLOCK更新锁的使用

    回到目录 对于高并发的场合下,使用UPDLOCK可以有效的控制并发更新的问题,即当一个线程在进行with(UPDLOCK)并进行update时,另一个线程将被阻塞,它会等第一个线程更新结束后,才可以进 ...

  9. 我所了解的chrome

    Chrome的隐身模式 先来说说隐身模式的启用方法吧 1.键盘快捷:Ctrl + Shift + N. 2.在Windows7下的任务栏处,右击“Chrome”图标,会出一个下拉菜单,点击“新建隐身窗 ...

  10. [Spring框架]Spring IOC的原理及详解。

    这里感谢 CSDN 的原博客:http://blog.csdn.net/m13666368773/article/details/7802126 看后  受益匪浅,这里再重温一遍Spring IOC ...