| Posted in Tech at 3:51 pm by Winters Mi 引用地址:http:///blog/archives/188.html XML大家都很熟悉,那也就不需要怎么解釋了。這里所說(shuō)的Rails指的就是目前正如火如荼發(fā)展的Ruby on Rails,因?yàn)樗姆奖憧旖?,越?lái)越多的人開(kāi)始對(duì)他進(jìn)行學(xué)習(xí)和研究。本篇的目的是為了介紹在使用RoR搭建網(wǎng)站時(shí)對(duì)XML的處理,例如RSS文件的生成等等。首先不得不對(duì)這個(gè)東西的整體大概介紹一下。Ruby是早年日本人寫(xiě)出來(lái)的一個(gè)解釋型語(yǔ)言,同Python、Perl非常相似,但是更為突出的一點(diǎn)就是他的OO特性,尤其在Rails中。語(yǔ)法其實(shí)也不是很難,我差不多花了兩天時(shí)間大致了解了整體的語(yǔ)法特性。整體來(lái)說(shuō)與Perl比較類(lèi)似(跟吉子討論之后總結(jié)出來(lái)的)。個(gè)人覺(jué)得比較難以理解和記憶的包括兩點(diǎn):一是$變量,類(lèi)似于Perl中的$變量,比如$!總是表示最近發(fā)生的錯(cuò)誤,$1表示正則表達(dá)式匹配的第一部分等等,因?yàn)閷?shí)在是很多,所以記憶起來(lái)確實(shí)還是比較頭疼的;第二是Block語(yǔ)法,Ruby中比較強(qiáng)大的一點(diǎn)也是這個(gè),即增強(qiáng)了對(duì)于容器迭代處理的本領(lǐng),拿Java的處理來(lái)做個(gè)比較,比如在Java1.4中對(duì)于一個(gè)列表的迭代處理可以是這樣的:
 
 for( int i = 0; i < list.size(); ++i) {
     String aString = (String)list.get(i);
     System.out.println(aString);
}在Java5.0中對(duì)于迭代也是加強(qiáng)了很多,可以這樣做:
 
 for(String aString: list) {
     System.out.println(aString);
}在Ruby中就可以這樣寫(xiě):
 
 list.each { |aString| puts aString}
其實(shí)看上去沒(méi)有什么特殊的,呵呵,不過(guò)玄機(jī)是在這個(gè)list.each里面,在實(shí)現(xiàn)中會(huì)用一個(gè)yield來(lái)呼喊跟在后面的Block對(duì)象,理解上也不是很困難,不過(guò)看一個(gè)例子:
 
 def fibUpTo(max)
     i1, i2 = 1, 1        # parallel assignment
     while i1 < = max
          yield i1
          i1, i2 = i2, i1+i2
     end
end
fibUpTo(500) { |f| print f, ‘ ‘ }
#1 1 2 3 5 8 13 21 34 55 89 144 233 377
這段敗家玩意是用來(lái)算菲波那切數(shù)列的,我頭一天幾乎就暈菜在這了,后來(lái)才慢慢明白。以上就是我所感覺(jué)Ruby中比較困難的一些地方。
 下面來(lái)說(shuō)說(shuō)Rails,呵呵
 
 Rails可以說(shuō)是一個(gè)很成功的MVC的框架,他的作者也在最近的OSCON大會(huì)上被Google、Yahoo等多個(gè)商家評(píng)為本年度最佳Hacker?,F(xiàn)在每天Rails的郵件列表大概我都會(huì)收到7、80封信。Rails用的最多的演示就是搭建Blog,我看了幾個(gè),感覺(jué)就是使用Rails基本上10分鐘左右就能搭建出一個(gè)雛形的Blog系統(tǒng),包括發(fā)貼、刪除、更新、Comment等等,讓人感覺(jué)確實(shí)非常的驚訝,初期Rails的學(xué)習(xí)曲線不是很平緩,因?yàn)槭褂肦ails建立一個(gè)工程,就像MFC一樣,編譯運(yùn)行,一個(gè)頁(yè)面就出來(lái)了,然后一堆目錄文件都擺在那里,根本不知道什么是什么,不過(guò)跟隨一個(gè)例子慢慢做,很快就能上手,然后多多利用Rails Wiki和Maillist,基本上都能找到答案。
 ok,進(jìn)入正題,Rails對(duì)于XML的操作。一般無(wú)非也就是兩種,創(chuàng)建XML,比如生成RSS文件,另一種就是解析,比如做個(gè)RSS閱讀器等等,那今天先來(lái)搞搞怎么生成XML,因?yàn)檫@個(gè)相對(duì)簡(jiǎn)單一些,:P(Rails的Wiki中有一部分內(nèi)容),我們也可以以RSS為例。希望大家是在對(duì)Rails有了一定了解之后,尤其是Rails的Views的概念之后可以來(lái)看看這個(gè),呵呵。
 XML其實(shí)跟HTML一樣都可以是Rails框架中的一個(gè)視圖,通過(guò)Controller來(lái)控制View的產(chǎn)生。一般來(lái)說(shuō)需要作的第一步就是把HTTP的協(xié)議頭改了,因?yàn)槲覀冎繦TML和XML的HTTP協(xié)議頭不是完全一樣的,非常簡(jiǎn)單,比如我們有一個(gè)RSS Controller,rss這個(gè)動(dòng)作是用來(lái)生成RSS XML的,簡(jiǎn)單的snippet如下:
 
 class RSSController < ApplicationController
   before_filter :set_xml_header
	
   # action to create rss xml file, but have to change
   # HTTP header before
   def rss
   end
	
   def set_xml_header
     @headers[‘Content-Type‘] = ‘text/xml; character=utf-8‘
   end
