123456789_123456789_123456789_123456789_123456789_

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.

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(parent) ⇒ Elements

Constructor

parent

the parent Element

[ GitHub ]

  
# File 'lib/rexml/element.rb', line 740

def initialize parent
  @element = parent
end

Instance Attribute Details

#empty?Boolean (readonly)

Returns true if there are no Element children, false otherwise

[ GitHub ]

  
# File 'lib/rexml/element.rb', line 808

def empty?
  @element.find{ |child| child.kind_of? Element}.nil?
end

Instance Method Details

#<<(element = nil)

Alias for #add.

[ GitHub ]

  
# File 'lib/rexml/element.rb', line 885

alias :<< :add

#[](index, name = nil)

Fetches a child element. Filters only Element children, regardless of the XPath match.

index

the search parameter. This is either an Integer, which will be used to find the index'th child Element, or an XPath, which will be used to search for the Element. Because of the nature of XPath searches, any element in the connected XML document can be fetched through any other element. The Integer index is 1-based, not 0-based. This means that the first child element is at index 1, not 0, and the nth element is at index n, not n-1. This is because XPath indexes element children starting from 1, not 0, and the indexes should be the same.

name

optional, and only used in the first argument is an Integer. In that case, the index'th child Element that has the supplied name will be returned. Note again that the indexes start at 1.

Returns

the first matching Element, or nil if no child matched

doc = Document.new '<a><b/><c id="1"/><c id="2"/><d/></a>'
doc.root.elements[1]       #-> <b/>
doc.root.elements['c']     #-> <c id="1"/>
doc.root.elements[2,'c']   #-> <c id="2"/>
[ GitHub ]

  
# File 'lib/rexml/element.rb', line 765

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, element)

Sets an element, replacing any previous matching element. If no existing element is found ,the element is added.

index

Used to find a matching element to replace. See []().

element

The element to replace the existing element with the previous element

Returns

nil if no previous element was found.

doc = Document.new '<a/>'
doc.root.elements[10] = Element.new('b')    #-> <a><b/></a>
doc.root.elements[1]                        #-> <b/>
doc.root.elements[1] = Element.new('c')     #-> <a><c/></a>
doc.root.elements['c'] = Element.new('d')   #-> <a><d/></a>
[ GitHub ]

  
# File 'lib/rexml/element.rb', line 797

def []=( index, element )
  previous = self[index]
  if previous.nil?
    @element.add element
  else
    previous.replace_with element
  end
  return previous
end

#add(element = nil) Also known as: #<<

Adds an element

element

if supplied, is either an Element, String, or Source (see Element.initialize). If not supplied or nil, a new, default Element will be constructed

Returns

the added Element

a = Element.new('a')
a.elements.add(Element.new('b'))  #-> <a><b/></a>
a.elements.add('c')               #-> <a><b/><c/></a>
[ GitHub ]

  
# File 'lib/rexml/element.rb', line 873

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)

[ GitHub ]

  
# File 'lib/rexml/element.rb', line 905

def collect( xpath=nil )
  collection = []
  XPath::each( @element, xpath ) {|e|
    collection << yield(e)  if e.kind_of?(Element)
  }
  collection
end

#delete(element)

Deletes a child Element

element

Either an Element, which is removed directly; an xpath, where the first matching child is removed; or an Integer, where the n'th Element is removed.

Returns

the removed child

doc = Document.new '<a><b/><c/><c id="1"/></a>'
b = doc.root.elements[1]
doc.root.elements.delete b           #-> <a><c/><c id="1"/></a>
doc.elements.delete("a/c[@id='1']")  #-> <a><c/></a>
doc.root.elements.delete 1           #-> <a/>
[ GitHub ]

  
# File 'lib/rexml/element.rb', line 837

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 multiple elements. Filters for Element children, regardless of XPath matching.

xpath

all elements matching this String path are removed.

Returns

an ::Array of Elements that have been removed

doc = Document.new '<a><c/><c/><c/><c/></a>'
deleted = doc.elements.delete_all 'a/c' #-> [<c/>, <c/>, <c/>, <c/>]
[ GitHub ]

  
# File 'lib/rexml/element.rb', line 852

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)

Iterates through all of the child Elements, optionally filtering them by a given XPath

xpath

optional. If supplied, this is a String XPath, and is used to filter the children, so that only matching children are yielded. Note that XPaths are automatically filtered for Elements, so that non-Element children will not be yielded

doc = Document.new '<a><b/><c/><d/>sean<b/><c/><d/></a>'
doc.root.elements.each {|e|p e}       #-> Yields b, c, d, b, c, d elements
doc.root.elements.each('b') {|e|p e}  #-> Yields b, b elements
doc.root.elements.each('child::node()')  {|e|p e}
#-> Yields <b/>, <c/>, <d/>, <b/>, <c/>, <d/>
XPath.each(doc.root, 'child::node()', &block)
#-> Yields <b/>, <c/>, <d/>, sean, <b/>, <c/>, <d/>
[ GitHub ]

  
# File 'lib/rexml/element.rb', line 901

def each( xpath=nil )
  XPath::each( @element, xpath ) {|e| yield e if e.kind_of? Element }
end

#index(element)

Returns the index of the supplied child (starting at 1), or -1 if the element is not a child

element

an Element child

[ GitHub ]

  
# File 'lib/rexml/element.rb', line 815

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)

[ GitHub ]

  
# File 'lib/rexml/element.rb', line 913

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

#literalize(name) (private)

Private helper class. Removes quotes from quoted strings

[ GitHub ]

  
# File 'lib/rexml/element.rb', line 953

def literalize name
  name = name[1..-2] if name[0] == ?' or name[0] == ?"               #'
  name
end

#size

Returns the number of Element children of the parent object.

doc = Document.new '<a>sean<b/>elliott<b/>russell<b/></a>'
doc.root.size            #-> 6, 3 element and 3 text nodes
doc.root.elements.size   #-> 3
[ GitHub ]

  
# File 'lib/rexml/element.rb', line 932

def size
  count = 0
  @element.each {|child| count+=1 if child.kind_of? Element }
  count
end

#to_a(xpath = nil)

Returns an ::Array of Element children. An XPath may be supplied to filter the children. Only Element children are returned, even if the supplied XPath matches non-Element children.

doc = Document.new '<a>sean<b/>elliott<c/></a>'
doc.root.elements.to_a                  #-> [ <b/>, <c/> ]
doc.root.elements.to_a("child::node()") #-> [ <b/>, <c/> ]
XPath.match(doc.root, "child::node()")  #-> [ sean, <b/>, elliott, <c/> ]
[ GitHub ]

  
# File 'lib/rexml/element.rb', line 945

def to_a( xpath=nil )
  rv = XPath.match( @element, xpath )
  return rv.find_all{|e| e.kind_of? Element} if xpath
  rv
end