class REXML::Elements
此类为 Elements
提供子元素的过滤,并提供 XPath
搜索支持。您应该只将此类视为 element.elements
对象。因此,您不应该自己实例化此类。
xml_string = <<-EOT <?xml version="1.0" encoding="UTF-8"?> <bookstore> <book category="cooking"> <title lang="en">Everyday Italian</title> <author>Giada De Laurentiis</author> <year>2005</year> <price>30.00</price> </book> <book category="children"> <title lang="en">Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> <book category="web"> <title lang="en">XQuery Kick Start</title> <author>James McGovern</author> <author>Per Bothner</author> <author>Kurt Cagle</author> <author>James Linn</author> <author>Vaidyanathan Nagarajan</author> <year>2003</year> <price>49.99</price> </book> <book category="web" cover="paperback"> <title lang="en">Learning XML</title> <author>Erik T. Ray</author> <year>2003</year> <price>39.95</price> </book> </bookstore> EOT d = REXML::Document.new(xml_string) elements = d.root.elements elements # => #<REXML::Elements @element=<bookstore> ... </>>
公共类方法
返回一个新的 Elements 对象,其中包含给定的 parent
。不指定 parent.elements = self
d = REXML::Document.new(xml_string) eles = REXML::Elements.new(d.root) eles # => #<REXML::Elements @element=<bookstore> ... </>> eles == d.root.elements # => false
# File rexml-3.4.0/lib/rexml/element.rb, line 1604 def initialize parent @element = parent end
公共实例方法
返回通过参数选择的第一个 Element 对象(如果找到),或者如果没有找到,则返回 nil
。
注意
-
index
是从 1 开始的,而不是从 0 开始的,因此-
第一个元素的索引是
1
-
第 n 个元素的索引是
n
。
-
-
选择会忽略非 Element 节点。
当给出单个参数 index
时,返回给定索引的元素(如果有);否则,返回 nil
d = REXML::Document.new(xml_string) eles = d.root.elements eles # => #<REXML::Elements @element=<bookstore> ... </>> eles[1] # => <book category='cooking'> ... </> eles.size # => 4 eles[4] # => <book category='web' cover='paperback'> ... </> eles[5] # => nil
此索引处的节点不是 Element,因此不会返回
eles = d.root.first.first # => <title lang='en'> ... </> eles.to_a # => ["Everyday Italian"] eles[1] # => nil
当给出单个参数 xpath
时,返回通过该 xpath
找到的第一个元素(如果有);否则,返回 nil
eles = d.root.elements # => #<REXML::Elements @element=<bookstore> ... </>> eles['/bookstore'] # => <bookstore> ... </> eles['//book'] # => <book category='cooking'> ... </> eles['//book [@category="children"]'] # => <book category='children'> ... </> eles['/nosuch'] # => nil eles['//nosuch'] # => nil eles['//book [@category="nosuch"]'] # => nil eles['.'] # => <bookstore> ... </> eles['..'].class # => REXML::Document
当给出参数 n
和 name
时,返回第 n 个找到的具有给定 name
的元素,或者如果没有第 n 个元素,则返回 nil
eles = d.root.elements # => #<REXML::Elements @element=<bookstore> ... </>> eles[1, 'book'] # => <book category='cooking'> ... </> eles[4, 'book'] # => <book category='web' cover='paperback'> ... </> eles[5, 'book'] # => nil
# File rexml-3.4.0/lib/rexml/element.rb, line 1676 def []( index, name=nil) if index.kind_of? Integer raise "index (#{index}) must be >= 1" if index < 1 name = literalize(name) if name num = 0 @element.find { |child| child.kind_of? Element and (name.nil? ? true : child.has_name?( name )) and (num += 1) == index } else return XPath::first( @element, index ) #{ |element| # return element if element.kind_of? Element #} #return nil end end
替换或添加一个元素。
当 eles[index]
存在时,将其替换为 replacement_element
并返回 replacement_element
d = REXML::Document.new(xml_string) eles = d.root.elements # => #<REXML::Elements @element=<bookstore> ... </>> eles[1] # => <book category='cooking'> ... </> eles[1] = REXML::Element.new('foo') eles[1] # => <foo/>
如果 replacement_element
不是 Element,则不执行任何操作(或引发异常)
eles[2] # => <book category='web' cover='paperback'> ... </> eles[2] = REXML::Text.new('bar') eles[2] # => <book category='web' cover='paperback'> ... </>
当 eles[index]
不存在时,将 replacement_element
添加到元素并返回
d = REXML::Document.new(xml_string) eles = d.root.elements # => #<REXML::Elements @element=<bookstore> ... </>> eles.size # => 4 eles[50] = REXML::Element.new('foo') # => <foo/> eles.size # => 5 eles[5] # => <foo/>
如果 replacement_element
不是 Element,则不执行任何操作(或引发异常)
eles[50] = REXML::Text.new('bar') # => "bar" eles.size # => 5
# File rexml-3.4.0/lib/rexml/element.rb, line 1731 def []=( index, element ) previous = self[index] if previous.nil? @element.add element else previous.replace_with element end return previous end
添加一个元素;返回添加的元素。
如果不带参数,则创建并添加一个新元素。新元素具有
-
没有名称。
-
来自 Elements 对象的父级。
-
来自该父级的上下文。
示例
d = REXML::Document.new(xml_string) elements = d.root.elements parent = elements.parent # => <bookstore> ... </> parent.context = {raw: :all} elements.size # => 4 new_element = elements.add # => </> elements.size # => 5 new_element.name # => nil new_element.parent # => <bookstore> ... </> new_element.context # => {:raw=>:all}
如果使用字符串参数 name
,则创建并添加一个新元素。新元素具有
-
名称
name
。 -
来自 Elements 对象的父级。
-
来自该父级的上下文。
示例
d = REXML::Document.new(xml_string) elements = d.root.elements parent = elements.parent # => <bookstore> ... </> parent.context = {raw: :all} elements.size # => 4 new_element = elements.add('foo') # => <foo/> elements.size # => 5 new_element.name # => "foo" new_element.parent # => <bookstore> ... </> new_element.context # => {:raw=>:all}
如果使用参数 element
,则创建并添加给定 element
的克隆。新元素具有来自给定 element
的名称、父级和上下文。
d = REXML::Document.new(xml_string) elements = d.root.elements elements.size # => 4 e0 = REXML::Element.new('foo') e1 = REXML::Element.new('bar', e0, {raw: :all}) element = elements.add(e1) # => <bar/> elements.size # => 5 element.name # => "bar" element.parent # => <bookstore> ... </> element.context # => {:raw=>:all}
# File rexml-3.4.0/lib/rexml/element.rb, line 1921 def add element=nil if element.nil? Element.new("", self, @element.context) elsif not element.kind_of?(Element) Element.new(element, self, @element.context) else @element << element element.context = @element.context element end end
迭代元素;返回块返回值数组。
如果不带参数,则迭代所有元素
d = REXML::Document.new(xml_string) elements = d.root.elements elements.collect {|element| element.size } # => [9, 9, 17, 9]
如果使用参数 xpath
,则迭代与给定 xpath
匹配的元素
xpath = '//book [@category="web"]' elements.collect(xpath) {|element| element.size } # => [17, 9]
# File rexml-3.4.0/lib/rexml/element.rb, line 1984 def collect( xpath=nil ) collection = [] XPath::each( @element, xpath ) {|e| collection << yield(e) if e.kind_of?(Element) } collection end
删除一个元素;返回删除的元素,如果没有删除,则返回 nil
。
如果给定整数参数 index
,则删除该偏移量的子元素
d = REXML::Document.new(xml_string) elements = d.root.elements elements.size # => 4 elements[2] # => <book category='children'> ... </> elements.delete(2) # => <book category='children'> ... </> elements.size # => 3 elements[2] # => <book category='web'> ... </> elements.delete(50) # => nil
如果给定元素参数 element
,则删除该子元素
d = REXML::Document.new(xml_string) elements = d.root.elements ele_1, ele_2, ele_3, ele_4 = *elements elements.size # => 4 elements[2] # => <book category='children'> ... </> elements.delete(ele_2) # => <book category='children'> ... </> elements.size # => 3 elements[2] # => <book category='web'> ... </> elements.delete(ele_2) # => nil
如果给定字符串参数 xpath
,则删除通过该 xpath 找到的第一个元素
d = REXML::Document.new(xml_string) elements = d.root.elements elements.delete('//book') # => <book category='cooking'> ... </> elements.delete('//book [@category="children"]') # => <book category='children'> ... </> elements.delete('//nosuch') # => nil
# File rexml-3.4.0/lib/rexml/element.rb, line 1821 def delete element if element.kind_of? Element @element.delete element else el = self[element] el.remove if el end end
删除通过给定 xpath
找到的所有元素;返回删除的元素数组(如果有),否则返回 nil
。
d = REXML::Document.new(xml_string) elements = d.root.elements elements.size # => 4 deleted_elements = elements.delete_all('//book [@category="web"]') deleted_elements.size # => 2 elements.size # => 2 deleted_elements = elements.delete_all('//book') deleted_elements.size # => 2 elements.size # => 0 elements.delete_all('//book') # => []
# File rexml-3.4.0/lib/rexml/element.rb, line 1847 def delete_all( xpath ) rv = [] XPath::each( @element, xpath) {|element| rv << element if element.kind_of? Element } rv.each do |element| @element.delete element element.remove end return rv end
迭代元素。
如果不带参数,则使用每个元素调用块
d = REXML::Document.new(xml_string) elements = d.root.elements elements.each {|element| p element }
输出
<book category='cooking'> ... </> <book category='children'> ... </> <book category='web'> ... </> <book category='web' cover='paperback'> ... </>
如果使用参数 xpath
,则使用每个与给定 xpath
匹配的元素调用块
elements.each('//book [@category="web"]') {|element| p element }
输出
<book category='web'> ... </> <book category='web' cover='paperback'> ... </>
# File rexml-3.4.0/lib/rexml/element.rb, line 1963 def each( xpath=nil ) XPath::each( @element, xpath ) {|e| yield e if e.kind_of? Element } end
如果没有任何子元素,则返回 true
,否则返回 false
。
d = REXML::Document.new('') d.elements.empty? # => true d = REXML::Document.new(xml_string) d.elements.empty? # => false
# File rexml-3.4.0/lib/rexml/element.rb, line 1751 def empty? @element.find{ |child| child.kind_of? Element}.nil? end
返回给定 element
的从 1 开始的索引(如果找到);否则,返回 -1
d = REXML::Document.new(xml_string) elements = d.root.elements ele_1, ele_2, ele_3, ele_4 = *elements elements.index(ele_4) # => 4 elements.delete(ele_3) elements.index(ele_4) # => 3 elements.index(ele_3) # => -1
# File rexml-3.4.0/lib/rexml/element.rb, line 1769 def index element rv = 0 found = @element.find do |child| child.kind_of? Element and (rv += 1) and child == element end return rv if found == element return -1 end
使用元素调用块;返回最后一个块返回值。
如果不带参数,则迭代元素,调用块 elements.size - 1
次。
-
第一次调用传递第一个和第二个元素。
-
第二次调用传递第一个块返回值和第三个元素。
-
第三次调用传递第二个块返回值和第四个元素。
-
以此类推。
在此示例中,块返回传递的元素,该元素随后将作为下一个调用的对象参数
d = REXML::Document.new(xml_string) elements = d.root.elements elements.inject do |object, element| p [elements.index(object), elements.index(element)] element end
输出
[1, 2] [2, 3] [3, 4]
如果使用单个参数 xpath
,则仅使用与该 xpath 匹配的元素调用块
elements.inject('//book [@category="web"]') do |object, element| p [elements.index(object), elements.index(element)] element end
输出
[3, 4]
如果将参数 xpath
指定为 nil
且还给出了参数 initial
,则为每个元素调用一次块。
-
第一次调用传递
initial
和第一个元素。 -
第二次调用传递第一个块返回值和第二个元素。
-
第三次调用传递第二个块返回值和第三个元素。
-
以此类推。
在此示例中,第一个对象索引为 -1
elements.inject(nil, 'Initial') do |object, element| p [elements.index(object), elements.index(element)] element end
输出
[-1, 1] [1, 2] [2, 3] [3, 4]
在这种形式中,传递的对象可以用作累加器
elements.inject(nil, 0) do |total, element| total += element.size end # => 44
如果同时给出参数 xpath
和 initial
,则仅使用与该 xpath 匹配的元素调用块
elements.inject('//book [@category="web"]', 0) do |total, element| total += element.size end # => 26
# File rexml-3.4.0/lib/rexml/element.rb, line 2069 def inject( xpath=nil, initial=nil ) first = true XPath::each( @element, xpath ) {|e| if (e.kind_of? Element) if (first and initial == nil) initial = e first = false else initial = yield( initial, e ) if e.kind_of? Element end end } initial end
返回创建 Elements 对象时引用的父元素。此元素也是在 Elements 对象中搜索的默认起点。
d = REXML::Document.new(xml_string) elements = REXML::Elements.new(d.root) elements.parent == d.root # => true
# File rexml-3.4.0/lib/rexml/element.rb, line 1619 def parent @element end
返回 Element 子元素的计数
d = REXML::Document.new '<a>sean<b/>elliott<b/>russell<b/></a>' d.root.elements.size # => 3 # Three elements. d.root.size # => 6 # Three elements plus three text nodes..
# File rexml-3.4.0/lib/rexml/element.rb, line 2093 def size count = 0 @element.each {|child| count+=1 if child.kind_of? Element } count end
返回元素子元素的数组(不包括非元素子元素)。
如果不带参数,则返回所有元素子元素的数组
d = REXML::Document.new '<a>sean<b/>elliott<c/></a>' elements = d.root.elements elements.to_a # => [<b/>, <c/>] # Omits non-element children. children = d.root.children children # => ["sean", <b/>, "elliott", <c/>] # Includes non-element children.
如果使用参数 xpath
,则返回与 xpath 匹配的元素子元素数组
elements.to_a('//c') # => [<c/>]
# File rexml-3.4.0/lib/rexml/element.rb, line 2117 def to_a( xpath=nil ) rv = XPath.match( @element, xpath ) return rv.find_all{|e| e.kind_of? Element} if xpath rv end
私有实例方法
私有辅助类。从带引号的字符串中删除引号
# File rexml-3.4.0/lib/rexml/element.rb, line 2125 def literalize name name = name[1..-2] if name[0] == ?' or name[0] == ?" #' name end