end
第二步就是要生成rss視圖的模板。在Rails中,模板是視圖不可缺少的一部分,模板也是直接展現(xiàn)給用戶的結(jié)果。一般的Rails模板都是rhtml文件,對(duì)于我們的例子,rss的模板需要是生成xml的,所以,就是rss.rxml。在Rails中,處理和使用rxml模板文件的工作是由Rxml Builder來(lái)完成的,就像他的項(xiàng)目介紹所說(shuō)的“Provide a simple way to create XML markup and data structures.”真的非常簡(jiǎn)單。
 比如,我們需要先生成xml的instruct行
 
 <?xml version=‘1.0‘ encoding=‘utf-8‘ ?>
在rxml文件中對(duì)應(yīng)的就是
 
 xml.instruct!
xml.instruct!用來(lái)控制產(chǎn)生xml中instruction,類(lèi)似于xml的頭等等,通過(guò)可變長(zhǎng)的參數(shù)可以改變改節(jié)點(diǎn)的屬性值;
 然后需要產(chǎn)生RSS的根節(jié)點(diǎn),比如我們使用RSS 2.0規(guī)范
 
 xml.rss, :version => ‘2.0‘,
               ‘xmlns:dc‘ => ‘http:///dc/elements/1.1/‘
上面的snippet顯示了如何生成節(jié)點(diǎn),并且包括了他的屬性,比如版本是2.0,使用dc的namespace,比如我們需要在RSS中支持dc:creator來(lái)標(biāo)明作者是誰(shuí)。那么又有一個(gè)問(wèn)題了,就是xml對(duì)于數(shù)據(jù)樹(shù)型結(jié)構(gòu)的描述,這點(diǎn)完全不是問(wèn)題,程序結(jié)構(gòu)同生成XML的結(jié)構(gòu)非常類(lèi)似,不象以前要寫(xiě)某某節(jié)點(diǎn)appendChild什么的,在Rails的rxml中,非常簡(jiǎn)單
 
 xml.rss, :version => ‘2.0‘,
               ‘xmlns:dc‘ => ‘http:///dc/elements/1.1/ do
      xml.channel ... do
          xml.title ...
          xml.link ...
          xml.item ... do
               xml.title ...
               ...
          end
      end
  end
從上面的框架直接生成了xml的樹(shù)型框架,完全用程序的嵌套特性完成了對(duì)于XML樹(shù)型數(shù)據(jù)結(jié)構(gòu)的構(gòu)造,簡(jiǎn)單吧。其實(shí)基本上上述就涵蓋了構(gòu)建XML文件的內(nèi)容了,不過(guò)我在做的時(shí)候遇到了一個(gè)問(wèn)題,就是節(jié)點(diǎn)的namespace,比如我們要建立一個(gè)節(jié)點(diǎn)dc:creator,或者rdf:resource等等,查了一下,因?yàn)?#8220;:”是Ruby的語(yǔ)法字符,不能向上面那么使用,所以rxml builder有一個(gè)方法,叫做xml.tag!,用來(lái)專(zhuān)門(mén)處理這個(gè),例如
 
 xml.tag! (‘SOAP:Envelope‘)
# produces <SOAP:Envelope>...</SOAP:Envelope>
Ruby中有很多有意思的函數(shù),比如isXXXX?,string.sub!,就是函數(shù)后面可以用?!這種來(lái)表示一定的含義,比如?就是表示布爾函數(shù),!一般表示對(duì)原對(duì)象的狀態(tài)或者數(shù)據(jù)會(huì)有修改甚至破壞可能的函數(shù),所以覺(jué)得這樣寫(xiě)比較ugly,于是接著找,找到了一句話
 
Direct support for XML namespaces is now available. If the first argument to a tag call is a symbol, it will be joined to the tag to produce a namespace:tag combination. It is easier to show this than describe it. 于是,現(xiàn)在就可以直接寫(xiě)成:
 xml.dc :creator, ‘Winters Mi‘
#produces <dc:creator>Winters Mi</dc:creator>
呵呵,這樣就比較好看了。
 今天就先到這里,后面會(huì)正確搞一搞解析XML的,據(jù)我所知,目前Ruby打包的XML解析器是rexml,曾經(jīng)試用過(guò),根Java也是沒(méi)有多大區(qū)別的,然后目前也有一個(gè)FeedTools,是專(zhuān)門(mén)支持Rails中對(duì)于RSS的解析的,目前主要版本的RSS都支持。學(xué)習(xí)Rails很快,作起來(lái)也很快,目前看比較適合概念展示用的原型系統(tǒng)等,大型的應(yīng)用還沒(méi)有看到,不過(guò)一些老外的網(wǎng)站也都開(kāi)始招RoR的開(kāi)發(fā)人員了。還是感覺(jué),如果有什么新的想法,可以很快用RoR搞一個(gè)出來(lái),也應(yīng)了Keso引用的那句話,要“早發(fā)布、常發(fā)布”,呵呵。  |