xml-通过 XML 发布新闻

发布日期: 10/26/2004 | 更新日期: 10/26/2004

Ted Roche

新的 RSS 新闻聚合频繁出现,这是因为越来越多的软件开发人员发现:无论是用于商业还是个人使用,该技术在 语言表达 方面确实有效。例如,一个程序员的网络日记可以为记录开发人员在最新项目或感兴趣的解决方案中感受到的喜悦或遇到的挑战提供一个很好的平台。在这篇 Ted Roche 4 月发表的 RSS 文章的续篇中,他展示了 Visual FoxPro 开发人员如何能够仅使用几个常用且功能强大的 VFP 命令来轻松地创建 RSS 聚合新闻。

*

在上个月有关 RSS 的文章中,我谈到了作为一个使用者来使用 RSS,手动读取和编写 RSS,订阅 RSS 聚合新闻以便在新闻阅读器中阅读,以及使用 blogging 软件发布 RSS。本文将探讨使用 Visual FoxPro 以编程方式生成 RSS。我将说明基本的格式,并讨论用 VFP 生成 RSS 的两种方法。

格式

RSS 的历史与很多特定标准类似,不同的团体获得绝对优势地位并声明其合理性,然后分裂并留下旧格式。实际上,现在有两种格式可以考虑:RSS 1.0 和 2.0。(第三个竞争者 Atom — 有争议,正如它的某些作者所坚持的,根本不是 RSS — 可能只是一种变体。它正处于早期开发阶段,目前的版本是 3.0,本文不会考虑它,但会对其加以关注。)

尽管有相似之处,RSS 1.0 和 RSS 2.0 仍然由两个对立的阵营所管理。如果您只能支持一个格式,那么 RSS 2.0 似乎是最简单且最普遍的。但是,RSS 1.0 具有更丰富的语法,并且对扩展基本结构的含义有更明确的定义。大多数工具对这两种格式都支持,并且正如我将展示的,在这两种格式中生成“公分母”输出并不是那么困难。

那么,什么是基础结构呢?一个 RSS 文档(也称为“聚合新闻”,因为它们很多都是新闻聚合)包含一个描述信息源(新闻“通道”)的标头和一个带有一篇或多篇文章、新闻头条、引用或者任何随附内容的正文。在 RSS 1.0 中,项是通道元素的同辈,它们在通道元素的 集合中列出。在 RSS 2.0 中,项本身作为子元素包含在通道元素内。上一篇文章展示了 RSS 2.0 的一个示例,由靠近顶部的 版本标记来区分。下面的代码展示了一个典型的 RSS 1.0 feed。请注意,整个文档都包括在 和 标记中。这表现了 RSS 1.0 文档的特性。

 1<rdf:rdf xmlns="http://purl.org/rss/1.0/" xmlns:admin="http://webns.net/mvcb/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/">
 2<channel rdf:about="http://www.tedroche.com" xmlns="">
 3<title>Ted Roche &amp; Associates, LLC Web 
 4    Site</title>
 5<link/>http://www.tedroche.com
 6           <description>Changes to the web site of Ted Roche
 7    &amp; Associates, LLC</description>
 8<dc:language>en-us</dc:language>
 9<dc:creator>
10</dc:creator>
11<dc:date>2004-01-07T16:55:48</dc:date>
12<admin:generatoragent rdf:resource="http://msdn.microsoft.com/vfoxpro"></admin:generatoragent>
13<admin:errorreportsto rdf:resource="mailto:[email protected]"></admin:errorreportsto>
14<items>
15<rdf:seq>
16<rdf:li rdf:resource="http://www.tedroche.com/ConfGrid#2003"></rdf:li>
17</rdf:seq>
18</items>
19</channel>
20<item rdf:about="http://www.tedroche.com/ConfGrid#2003" xmlns="">
21<title>New White Papers: VFP and RSS</title>
22<description><![CDATA[The first of my white papers
23    from 2003 conferences...]]></description>
24<link/>http://www.tedroche.com/ConfGrid#2003
25           <dc:creator>Unknown</dc:creator>
26<dc:date>2004-01-07T16:55:48</dc:date>
27</item>
28</rdf:rdf>

