class REXML::Attributes - rexml: Ruby Standard Library Documentation

# class REXML::Attributes

A class that defines the set of `Attributes` of an `Element` and provides operations for accessing elements in that set.

### Public Class Methods

new(element) click to toggle source

Creates and returns a new REXML::Attributes object. The element given by argument `element` is stored, but its own attributes are not modified:

    ele = REXML::Element.new('foo')
    attrs = REXML::Attributes.new(ele)
    attrs.object_id == ele.attributes.object_id # => false

Other instance methods in class REXML::Attributes may refer to:

- `element.document`.

- `element.prefix`.

- `element.expanded_name`.

    # File rexml-3.4.0/lib/rexml/element.rb, line 2156
    def initialize element
      @element = element
    end

### Public Instance Methods

<<( attribute )
Alias for: add
[name] → attribute_value or nil click to toggle source

Returns the value for the attribute given by `name`, if it exists; otherwise `nil`. The value returned is the unnormalized attribute value, with entities expanded:

    xml_string = <<-EOT
      <root xmlns:foo="http://foo" xmlns:bar="http://bar">
         <ele foo:att='1' bar:att='2' att='&lt;'/>
      </root>
    EOT
    d = REXML::Document.new(xml_string)
    ele = d.elements['//ele'] # => <a foo:att='1' bar:att='2' att='&lt;'/>
    ele.attributes['att']     # => "<"
    ele.attributes['bar:att'] # => "2"
    ele.attributes['nosuch']  # => nil

Related: `get_attribute` (returns an Attribute object).

    # File rexml-3.4.0/lib/rexml/element.rb, line 2181
    def [](name)
      attr = get_attribute(name)
      return attr.value unless attr.nil?
      return nil
    end

[name] = value → value click to toggle source

When `value` is non-`nil`, assigns that to the attribute for the given `name`, overwriting the previous value if it exists:

    xml_string = <<-EOT
      <root xmlns:foo="http://foo" xmlns:bar="http://bar">
         <ele foo:att='1' bar:att='2' att='&lt;'/>
      </root>
    EOT
    d = REXML::Document.new(xml_string)
    ele = d.root.elements['//ele'] # => <a foo:att='1' bar:att='2' att='&lt;'/>
    attrs = ele.attributes
    attrs['foo:att'] = '2' # => "2"
    attrs['baz:att'] = '3' # => "3"

When `value` is `nil`, deletes the attribute if it exists:

    attrs['baz:att'] = nil
    attrs.include?('baz:att') # => false

    # File rexml-3.4.0/lib/rexml/element.rb, line 2365
    def []=( name, value )
      if value.nil?             # Delete the named attribute
        attr = get_attribute(name)
        delete attr
        return
      end

      unless value.kind_of? Attribute
        if @element.document and @element.document.doctype
          value = Text::normalize( value, @element.document.doctype )
        else
          value = Text::normalize( value, nil )
        end
        value = Attribute.new(name, value)
      end
      value.element = @element
      old_attr = fetch(value.name, nil)
      if old_attr.nil?
        store(value.name, value)
      elsif old_attr.kind_of? Hash
        old_attr[value.prefix] = value
      elsif old_attr.prefix != value.prefix
        store value.name, {old_attr.prefix => old_attr,
                           value.prefix    => value}
      else
        store value.name, value
      end
      return @element
    end

add(attribute) → attribute click to toggle source

Adds attribute `attribute`, replacing the previous attribute of the same name if it exists; returns `attribute`:

    xml_string = <<-EOT
      <root xmlns:foo="http://foo" xmlns:bar="http://bar">
         <ele foo:att='1' bar:att='2' att='&lt;'/>
      </root>
    EOT
    d = REXML::Document.new(xml_string)
    ele = d.root.elements['//ele'] # => <a foo:att='1' bar:att='2' att='&lt;'/>
    attrs = ele.attributes
    attrs # => {"att"=>{"foo"=>foo:att='1', "bar"=>bar:att='2', ""=>att='&lt;'}}
    attrs.add(REXML::Attribute.new('foo:att', '2')) # => foo:att='2'
    attrs.add(REXML::Attribute.new('baz', '3')) # => baz='3'
    attrs.include?('baz') # => true

    # File rexml-3.4.0/lib/rexml/element.rb, line 2522
    def add( attribute )
      self[attribute.name] = attribute
    end

Also aliased as: <<
delete(name) → element click to toggle source
delete(attribute) → element

Removes a specified attribute if it exists; returns the attributes’ element.

When string argument `name` is given, removes the attribute of that name if it exists:

    xml_string = <<-EOT
      <root xmlns:foo="http://foo" xmlns:bar="http://bar">
         <ele foo:att='1' bar:att='2' att='&lt;'/>
      </root>
    EOT
    d = REXML::Document.new(xml_string)
    ele = d.root.elements['//ele'] # => <a foo:att='1' bar:att='2' att='&lt;'/>
    attrs = ele.attributes
    attrs.delete('foo:att') # => <ele bar:att='2' att='&lt;'/>
    attrs.delete('foo:att') # => <ele bar:att='2' att='&lt;'/>

