# 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 992
    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 1007
    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 1109
    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 1226
    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 1196
    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 1236
    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 1049
    def each
      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 1034
    def each_attribute # :yields: attribute
      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 1064
    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 1250
    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 1020
    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 1170
    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 1154
    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 1013
    def to_a
      enum_for(:each_attribute).to_a
    end