返回页首 返回页首

生成 RSS

生成 RSS 的方法有很多种。在上一篇文章中,我提到了 Notepad,它是一种粗糙但有效的工具。在这里,我将以两种不同的方法使用 VFP:textmerge 和 MSXML COM 对象。每种技术都有其优势和劣势。

VFP 技术的优势在于其速度和配置的简单性。Textmerge 在速度上占优势:由于所使用的所有对象都是原生 VFP 命令,其生成过程快如闪电。安装生成 RSS 的 VFP 应用程序只需要通常的运行库安装。与之相对,MSXML 对象必须在目标机器上安装和配置;在 Web 服务器上使用它时,我遇到了一些困难,而其他人也报告了类似的问题。原生 VFP 技术避免了这一点。(请注意,XMLToCursor 使用 MSXML COM 对象;如果您要寻求一种“纯粹”的 VFP 解决方案,那么也需要避免这一点。)

但是,VFP 没有任何原生功能来验证和操作 XML;因此,生成的聚合新闻可能不正确。最佳示例之一在上述代码块中:新闻聚合的标题是“Ted Roche & Associates,LLC Web Site”,and 字符需要“转义”为 _ & _ 格式,以防止分析错误。同样,大于号和小于号也要分别转换为 _ > _ 和 _ < _ 。

根据您为聚合新闻选择的字符集,其他字符也应该进行转义,以确保在目标系统上正确显示。除了字符集转换以外,使用 MSXML COM 对象还可以确保完成一些基本的验证。COM 对象将始终生成有效且格式规范的 XML。使用 Visual FoxPro 对象,您需要自己检查 XML。

为了简化本文中的技术解释,您可以假定数据来自两个游标:curHead 包含标题、说明以及通道(标头)元素所需的链接信息,curItem 包含每个新闻项的一个记录,并带有该文章的标题、链接和说明。

返回页首 返回页首

使用 FoxPro textmerge 生成 RSS

FoxPro textmerge 可以通过以下代码快速而有效地生成 XML,这段代码将生成一个 RSS 2.0 feed:

LOCAL lcXML as String, lcContents as String, lcFileName
STORE SPACE(0) TO lcXML, lcContents
#DEFINE CRLF CHR(13)+CHR(10)
lcFileName = "trweb.xml"
* Read header information
SELECT cTitle as Title, ;
  cLink as Link, ;
  mDesc as Description ;
FROM trhead ;
INTO CURSOR curHead
* Read news items
Select TOP 10 cTitle as Title, ;
  tUpdated as pubDate, ;
  mContent as Description, ;
  cLink as link ;
FROM trweb ;
ORDER BY tUpdated descending ;
INTO CURSOR curItem
* Generate the items - body'
SELECT curItem
SET textmerge TO memvar lcXML additive
SET TEXTMERGE ON noshow
SCAN
  \
1<item>
2      \<title>&lt;<htmlfix(curitem.title)>&gt;</htmlfix(curitem.title)></title>
3      \<description>&lt;<htmlfix(curitem.description)>&gt;</htmlfix(curitem.description)></description>
4      \<pubdate>&lt;<rfc822date(datetime())>&gt;</rfc822date(datetime())></pubdate>
5      \<link/>&lt;<htmlfix(curitem.link)>&gt;
6      \</htmlfix(curitem.link)></item>

ENDSCAN SET TEXTMERGE off SET TEXTMERGE to * Generate the heading and channel items and embed * the body within Set Textmerge To Memvar lcContents Set Textmerge On Noshow \

\