When attribute argument `attribute` is given, removes that attribute if it exists:

    attr = REXML::Attribute.new('bar:att', '2')
    attrs.delete(attr) # => <ele att='&lt;'/> # => <ele att='&lt;'/>
    attrs.delete(attr) # => <ele att='&lt;'/> # => <ele/>

Calls superclass method

    # File rexml-3.4.0/lib/rexml/element.rb, line 2475
    def delete( attribute )
      name = nil
      prefix = nil
      if attribute.kind_of? Attribute
        name = attribute.name
        prefix = attribute.prefix
      else
        attribute =~ Namespace::NAMESPLIT
        prefix, name = $1, $2
        prefix = '' unless prefix
      end
      old = fetch(name, nil)
      if old.kind_of? Hash # the supplied attribute is one of many
        old.delete(prefix)
        if old.size == 1
          repl = nil
          old.each_value{|v| repl = v}
          store name, repl
        end
      elsif old.nil?
        return @element
      else # the supplied attribute is a top-level one
        super(name)
      end
      @element
    end

delete_all(name) → array_of_removed_attributes click to toggle source

Removes all attributes matching the given `name`; returns an array of the removed attributes:

    xml_string = <<-EOT
      <root xmlns:foo="http://foo" xmlns:bar="http://bar">
         <ele foo:att='1' bar:att='2' att='&lt;'/>
      </root>
    EOT
    d = REXML::Document.new(xml_string)
    ele = d.root.elements['//ele'] # => <a foo:att='1' bar:att='2' att='&lt;'/>
    attrs = ele.attributes
    attrs.delete_all('att') # => [att='&lt;']

    # File rexml-3.4.0/lib/rexml/element.rb, line 2544
    def delete_all( name )
      rv = []
      each_attribute { |attribute|
        rv << attribute if attribute.expanded_name == name
      }
      rv.each{ |attr| attr.remove }
      return rv
    end

each {|expanded_name, value| ... } click to toggle source

Calls the given block with each expanded-name/value pair:

    xml_string = <<-EOT
      <root xmlns:foo="http://foo" xmlns:bar="http://bar">
         <ele foo:att='1' bar:att='2' att='&lt;'/>
      </root>
    EOT
    d = REXML::Document.new(xml_string)
    ele = d.root.elements['//ele']   # => <a foo:att='1' bar:att='2' att='&lt;'/>
    ele.attributes.each do |expanded_name, value|
      p [expanded_name, value]
    end

Output:

    ["foo:att", "1"]
    ["bar:att", "2"]
    ["att", "<"]

    # File rexml-3.4.0/lib/rexml/element.rb, line 2283
    def each
      return to_enum(__method__) unless block_given?
      each_attribute do |attr|
        yield [attr.expanded_name, attr.value]
      end
    end

each_attribute {|attr| ... } click to toggle source

Calls the given block with each REXML::Attribute object:

    xml_string = <<-EOT
      <root xmlns:foo="http://foo" xmlns:bar="http://bar">
         <ele foo:att='1' bar:att='2' att='&lt;'/>
      </root>
    EOT
    d = REXML::Document.new(xml_string)
    ele = d.root.elements['//ele']   # => <a foo:att='1' bar:att='2' att='&lt;'/>
    ele.attributes.each_attribute do |attr|
      p [attr.class, attr]
    end

Output:

    [REXML::Attribute, foo:att='1']
    [REXML::Attribute, bar:att='2']
    [REXML::Attribute, att='&lt;']

    # File rexml-3.4.0/lib/rexml/element.rb, line 2250
    def each_attribute # :yields: attribute
      return to_enum(__method__) unless block_given?
      each_value do |val|
        if val.kind_of? Attribute
          yield val
        else
          val.each_value { |atr| yield atr }
        end
      end
    end

get_attribute(name) → attribute_object or nil click to toggle source

Returns the REXML::Attribute object for the given `name`:

    xml_string = <<-EOT
      <root xmlns:foo="http://foo" xmlns:bar="http://bar">
         <ele foo:att='1' bar:att='2' att='&lt;'/>
      </root>
    EOT
    d = REXML::Document.new(xml_string)
    ele = d.root.elements['//ele'] # => <a foo:att='1' bar:att='2' att='&lt;'/>
    attrs = ele.attributes
    attrs.get_attribute('foo:att')       # => foo:att='1'
    attrs.get_attribute('foo:att').class # => REXML::Attribute
    attrs.get_attribute('bar:att')       # => bar:att='2'
    attrs.get_attribute('att')           # => att='&lt;'
    attrs.get_attribute('nosuch')        # => nil

    # File rexml-3.4.0/lib/rexml/element.rb, line 2309
    def get_attribute( name )
      attr = fetch( name, nil )
      if attr.nil?
        return nil if name.nil?
        # Look for prefix
        name =~ Namespace::NAMESPLIT
        prefix, n = $1, $2
        if prefix
          attr = fetch( n, nil )
          # check prefix
          if attr == nil
          elsif attr.kind_of? Attribute
            return attr if prefix == attr.prefix
          else
            attr = attr[ prefix ]
            return attr
          end
        end
        element_document = @element.document
        if element_document and element_document.doctype
          expn = @element.expanded_name
          expn = element_document.doctype.name if expn.size == 0
          attr_val = element_document.doctype.attribute_of(expn, name)
          return Attribute.new( name, attr_val ) if attr_val
        end
        return nil
      end
      if attr.kind_of? Hash
        attr = attr[ @element.prefix ]
      end
      return attr
    end

