读取RDF格式的RSS文件

左直拳

 

RSS目前据说有3种格式:0.9X1.02.0。用得最多的是2.0。对于RSS2.0,没有什么难的,在C#里,采用

XmlDocument xml = new XmlDocument();

xml.LoadXml(xmlFile);

XmlNodeList nodes = xml.SelectNodes("/rss/channel/item");

就可以轻松获得里面的每一个节点。

但对于RDF格式(也许就是RSS1.0吧?RSS的定义很混乱,搞不清楚)就不行了。比如,现在有一个RSS,格式如下:

<?xml version="1.0" encoding="utf-8"?>

<?xml-stylesheet title="XSL_formatting"  type="text/xsl" href="/china/rss.xsl"           ?>

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:cc="http://web.resource.org/cc/" xmlns="http://purl.org/rss/1.0/">

……

  <item rdf:about="http://www.bbc.co.uk/go/wsy/pub/rss/1.0/-/china/learningenglish/takeawayenglish/tae/2007/01/070131_music_in_schools.shtml">

      <title xml:lang="zh-Hans">Music in Schools 校园音乐课程</title>

<link>http://www.bbc.co.uk/go/wsy/pub/rss/1.0/-/china/learningenglish/takeawayenglish/tae/2007/01/070131_music_in_schools.shtml</link>

      <description xml:lang="zh-Hans">Can you play a musical instrument? Learn all about British school music lessons in Take Away English. </description>

      <dc:date>2007-01-31T17:30:57+00:00</dc:date>

      <dc:format>text/plain</dc:format>

      <dc:language>zh-Hans</dc:language>

      <dc:publisher>http://www.bbcchina..com.cn</dc:publisher>

      <dc:creator>http://www.bbc.co.uk/china</dc:creator>

      <dc:type>Tae, Takeaway English</dc:type>

   </item>

<item>……</item>

<item>……</item>

……

</rdf:RDF>

对于这种格式,表面上看,也是XML嘛,可直接用上面的方式去读取就是不行,一个节点也拿不到。

开始以为是什么XPath写得不对,一会儿xml.SelectNodes("//RDF/item")不行,一会儿xml.SelectNodes("//rdf:RDF/item")也不行。

后来才知道,要指定命名空间。

留意一下RSS文件中的代码

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:cc="http://web.resource.org/cc/" xmlns="http://purl.org/rss/1.0/">

两个红色部分分别表示两个不同的命名空间。其中第二个(xmlns="http://purl.org/rss/1.0/")没有前缀,说明它是默认命名空间,则其所有子孙节点没有指定前缀的,都使用该命名空间。比如,<item>就属于默认命名空间,<dc:date>就属于命名空间dc

明白了这个道理,就可以写C#代码如下:

XmlNamespaceManager nsMgr = new XmlNamespaceManager(xml.NameTable);

nsMgr.AddNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");

nsMgr.AddNamespace("rss", "http://purl.org/rss/1.0/");

XmlNodeList nodes = xml.SelectNodes("/rdf:RDF/rss:item", nsMgr);

这样就可以获得节点<item>的集合了。

同理,要获得<Item>里面的子节点也应该要指定命名空间:

string link = nodes[i].SelectSingleNode("rss:link",nsMgr).InnerText