\

 1<rss version="2.0">
 2      \<channel>
 3      \  <title>&lt;<htmlfix(curhead.title)>&gt;</htmlfix(curhead.title)></title>
 4      \  <link/>&lt;<htmlfix(curhead.link)>&gt;
 5      \  <description>&lt;<htmlfix(curhead.description)>&gt;</htmlfix(curhead.description)></description>
 6      \  <language>en-us</language>
 7      \  <copyright>Copyright &lt;<year(date())>&gt;</year(date())></copyright>
 8      \  <lastbuilddate>&lt;<rfc822date(datetime())>&gt;</rfc822date(datetime())></lastbuilddate>
 9      \  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
10      \  <generator>&lt;<version()>&gt;</version()></generator>
11      \  <ttl>60</ttl>
12      \
13      \  &lt;<lcxml>&gt;
14      \
15      \</lcxml></htmlfix(curhead.link)></channel>
16      \</rss>

Set Textmerge Off Set Textmerge To * Write it out lcSafety = Set("Safety") Set Safety Off Strtofile(lcContents, lcFileName, 0) Set Safety &lcSafety FUNCTION HTMLFix(tcString) * This code ASSUMES the incoming string is ANSI, * CHR(32) to (127) and has not already had the * characters converted - it will make a mess of a * string that already has strings like — in it. LOCAL lcString as string lcString = STRTRAN(tcString,"&","&") lcString = STRTRAN(lcString,"<","<") lcString = STRTRAN(lcString,">",">") RETURN ALLTRIM(lcString)

下面看一下代码中发生了什么。curItems 游标包含名为“title”、“description”和“link”的字段,用于匹配 XML 主体所需的项。在源表中,这些字段被相应地命名为 cTitle、mDesc 和 cLink,但是它们被生成游标的 SQL SELECT 语句中的别名加以更改。在更多几个代码行中,项目列表是通过 scan 和 textmerge 生成的。然后,用 textmerge 生成主文档,从 curHead 游标取出值,并对其他值(如果您需要扩展该示例,也可以将这些值包含在 curHead 游标中)进行硬编码。最后,用 StrToFile() 写出文件。

RFC822Date() 函数是一个简单的 UDF,包含它是为了将所提供的 FoxPro datetime 值转换为 RSS 2.0 规范所需的 RFC 822 格式,如“Thu, 27 Feb 2003 14:11:12 GMT”。(RSS 1.0 规范要求一种由 ISO 8601 指定的不同格式,其格式为 YYYY-MM-DDTHH:MM:SSZ。)执行这两种转换所需的用户定义的函数包含在随附的下载资料中。字符串从其固定宽度的表长度中剪裁掉,并且 and 符号、大于号和小于号由 HTMLFix() UDF 中的等效字符替换。

用 Visual FoxPro 生成 RSS 聚合新闻快速而有效,并且使程序员能够控制写入磁盘的每个字节。作为交换条件,程序员必须确保格式完全正确,并且如果需要的话,还要确保进行字符转换。

返回页首 返回页首

使用 MSXML COM 对象生成 RSS

使用 XML 处理器(如 MSXML COM 对象)生成 RSS 在开始可能会有一点复杂和冗长,但它确实有某些优势。从面向对象的观点来说,使用 COM 对象会轻松一些或“更正确”吗?可能不会。任何方法都可以重新构建到适当的对象和方法集中。XML 分析器知道需要将文本值正确编码以生成有效的 XML,它还将自动执行编码,或引发您的代码必须处理的错误。但它不会生成无效的 XML,而 Visual FoxPro textmerge 模块却可以生成。

创建 XML 文档的细节相当简单:调用 MSXML COM 对象,然后告诉它创建一个新文档。此时,构建所需文档的过程包括:添加元素和属性,以及为它们指定值。如果您是 XML 的初学者,请注意,元素是用尖括号标记括起来的一个节点。每个元素都以一个开始标记(如 )开头,并以一个结束 标记结尾。属性是元素标记中的一个名-值对,它描述元素的属性。如果我将一个 xmlns 属性添加到项目标记中,它将变为 。以下代码演示了过程如何开始:它会创建一个 XML 文档,并添加最初的几个元素和属性。代码其余部分的重复性很高,它在下载资料中提供。