get_attribute_ns(namespace, name) click to toggle source

Returns the REXML::Attribute object among the attributes that matches the given `namespace` and `name`:

    xml_string = <<-EOT
      <root xmlns:foo="http://foo" xmlns:bar="http://bar">
         <ele foo:att='1' bar:att='2' att='&lt;'/>
      </root>
    EOT
    d = REXML::Document.new(xml_string)
    ele = d.root.elements['//ele'] # => <a foo:att='1' bar:att='2' att='&lt;'/>
    attrs = ele.attributes
    attrs.get_attribute_ns('http://foo', 'att')    # => foo:att='1'
    attrs.get_attribute_ns('http://foo', 'nosuch') # => nil

    # File rexml-3.4.0/lib/rexml/element.rb, line 2570
    def get_attribute_ns(namespace, name)
      result = nil
      each_attribute() { |attribute|
        if name == attribute.name &&
          namespace == attribute.namespace() &&
          ( !namespace.empty? || !attribute.fully_expanded_name.index(':') )
          # foo will match xmlns:foo, but only if foo isn't also an attribute
          result = attribute if !result or !namespace.empty? or
                                !attribute.fully_expanded_name.index(':')
        end
      }
      result
    end

length click to toggle source

Returns the count of attributes:

    xml_string = <<-EOT
      <root xmlns:foo="http://foo" xmlns:bar="http://bar">
         <ele foo:att='1' bar:att='2' att='&lt;'/>
      </root>
    EOT
    d = REXML::Document.new(xml_string)
    ele = d.root.elements['//ele']   # => <a foo:att='1' bar:att='2' att='&lt;'/>
    ele.attributes.length # => 3

    # File rexml-3.4.0/lib/rexml/element.rb, line 2221
    def length
      c = 0
      each_attribute { c+=1 }
      c
    end

Also aliased as: size
namespaces click to toggle source

Returns a hash of name/value pairs for the namespaces:

    xml_string = '<a xmlns="foo" xmlns:x="bar" xmlns:y="twee" z="glorp"/>'
    d = REXML::Document.new(xml_string)
    d.root.attributes.namespaces # => {"xmlns"=>"foo", "x"=>"bar", "y"=>"twee"}

    # File rexml-3.4.0/lib/rexml/element.rb, line 2431
    def namespaces
      namespaces = {}
      each_attribute do |attribute|
        namespaces[attribute.name] = attribute.value if attribute.prefix == 'xmlns' or attribute.name == 'xmlns'
      end
      if @element.document and @element.document.doctype
        expn = @element.expanded_name
        expn = @element.document.doctype.name if expn.size == 0
        @element.document.doctype.attributes_of(expn).each {
          |attribute|
          namespaces[attribute.name] = attribute.value if attribute.prefix == 'xmlns' or attribute.name == 'xmlns'
        }
      end
      namespaces
    end

prefixes → array_of_prefix_strings click to toggle source

Returns an array of prefix strings in the attributes. The array does not include the default namespace declaration, if one exists.

    xml_string = '<a xmlns="foo" xmlns:x="bar" xmlns:y="twee" z="glorp"/>'
    d = REXML::Document.new(xml_string)
    d.root.attributes.prefixes # => ["x", "y"]

    # File rexml-3.4.0/lib/rexml/element.rb, line 2406
    def prefixes
      ns = []
      each_attribute do |attribute|
        ns << attribute.name if attribute.prefix == 'xmlns'
      end
      if @element.document and @element.document.doctype
        expn = @element.expanded_name
        expn = @element.document.doctype.name if expn.size == 0
        @element.document.doctype.attributes_of(expn).each {
          |attribute|
          ns << attribute.name if attribute.prefix == 'xmlns'
        }
      end
      ns
    end

size()
Alias for: length
to_a → array_of_attribute_objects click to toggle source

Returns an array of REXML::Attribute objects representing the attributes:

    xml_string = <<-EOT
      <root xmlns:foo="http://foo" xmlns:bar="http://bar">
         <ele foo:att='1' bar:att='2' att='&lt;'/>
      </root>
    EOT
    d = REXML::Document.new(xml_string)
    ele = d.root.elements['//ele']   # => <a foo:att='1' bar:att='2' att='&lt;'/>
    attrs = ele.attributes.to_a      # => [foo:att='1', bar:att='2', att='&lt;']
    attrs.first.class                # => REXML::Attribute

    # File rexml-3.4.0/lib/rexml/element.rb, line 2203
    def to_a
      enum_for(:each_attribute).to_a
    end