# 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

Constructor

element

  the `Element` of which this is an `Attribute`

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

### Public Instance Methods

<<( attribute )
Alias for: add
[](name) click to toggle source

Fetches an attribute value. If you want to get the `Attribute` itself, use `get_attribute`()

name

  an `XPath` attribute name. Namespaces are relevant here.

Returns

  the `String` value of the matching attribute, or `nil` if no matching attribute was found. This is the unnormalized value (with entities expanded).

    doc = Document.new "<a foo:att='1' bar:att='2' att='&lt;'/>"
    doc.root.attributes['att']         #-> '<'
    doc.root.attributes['bar:att']     #-> '2'

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

[]=( name, value ) click to toggle source

Sets an attribute, overwriting any existing attribute value by the same name. `Namespace` is significant.

name

  the name of the attribute

value

  (optional) If supplied, the value of the attribute. If nil, any existing matching attribute is deleted.

Returns

  Owning element

    doc = Document.new "<a x:foo='1' foo='3'/>"
    doc.root.attributes['y:foo'] = '2'
    doc.root.attributes['foo'] = '4'
    doc.root.attributes['x:foo'] = nil

    # File lib/rexml/element.rb, line 1112
    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
        # Check for conflicting namespaces
        raise ParseException.new(
          "Namespace conflict in adding attribute \"#{value.name}\": "+
          "Prefix \"#{old_attr.prefix}\" = "+
          "\"#{@element.namespace(old_attr.prefix)}\" and prefix "+
          "\"#{value.prefix}\" = \"#{@element.namespace(value.prefix)}\"") if
          value.prefix != "xmlns" and old_attr.prefix != "xmlns" and
          @element.namespace( old_attr.prefix ) ==
            @element.namespace( value.prefix )
          store value.name, { old_attr.prefix   => old_attr,
            value.prefix                => value }
      else
        store value.name, value
      end
      return @element
    end

add( attribute ) click to toggle source

Adds an attribute, overriding any existing attribute by the same name. Namespaces are significant.

attribute

  An `Attribute`

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

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

Removes an attribute

attribute

  either a `String`, which is the name of the attribute to remove – namespaces are significant here – or the attribute to remove.

Returns

  the owning element

    doc = Document.new "<a y:foo='0' x:foo='1' foo='3' z:foo='4'/>"
    doc.root.attributes.delete 'foo'   #-> <a y:foo='0' x:foo='1' z:foo='4'/>"
    doc.root.attributes.delete 'x:foo' #-> <a y:foo='0' z:foo='4'/>"
    attr = doc.root.attributes.get_attribute('y:foo')
    doc.root.attributes.delete attr    #-> <a z:foo='4'/>"

Calls superclass method `Hash#delete`

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

Deletes all attributes matching a name. Namespaces are significant.

name

  A `String`; all attributes that match this path will be removed

Returns

  an `Array` of the `Attributes` that were removed

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

Iterates over each attribute of an `Element`, yielding the expanded name and value as a pair of Strings.

    doc = Document.new '<a x="1" y="2"/>'
    doc.root.attributes.each {|name, value| p name+" => "+value }

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

each_attribute() { |attribute| ... } click to toggle source

Iterates over the attributes of an `Element`. Yields actual `Attribute` nodes, not `String` values.

    doc = Document.new '<a x="1" y="2"/>'
    doc.root.attributes.each_attribute {|attr|
      p attr.expanded_name+" => "+attr.value
    }

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

Fetches an attribute

name

  the name by which to search for the attribute. Can be a `prefix:name` namespace name.

Returns

  The first matching attribute, or nil if there was none. This

value is an `Attribute` node, not the `String` value of the attribute.

    doc = Document.new '<a x:foo="1" foo="2" bar="3"/>'
    doc.root.attributes.get_attribute("foo").value    #-> "2"
    doc.root.attributes.get_attribute("x:foo").value  #-> "1"

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

The `get_attribute_ns` method retrieves a method by its namespace and name. Thus it is possible to reliably identify an attribute even if an `XML` processor has changed the prefix.

`Method` contributed by Henrik Martensson

    # File lib/rexml/element.rb, line 1253
    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 number of attributes the owning `Element` contains.

    doc = Document "<a x='1' y='2' foo:x='3'/>"
    doc.root.attributes.length        #-> 3

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

Also aliased as: size
namespaces() click to toggle source

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

Returns an array of Strings containing all of the prefixes declared by this set of # attributes. The array does not include the default namespace declaration, if one exists.

    doc = Document.new("<a xmlns='foo' xmlns:x='bar' xmlns:y='twee' "+
          "z='glorp' p:k='gru'/>")
    prefixes = doc.root.attributes.prefixes    #-> ['x', 'y']

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

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