loXML = newobject('msxml2.domdocument.4.0')
loXml.async = .f.
* Create the XML root
loNewItem = loXML.CreateProcessingInstruction([xml], ;
           [version='1.0' encoding='iso-8859-1'])
loXML.appendChild(loNewItem)
* Create the RSS root element
loDocument = loXml.createElement('rss') 
loXML.appendChild(loDocument)
* Add the RSS Version number
loAttribute = loXML.createAttribute([version])
loAttribute.value="2.0"
loDocument.attributes.setNamedItem(loAttribute)
* Add the channel element
loElement = loXML.createElement("channel")
loChannel = loDocument.appendChild(loElement)

当 RSS 数据完全添加到 XML 分析器之后,通过从 loXML.XML 属性中提取字符串或调用内部的 loXML.Save() 方法,将数据保存到磁盘上。期间出现的错误可以用错误处理程序捕获,然后进行相应的处理(这是使用 VFP8 新的 TRY...CATCH 结构化错误处理程序的好地方)。由于我使用这些函数并不是业务必需的,因此只选择将错误记录到一个错误文件中,并退出生成过程。您的错误处理方式将反映您的需要。

返回页首 返回页首

小结

Visual FoxPro 是生成与处理 RSS 文档的极佳工具。由于 RSS 只是 XML,而 XML 只不过是文本,FoxPro 的内置文本操作功能可以使 RSS 的生成既快速又简单。由于 Visual FoxPro 还是 COM 对象的良好宿主,因此由 VFP 驱动的 XML 分析器是另一项适用的技术。您所作的选择取决于您的特定环境和应用程序需求。

返回页首 返回页首

参考资料

有关 RSS 的更多信息,请参阅 O'Reilly 丛书:由 Ben Hammersley 撰写的 Content Syndication with RSS ,由 Cory Doctorow 等人撰写的 Essential Blogging ,以及由 Shelley Powers 撰写的 Practical RDF 。O'Reilly 站点 ( www.oreilly.com ) 上有许多关于 RSS 的文章,尽管它们倾向于支持 1.0 版。 www.scripting.com 上的 Dave Winer 是 2.0 版的支持者。在 http://web.resource.org/rss/1.0http://blogs.law.harvard.edu/tech/rss 上分别查看 RSS 1.0 和 2.0 的规范。最后,当您认为已经生成了一个有效的聚合新闻后,请根据 www.feedvalidator.org 上的 RSS Feed Validator 对其进行检查。

下载 **** 405ROCHE.ZIP

返回页首 返回页首

提要栏:其他资源

感兴趣的 RSS 聚合新闻:

• |

Rick Strahl — 某些列在 www.west-wind.com

---|---
• |

FoxForum Wiki — www.tedroche.com/FoxWikiRSS/FoxWikiRSS20.xml

• |

FoxCentral.net — www.foxcentral.net/foxcentralRssFeed.fc

• |

Fox KB Updates — www.kbalterz.com/rss/fox.xml

网络日记:

• |

Garrett Fitzgerald — http://blog.donnael.com

---|---
• |

Andrew MacNeill — http://akselsoft.blogspot.com

• |

Ted Roche — http://radio.weblogs.com/0117767

• |

MS Data Team — http://blogs.msdn.com/vsdata

有关 FoxTalk 和 Pinnacle Publishing 的详细信息,请访问其网站 http://www.pinpub.com/

注:这不是 Microsoft Corporation 的网站。Microsoft 对该网站的内容不承担责任。

本文是从 FoxTalk 2004 年 5 月号转载的。版权所有 2004,Pinnacle Publishing, Inc.(除非另行说明)。保留所有权利。FoxTalk 是 Pinnacle Publishing, Inc. 独立发行的产品。未经 Pinnacle Publishing, Inc. 事先同意,不得以任何形式使用或复制本文的任何部分(评论文章中的简短引用除外)。要联系 Pinnacle Publishing, Inc.,请致电 1-800-788-1900。

转到原英文页面

Published At
Categories with Web编程
Tagged with
comments powered by Disqus