Class: REXML::Elements
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Instance Chain:
self,
Enumerable
|
|
Inherits: | Object |
Defined in: | lib/rexml/element.rb |
Overview
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> ... </>>
Class Method Summary
-
.new(parent) ⇒ Elements
constructor
Returns a new Elements object with the given #parent.
Instance Attribute Summary
-
#empty? ⇒ Boolean
readonly
Returns
true
if there are no children,false
otherwise.
Instance Method Summary
-
#<<(element = nil)
Alias for #add.
-
#[](index) ⇒ element?
Returns the first Element object selected by the arguments, if any found, or
nil
if none found. -
#[]=(index, replacement_element) ⇒ replacement_element?
Replaces or adds an element.
-
#add ⇒ new_element
(also: #<<)
Adds an element; returns the element added.
-
#collect(xpath = nil) {|element| ... } ⇒ Array
Iterates over the elements; returns the array of block return values.
-
#delete(index) ⇒ removed_element?
Removes an element; returns the removed element, or
nil
if none removed. -
#delete_all(xpath)
Removes all elements found via the given
xpath
; returns the array of removed elements, if any, elsenil
. -
#each(xpath = nil) {|element| ... } ⇒ self
Iterates over the elements.
-
#index(element)
Returns the 1-based index of the given
element
, if found; otherwise, returns -1: -
#inject(xpath = nil, initial = nil) ⇒ Object
Calls the block with elements; returns the last block return value.
-
#parent
Returns the parent element cited in creating the Elements object.
-
#size ⇒ Integer
Returns the count of Element children:
-
#to_a(xpath = nil) ⇒ Elements
Returns an array of element children (not including non-element children).
-
#literalize(name)
private
Private helper class.
Constructor Details
.new(parent) ⇒ Elements
Instance Attribute Details
#empty? ⇒ Boolean
(readonly)
# File 'lib/rexml/element.rb', line 1755
def empty? @element.find{ |child| child.kind_of? Element}.nil? end
Instance Method Details
#<<(element = nil)
Alias for #add.
# File 'lib/rexml/element.rb', line 1937
alias :<< :add
#[](index) ⇒ element
?
#[](xpath) ⇒ element
?
#[](n, name) ⇒ element
?
element
?
#[](xpath) ⇒ element
?
#[](n, name) ⇒ element
?
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 '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
#[]=(index, replacement_element) ⇒ replacement_element
?
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
#add ⇒ new_element
#add(name) ⇒ new_element
#add(element) ⇒ element
Also known as: #<<
new_element
#add(name) ⇒ new_element
#add(element) ⇒ element
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}
#collect(xpath = nil) {|element| ... } ⇒ Array
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]
#delete(index) ⇒ removed_element
?
#delete(element) ⇒ removed_element
?
#delete(xpath) ⇒ removed_element
?
removed_element
?
#delete(element) ⇒ removed_element
?
#delete(xpath) ⇒ removed_element
?
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 '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
#delete_all(xpath)
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') # => []
#each(xpath = nil) {|element| ... } ⇒ self
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 }
<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 }
<book category='web'> ... </>
<book category='web' cover='paperback'> ... </>
#index(element)
# File '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
#inject(xpath = nil, initial = nil) ⇒ Object
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
[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
[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
[-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
#literalize(name) (private)
Private helper class. Removes quotes from quoted strings
# File 'lib/rexml/element.rb', line 2129
def literalize name name = name[1..-2] if name[0] == ?' or name[0] == ?" #' name end
#parent
# File 'lib/rexml/element.rb', line 1623
def parent @element end
#size ⇒ Integer
#to_a(xpath = nil) ⇒ Elements
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/>]