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> ... </>>

公共类方法

new(parent) → new_elements_object 点击切换源代码

返回一个新的 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)
别名为:add
elements[index] → element 或 nil 点击切换源代码
elements[xpath] → element 或 nil
elements[n, name] → element 或 nil

返回通过参数选择的第一个 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

当给出参数 nname 时,返回第 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
elements[] = index, replacement_element → replacement_element 或 nil 点击切换源代码

替换或添加一个元素。

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
add → new_element 点击切换源代码
add(name) → new_element
add(element) → element

添加一个元素;返回添加的元素。

如果不带参数,则创建并添加一个新元素。新元素具有

  • 没有名称。

  • 来自 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
也别名为:<<
collect(xpath = nil) {|element| ... } → array 点击切换源代码

迭代元素;返回块返回值数组。

如果不带参数,则迭代所有元素

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
delete(index) → removed_element 或 nil 点击切换源代码
delete(element) → removed_element 或 nil
delete(xpath) → removed_element 或 nil

删除一个元素;返回删除的元素,如果没有删除,则返回 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
delete_all(xpath) 点击切换源代码

删除通过给定 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
each(xpath = nil) {|element| ... } → self 点击切换源代码

迭代元素。

如果不带参数,则使用每个元素调用块

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
empty? → true 或 false 点击切换源代码

如果没有任何子元素,则返回 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
index(element) 点击切换源代码

返回给定 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
inject(xpath = nil, initial = nil) → object 点击切换源代码

使用元素调用块;返回最后一个块返回值。

如果不带参数,则迭代元素,调用块 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

如果同时给出参数 xpathinitial,则仅使用与该 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
parent 点击切换源代码

返回创建 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
size → integer 点击切换源代码

返回 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
to_a(xpath = nil) → array_of_elements 点击切换源代码

返回元素子元素的数组(不包括非元素子元素)。

如果不带参数,则返回所有元素子元素的数组

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

私有实例方法

literalize(name) 点击切换源代码

私有辅助类。从带引号的字符串中删除引号

# 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