Object
A class which provides filtering of children for Elements, and XPath
search support. You are expected to only encounter this class as the
element.elements object. Therefore, you are not
expected to instantiate this yourself.
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> ... </>>
Returns a new Elements object with the given parent. Does
not assign 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.2.5/lib/rexml/element.rb, line 1608
def initialize parent
@element = parent
end
Returns the first Element object selected by the arguments, if any found,
or nil if none found.
Notes:
The index is 1-based, not 0-based, so that:
The first element has index 1
The nth element has index n.
The selection ignores non-Element nodes.
When the single argument index is given, returns the element
given by the index, if any; otherwise, 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
The node at this index is not an Element, and so is not returned:
eles = d.root.first.first # => <title lang='en'> ... </> eles.to_a # => ["Everyday Italian"] eles[1] # => nil
When the single argument xpath is given, returns the first
element found via that xpath, if any; otherwise,
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
With arguments n and name given, returns the
nth found element that has the given name, or
nil if there is no such nth element:
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.2.5/lib/rexml/element.rb, line 1680
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
Replaces or adds an element.
When eles[index] exists, replaces it with
replacement_element and returns
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/>
Does nothing (or raises an exception) if replacement_element
is not an Element:
eles[2] # => <book category='web' cover='paperback'> ... </> eles[2] = REXML::Text.new('bar') eles[2] # => <book category='web' cover='paperback'> ... </>
When eles[index] does not exist, adds
replacement_element to the element and returns
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/>
Does nothing (or raises an exception) if replacement_element
is not an Element:
eles[50] = REXML::Text.new('bar') # => "bar" eles.size # => 5
# File rexml-3.2.5/lib/rexml/element.rb, line 1735
def []=( index, element )
previous = self[index]
if previous.nil?
@element.add element
else
previous.replace_with element
end
return previous
end
Adds an element; returns the element added.
With no argument, creates and adds a new element. The new element has:
No name.
Parent from the Elements object.
Context from the that parent.
Example:
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}
With string argument name, creates and adds a new element. The
new element has:
Name name.
Parent from the Elements object.
Context from the that parent.
Example:
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}
With argument element, creates and adds a clone of the given
element. The new element has name, parent, and context from
the given 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.2.5/lib/rexml/element.rb, line 1925
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
Iterates over the elements; returns the array of block return values.
With no argument, iterates over all elements:
d = REXML::Document.new(xml_string) elements = d.root.elements elements.collect {|element| element.size } # => [9, 9, 17, 9]
With argument xpath, iterates over elements that match the
given xpath:
xpath = '//book [@category="web"]' elements.collect(xpath) {|element| element.size } # => [17, 9]
# File rexml-3.2.5/lib/rexml/element.rb, line 1988
def collect( xpath=nil )
collection = []
XPath::each( @element, xpath ) {|e|
collection << yield(e) if e.kind_of?(Element)
}
collection
end
Removes an element; returns the removed element, or nil if
none removed.
With integer argument index given, removes the child element
at that offset:
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
With element argument element given, removes that child
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
With string argument xpath given, removes the first element
found via that 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.2.5/lib/rexml/element.rb, line 1825
def delete element
if element.kind_of? Element
@element.delete element
else
el = self[element]
el.remove if el
end
end
Removes all elements found via the given xpath; returns the
array of removed elements, if any, else 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.2.5/lib/rexml/element.rb, line 1851
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
Iterates over the elements.
With no argument, calls the block with each element:
d = REXML::Document.new(xml_string) elements = d.root.elements elements.each {|element| p element }
Output:
<book category='cooking'> ... </> <book category='children'> ... </> <book category='web'> ... </> <book category='web' cover='paperback'> ... </>
With argument xpath, calls the block with each element that
matches the given xpath:
elements.each('//book [@category="web"]') {|element| p element }
Output:
<book category='web'> ... </> <book category='web' cover='paperback'> ... </>
# File rexml-3.2.5/lib/rexml/element.rb, line 1967
def each( xpath=nil )
XPath::each( @element, xpath ) {|e| yield e if e.kind_of? Element }
end
Returns true if there are no children, false
otherwise.
d = REXML::Document.new('') d.elements.empty? # => true d = REXML::Document.new(xml_string) d.elements.empty? # => false
# File rexml-3.2.5/lib/rexml/element.rb, line 1755
def empty?
@element.find{ |child| child.kind_of? Element}.nil?
end
Returns the 1-based index of the given element, if found;
otherwise, returns -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.2.5/lib/rexml/element.rb, line 1773
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
Calls the block with elements; returns the last block return value.
With no argument, iterates over the elements, calling the block
elements.size - 1 times.
The first call passes the first and second elements.
The second call passes the first block return value and the third element.
The third call passes the second block return value and the fourth element.
And so on.
In this example, the block returns the passed element, which is then the object argument to the next call:
d = REXML::Document.new(xml_string) elements = d.root.elements elements.inject do |object, element| p [elements.index(object), elements.index(element)] element end
Output:
[1, 2] [2, 3] [3, 4]
With the single argument xpath, calls the block only with
elements matching that xpath:
elements.inject('//book [@category="web"]') do |object, element| p [elements.index(object), elements.index(element)] element end
Output:
[3, 4]
With argument xpath given as nil and argument
initial also given, calls the block once for each element.
The first call passes the initial and the first element.
The second call passes the first block return value and the second element.
The third call passes the second block return value and the third element.
And so on.
In this example, the first object index is -1
elements.inject(nil, 'Initial') do |object, element| p [elements.index(object), elements.index(element)] element end
Output:
[-1, 1] [1, 2] [2, 3] [3, 4]
In this form the passed object can be used as an accumulator:
elements.inject(nil, 0) do |total, element| total += element.size end # => 44
With both arguments xpath and initial are given,
calls the block only with elements matching that xpath:
elements.inject('//book [@category="web"]', 0) do |total, element| total += element.size end # => 26
# File rexml-3.2.5/lib/rexml/element.rb, line 2073
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
Returns the parent element cited in creating the Elements object. This element is also the default starting point for searching in the Elements object.
d = REXML::Document.new(xml_string) elements = REXML::Elements.new(d.root) elements.parent == d.root # => true
# File rexml-3.2.5/lib/rexml/element.rb, line 1623
def parent
@element
end
Returns the count of Element children:
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.2.5/lib/rexml/element.rb, line 2097
def size
count = 0
@element.each {|child| count+=1 if child.kind_of? Element }
count
end
Returns an array of element children (not including non-element children).
With no argument, returns an array of all element children:
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.
With argument xpath, returns an array of element children that
match the xpath:
elements.to_a('//c') # => [<c/>]
# File rexml-3.2.5/lib/rexml/element.rb, line 2121
def to_a( xpath=nil )
rv = XPath.match( @element, xpath )
return rv.find_all{|e| e.kind_of? Element} if xpath
rv
end