# class REXML::Elements

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.

### Public Class Methods

new(parent) click to toggle source

Constructor

parent

  the parent Element

    # File lib/rexml/element.rb, line 764
    def initialize parent
      @element = parent
    end

### Public Instance Methods

<<(element=nil)
Alias for: add
[]( index, name=nil) click to toggle source

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 +n+th 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"/>

    # File lib/rexml/element.rb, line 789
    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 ) click to toggle source

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>

    # File lib/rexml/element.rb, line 821
    def []=( index, element )
      previous = self[index]
      if previous.nil?
        @element.add element
      else
        previous.replace_with element
      end
      return previous
    end

add(element=nil) click to toggle source

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>

    # File lib/rexml/element.rb, line 897
    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

Also aliased as: <<
collect( xpath=nil ) { |e| ... } click to toggle source

    # File lib/rexml/element.rb, line 929
    def collect( xpath=nil )
      collection = []
      XPath::each( @element, xpath ) {|e|
        collection << yield(e)  if e.kind_of?(Element)
      }
      collection
    end

delete(element) click to toggle source

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

    # File lib/rexml/element.rb, line 861
    def delete element
      if element.kind_of? Element
        @element.delete element
      else
        el = self[element]
        el.remove if el
      end
    end

delete_all( xpath ) click to toggle source

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

    # File lib/rexml/element.rb, line 876
    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 ) { |e| ... } click to toggle source

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

    # File lib/rexml/element.rb, line 925
    def each( xpath=nil )
      XPath::each( @element, xpath ) {|e| yield e if e.kind_of? Element }
    end

empty?() click to toggle source

Returns `true` if there are no `Element` children, `false` otherwise

    # File lib/rexml/element.rb, line 832
    def empty?
      @element.find{ |child| child.kind_of? Element}.nil?
    end

index(element) click to toggle source

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

element

  an `Element` child

    # File lib/rexml/element.rb, line 839
    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 ) { |initial, e| ... } click to toggle source

    # File lib/rexml/element.rb, line 937
    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

size() click to toggle source

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

    # File lib/rexml/element.rb, line 956
    def size
      count = 0
      @element.each {|child| count+=1 if child.kind_of? Element }
      count
    end

to_a( xpath=nil ) click to toggle source

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

    # File lib/rexml/element.rb, line 969
    def to_a( xpath=nil )
      rv = XPath.match( @element, xpath )
      return rv.find_all{|e| e.kind_of? Element} if xpath
      rv
    end

### Private Instance Methods

literalize(name) click to toggle source

Private helper class. Removes quotes from quoted strings

    # File lib/rexml/element.rb, line 977
    def literalize name
      name = name[1..-2] if name[0] == ?' or name[0] == ?"               #'
      name
    end