# 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 765
    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 790
    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 822
    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 898
    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 930
    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 862
    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 877
    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 926
    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 833
    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 840
    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 938
    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 957
    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 970
    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 978
    def literalize name
      name = name[1..-2] if name[0] == ?' or name[0] == ?"               #'
      name
    end