RUBY中對XML的文檔的解析可以使用這個庫REXML庫。
REXML庫是ruby的一個XML工具包,是使用純Ruby語言編寫的,遵守XML1.0規範。
在Ruby1.8版本及其以後,RUBY標準庫中將包含REXML。
REXML庫的路徑是: rexml/document
所有的方法和類都被封裝到一個REXML模組內。
所以使用的時候要先匯入rexml/document庫,然後把REXML模組展開到當前指令碼環境中,這樣使用REXML模組內的類就不用使用REXML::模組來引用REXML中的類了
require 'rexml/document'
include REXML
REXML有兩種方式訪問一個XML文檔,一種是樹方式,一種是流方式。
樹方式,與Javascript中的DOM方式類似,但是更加簡化,使用起來更加簡單快捷,以下就是樹方式解析XML文檔的介紹。
REXML模組裡面常用的類有以下幾個:
一 Document類
1 Document::new
Document類的構造方法,參數可以為一個xml檔案的路徑,或者一個IO對象,但必須保證該IO對象的流指標所指向的位置 到 流末尾 之間的內容,含有一篇合法的XML文檔。
2 Document#root
返回一個element類型的對象,是該xml的根項目
3 Document#version
返回當前xml文檔的版本資訊 從xml的首行中解析
如<?xml version="abcd"?>
那#version就返回'abcd',預設值是'1.0'
4 Document#encoding
返回當前xml文檔的編碼方式 同#version從xml首行讀取
如<?xml version="1.0" encode="GB2312"?>
需要注意的一個地方是,假如encode的內容是隨便輸入的,比如abc,那Documnet.new的時候,這篇xml文檔沒辦法解析。
二 Element Class
1 Element::new(arg = UNDEFINED,parent=nil,context=nil)
Element對象的建構函式。
arg:預設值是undefined,未定義,如果是一個字串的話,這個字串將做為這個元素的名稱,如果同樣也是一個element的話,會將該element複製過來,當然僅是淺層複製,也就是只複製該元素的名稱,屬性和命名空間。
parent:預設nil,是該元素的父元素。
context:預設nil。
2 Element#add_attribute( key, value = nil)
給該元素添加一個屬性,假如已經存在同名的key,則覆蓋這個key。
傳回值是value。
假如第一個參數key不是字串,而是一個Attribute類型的對象的話,第二個參數就可以省略了,會直接把該Attribute對象添加到該元素的Attribute列表中。ele = Element.new 'Book' #<Book />
ele.add_attribute 'name', 'rubys way' #<Book name="rubys way" />
att = Attribute.new 'price', '$5'
ele.add_attribute att #<Book name="rubys way" price="$5" />
注意上面的代碼,我先建立了att對象,然後再調用ele#add_attribute方法把att對象加到ele的attributes中去的。
3 Element#add_attributes( hash )
增加多個屬性到該元素。
hash: 可以是一個Hash或者一個二維Array。ele.add_attributes({"name" => "rubys way", "type" => "book"})#Hash
ele.add_attributes([["name","rubys way"], ["type","book"]])#array of arrays
4 Element#add_element(element, attrs=nil)
添加一個子項目到該元素,可以在添加的時候設定子項目的屬性。
element:如果是一個element,則該element被添加到該父element中,否則,將根據該參數構造一個element,比如該參數是一個string,就會構造一個新的名稱為指定的string的element加入到該元素的子項目中。
attr:如果提供了該參數,必須是一個Hash,該Hash的name將會稱為attribute的name,value就是attribute的value。
5 Element#add_namespace(prefix, uri=nil)
prefix:首碼,xmlns:prefix。
uri:內容。
如果只有一個參數的話,就沒有首碼了,直接是xmns="uri"
比如irb(main):242:0> ele = Element.new "filed"
=> <filed/>
irb(main):243:0> ele
=> <filed/>
irb(main):244:0> ele.add_namespace "pre", "uri"
=> <filed xmlns:pre='uri'/>
irb(main):245:0> ele.add_namespace "uri"
=> <filed xmlns:pre='uri' xmlns='uri'/>
irb(main):246:0> ele.add_namespace "uriuri"
=> <filed xmlns:pre='uri' xmlns='uriuri'/>
6 Element#add_text( string )
給一個Element添加text,比如:irb(main):251:0> ele = Element.new "ele"
=> <ele/>
irb(main):252:0> ele
=> <ele/>
irb(main):253:0> ele.add_text "hallo"
=> <ele> </>
irb(main):254:0> ele.add_text " world"
=> nil
irb(main):255:0> ele
=> <ele> </>
irb(main):256:0> ele.text
=> "hallo world"
7 Element#attribute( key )
訪問一個key,取得該key的value。
8 Element#cdatas()
擷取CData類型的數組。
9 Element#clone()
返回當前元素的淺表複製,也就是僅僅是當前元素的複製,不包括子項目。
10 Element#comments
擷取該元素的所有comment,返回一個數組。
11 Element#delete_attribute(key)
刪除指定名稱的attribute。
12 Element#delete_element(element)
刪除一個element。
參數element: 必須是element對象,或string,integer,如果是element對象,則該element對象被刪除,如果是string,則按XPATH運算式,把符合項刪除,如果是數字,則刪除指定的第幾個元素。
13 Element#delete_namespace(namespace="xmlns")
刪除指定名稱的命名空間,預設為xmlns
14 Element#document()
返回所屬的Document對象,or nil if this element doesn't belong to a document.
15 Element#each_element(xpath = nil) {|element| ...}
根據xpath指定的搜尋條件,遍曆所有符合xpath的element。
16 Element#each_element_with_attribute( key, value=nil, max=0, name=nil) {|element| ... }
根據屬性值遍曆子項目。
key參數限定了屬性的名稱,所有擁有該屬性的子項目被匹配出來
value參數限定了值。
max是匹配的個數。
name是子項目名稱。
17 Element#each_element_with_text(text=nil, max=0, name=nil) {|element| ...}
text: 符合該text的
max: 最大符合次數,設定為0為不限制。
name: 符合的子項目名稱。
18 Element#each_with_something(test, max=0, name=nil){|child if test.call(child) and num+=1 | ...}
這個方法變態不?
ruby的語言的魅力也就在這裡,很方便的給迭代方法,傳入一個作為條件的Proc。
test是一個Proc的執行個體,該Proc只有一個參數,就是每個element。
max是最大匹配數,為0時不限制。
name是名稱。
有多少個element就會調用多少次test.call。
19 Element#get_elements( xpath )
根據xpath返回一個數組,一個array,每個元素都是符合xpath的子項目。
20 Element#get_text( path=nil)
返回第一個text節點。
比如:xml = Document.new "<b>some text<c/>more text</b>" #此時xml有兩個text node
xml.root.get_text.value #-> "some text"
21 Element#has_attributes?
是否有屬性
22 Element#has_elements?
是否有子項目
23 Element#has_text?
是否有textnode
24 Element#namespace(prefix=nil)
取namespace的值,預設沒有首碼,取"xmlns"
25 Element#namespaces()
取所有的命名空間,返回一個Hash
26 Element#next_element()
取下一個element
27 Element#node_type()
取節點類型,:element或:attribute或:namespace
28 Element#prifixes
返回是一個數組,包括所有的命名空間首碼
29 Element#previous_element
返回前面的一個元素,如果沒有返回Nil。
30 Element#root
返回根項目。
31 Element#root_node
可以用這個來判斷兩個element是否是屬於同一個root的,比如ele.root_node == ele[0].root_node
32 Element#text
返回text值
33 Element#text=
設定text值
34 Element#texts
返回所有的text。
這裡有一點要說說,就是一個element可能會有多個text node,看下面的例子:ele = Document.new "<a>some string<b/>more string</a>"
ele.root.text #-> "some string"
ele.root.texts #-> ["some string","more string"]
35 Element#xpath()
擷取一個節點的xpath,這個很有用,如果你不知道該怎麼匹配一個節點,就可以直接用這個方法查看下。
三 Elements Class
element的集合,可以用element.elements來訪問子集。
1 elements::new(element)
建構函式。
element: 指示新建立的elements隸屬於哪個element。
2 elements#<<
alias for #add
3 elements#[]