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
trueif there are no children,falseotherwise.
Instance Method Summary
-
#<<(element = nil)
Alias for #add.
-
#[](index) ⇒ element?
Returns the first Element object selected by the arguments, if any found, or
nilif 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
nilif 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 1751
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 1933
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 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
#[]=(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 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)
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 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
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
initialand 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 2125
def literalize name name = name[1..-2] if name[0] == ?' or name[0] == ?" #' name end
#parent
# File 'lib/rexml/element.rb', line 1619
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/>]