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