Class: REXML::Element

Class | REXML::Element
In: | rexml/element.rb
Parent: | Parent

Represents a tagged XML element. Elements are characterized by having children, attributes, and names, and can themselves be children.

### Methods

add_attribute add_attributes add_element add_namespace add_text attribute cdatas clone comments delete_attribute delete_element delete_namespace document each_element each_element_with_attribute each_element_with_text get_elements get_text has_attributes? has_elements? has_text? ignore_whitespace_nodes inspect instructions namespace namespaces new next_element node_type prefixes previous_element raw root root_node text text= texts whitespace write xpath

### Included Modules

Namespace

### Constants

UNDEFINED | = | "UNDEFINED";

### Attributes

attributes | [R] | Mechanisms for accessing attributes and child elements of this element.
context | [RW] | The context holds information about the processing environment, such as whitespace handling.
elements | [R] | Mechanisms for accessing attributes and child elements of this element.

### Public Class methods

new( arg = UNDEFINED, parent=nil, context=nil )

Constructor

arg: | if not supplied, will be set to the default value. If a String, the name of this object will be set to the argument. If an Element, the object will be shallowly cloned; name, attributes, and namespaces will be copied. Children will `not` be copied.
parent: | if supplied, must be a Parent, and will be used as the parent of this object.
context: | If supplied, must be a hash containing context items. Context items include:

- `:respect_whitespace` the value of this is :`all` or an array of strings being the names of the elements to respect whitespace for. Defaults to :`all`.
- `:compress_whitespace` the value can be :`all` or an array of strings being the names of the elements to ignore whitespace on. Overrides :`respect_whitespace`.
- `:ignore_whitespace_nodes` the value can be :`all` or an array of strings being the names of the elements in which to ignore whitespace-only nodes. If this is set, Text nodes which contain only whitespace will not be added to the document tree.
- `:raw` can be :`all`, or an array of strings being the names of the elements to process in raw mode. In raw mode, special characters in text is not converted to or from entities.

[Source]

    # File rexml/element.rb, line 58
                    def initialize( arg = UNDEFINED, parent=nil, context=nil )
                            super(parent)

                            @elements = Elements.new(self)
                            @attributes = Attributes.new(self)
                            @context = context

                            if arg.kind_of? String
                                    self.name = arg
                            elsif arg.kind_of? Element
                                    self.name = arg.expanded_name
                                    arg.attributes.each_attribute{ |attribute|
                                            @attributes << Attribute.new( attribute )
                                    }
                                    @context = arg.context
                            end
                    end

### Public Instance methods

add_attribute( key, value=nil )

Adds an attribute to this element, overwriting any existing attribute by the same name.

key: | can be either an Attribute or a String. If an Attribute, the attribute is added to the list of Element attributes. If String, the argument is used as the name of the new attribute, and the value parameter must be supplied.
value: | Required if `key` is a String, and ignored if the first argument is an Attribute. This is a String, and is used as the value of the new Attribute.
Returns: | the Attribute added

     e = Element.new 'e'
     e.add_attribute( 'a', 'b' )               #-> <e a='b'/>
     e.add_attribute( 'x:a', 'c' )             #-> <e a='b' x:a='c'/>
     e.add_attribute Attribute.new('b', 'd')   #-> <e a='b' x:a='c' b='d'/>

[Source]

    # File rexml/element.rb, line 591
                    def add_attribute( key, value=nil )
                            if key.kind_of? Attribute
                                    @attributes << key
                            else
                                    @attributes[key] = value
                            end
                    end

add_attributes(hash)

Add multiple attributes to this element.

hash: | is either a hash, or array of arrays

     el.add_attributes( {"name1"=>"value1", "name2"=>"value2"} )
     el.add_attributes( [ ["name1","value1"], ["name2"=>"value2"] ] )

[Source]

    # File rexml/element.rb, line 603
                    def add_attributes hash
                            if hash.kind_of? Hash
                                    hash.each_pair {|key, value| @attributes[key] = value }
                            elsif hash.kind_of? Array
                                    hash.each { |value| @attributes[ value[0] ] = value[1] }
                            end
                    end

add_element(element, attrs=nil)

Adds a child to this element, optionally setting attributes in the element.

element: | optional. If Element, the element is added. Otherwise, a new Element is constructed with the argument (see Element.initialize).
attrs: | If supplied, must be a Hash containing String name,value pairs, which will be used to set the attributes of the new Element.
Returns: | the Element that was added

     el = doc.add_element 'my-tag'
     el = doc.add_element 'my-tag', {'attr1'=>'val1', 'attr2'=>'val2'}
     el = Element.new 'my-tag'
     doc.add_element el

[Source]

    # File rexml/element.rb, line 295
                    def add_element element, attrs=nil
          raise "First argument must be either an element name, or an Element object" if element.nil?
                            el = @elements.add(element)
                            if attrs.kind_of? Hash
                                    attrs.each do |key, value|
                                            el.attributes[key]=value if key =~ /^xmlns:/
                                    end
                                    attrs.each do |key, value|
                                            el.attributes[key]=value if key !~ /^xmlns:/
                                    end
                            end
                            el
                    end

add_namespace( prefix, uri=nil )

Adds a namespace to this element.

prefix: | the prefix string, or the namespace URI if `uri` is not supplied
uri: | the namespace URI. May be nil, in which `prefix` is used as the URI

Evaluates to: this Element

     a = Element.new("a")
     a.add_namespace("xmlns:foo", "bar" )
     a.add_namespace("foo", "bar")  # shorthand for previous line
     a.add_namespace("twiddle")
     puts a   #-> <a xmlns:foo='bar' xmlns='twiddle'/>

[Source]

    # File rexml/element.rb, line 250
                    def add_namespace( prefix, uri=nil )
                            unless uri
                                    @attributes["xmlns"] = prefix
                            else
                                    prefix = "xmlns:#{prefix}" unless prefix =~ /^xmlns:/
                                    @attributes[ prefix ] = uri
                            end
                            self
                    end

add_text( text )

A helper method to add a Text child. Actual Text instances can be added with regular Parent methods, such as add() and <<()

text: | if a String, a new Text instance is created and added to the parent. If Text, the object is added directly.
Returns: | this Element

     e = Element.new('a')          #-> <e/>
     e.add_text 'foo'              #-> <e>foo</e>
     e.add_text Text.new(' bar')    #-> <e>foo bar</e>

Note that at the end of this example, the branch has 3 nodes; the ‘e’ element and 2 Text node children.

[Source]

    # File rexml/element.rb, line 528
                    def add_text( text )
                            if text.kind_of? String
                                    if @children[-1].kind_of? Text
                                            @children[-1] << text
                                            return
                                    end
                                    text = Text.new( text, whitespace(), nil, raw() )
                            end
                            self << text unless text.nil?
                            return self
                    end

attribute( name, namespace=nil )

Attributes #

[Source]

    # File rexml/element.rb, line 559
                    def attribute( name, namespace=nil )
                            prefix = ''
                            if namespace
                                    prefix = attributes.prefixes.each { |prefix|
                                            return "#{prefix}:" if namespace( prefix ) == namespace
                                    } || ''
                            end
                            attributes.get_attribute( "#{prefix}#{name}" )
                    end

cdatas()

Get an array of all CData children. IMMUTABLE

[Source]

    # File rexml/element.rb, line 635
                    def cdatas
                            find_all { |child| child.kind_of? CData }.freeze
                    end

clone()

Creates a shallow copy of self.

      d = Document.new "<a><b/><b/><c><d/></c></a>"
      new_a = d.root.clone
      puts new_a  # => "<a/>"

[Source]

    # File rexml/element.rb, line 96
                    def clone
                            Element.new self
                    end

comments()

Get an array of all Comment children. IMMUTABLE

[Source]

    # File rexml/element.rb, line 641
                    def comments
                            find_all { |child| child.kind_of? Comment }.freeze
                    end

delete_attribute(key)

Removes an attribute

key: | either an Attribute or a String. In either case, the attribute is found by matching the attribute name to the argument, and then removed. If no attribute is found, no action is taken.
Returns: | the attribute removed, or nil if this Element did not contain a matching attribute

     e = Element.new('E')
     e.add_attribute( 'name', 'Sean' )             #-> <E name='Sean'/>
     r = e.add_attribute( 'sur:name', 'Russell' )  #-> <E name='Sean' sur:name='Russell'/>
     e.delete_attribute( 'name' )                  #-> <E sur:name='Russell'/>
     e.delete_attribute( r )                       #-> <E/>

[Source]

    # File rexml/element.rb, line 624
                    def delete_attribute(key)
                            attr = @attributes.get_attribute(key)
                            attr.remove unless attr.nil?
                    end

delete_element(element)

Deletes a child element.

element: | Must be an `Element`, `String`, or `Integer`. If Element, the element is removed. If String, the element is found (via XPath) and removed. <em>This means that any parent can remove any descendant.<em> If Integer, the Element indexed by that number will be removed.
Returns: | the element that was removed.

     doc.delete_element "/a/b/c[@id='4']"
     doc.delete_element doc.elements["//k"]
     doc.delete_element 1

[Source]

    # File rexml/element.rb, line 320
                    def delete_element element
                            @elements.delete element
                    end

delete_namespace(namespace="xmlns")

Removes a namespace from this node. This only works if the namespace is actually declared in this node. If no argument is passed, deletes the default namespace.

Evaluates to: this element

     doc = Document.new "<a xmlns:foo='bar' xmlns='twiddle'/>"
     doc.root.delete_namespace
     puts doc     # -> <a xmlns:foo='bar'/>
     doc.root.delete_namespace 'foo'
     puts doc     # -> <a/>

[Source]

    # File rexml/element.rb, line 270
                    def delete_namespace namespace="xmlns"
                            namespace = "xmlns:#{namespace}" unless namespace == 'xmlns'
                            attribute = attributes.get_attribute(namespace)
                            attribute.remove unless attribute.nil?
                            self
                    end

document()

Evaluates to the document to which this element belongs, or nil if this element doesn’t belong to a document.

[Source]

    # File rexml/element.rb, line 131
                    def document
          rt = root
                            rt.parent if rt
                    end

each_element( xpath=nil ) {|Element| ...}

Synonym for Element.elements.each

[Source]

    # File rexml/element.rb, line 397
                    def each_element( xpath=nil, &block ) # :yields: Element
                            @elements.each( xpath, &block )
                    end

each_element_with_attribute( key, value=nil, max=0, name=nil ) {|Element| ...}

Iterates through the child elements, yielding for each Element that has a particular attribute set.

key: | the name of the attribute to search for
value: | the value of the attribute
max: | (optional) causes this method to return after yielding for this number of matching children
name: | (optional) if supplied, this is an XPath that filters the children to check.

     doc = Document.new "<a><b @id='1'/><c @id='2'/><d @id='1'/><e/></a>"
     # Yields b, c, d
     doc.root.each_element_with_attribute( 'id' ) {|e| p e}
     # Yields b, d
     doc.root.each_element_with_attribute( 'id', '1' ) {|e| p e}
     # Yields b
     doc.root.each_element_with_attribute( 'id', '1', 1 ) {|e| p e}
     # Yields d
     doc.root.each_element_with_attribute( 'id', '1', 0, 'd' ) {|e| p e}

[Source]

    # File rexml/element.rb, line 355
                    def each_element_with_attribute( key, value=nil, max=0, name=nil, &block ) # :yields: Element
                            each_with_something( proc {|child|
                                    if value.nil?
                                            child.attributes[key] != nil
                                    else
                                            child.attributes[key]==value
                                    end
                            }, max, name, &block )
                    end

each_element_with_text( text=nil, max=0, name=nil ) {|Element| ...}

Iterates through the children, yielding for each Element that has a particular text set.

text: | the text to search for. If nil, or not supplied, will itterate over all `Element` children that contain at least one `Text` node.
max: | (optional) causes this method to return after yielding for this number of matching children
name: | (optional) if supplied, this is an XPath that filters the children to check.

     doc = Document.new '<a><b>b</b><c>b</c><d>d</d><e/></a>'
     # Yields b, c, d
     doc.each_element_with_text {|e|p e}
     # Yields b, c
     doc.each_element_with_text('b'){|e|p e}
     # Yields b
     doc.each_element_with_text('b', 1){|e|p e}
     # Yields d
     doc.each_element_with_text(nil, 0, 'd'){|e|p e}

[Source]

    # File rexml/element.rb, line 386
                    def each_element_with_text( text=nil, max=0, name=nil, &block ) # :yields: Element
                            each_with_something( proc {|child|
                                    if text.nil?
                                            child.has_text?
                                    else
                                            child.text == text
                                    end
                            }, max, name, &block )
                    end

get_elements( xpath )

Synonym for Element.to_a This is a little slower than calling elements.each directly.

xpath: | any XPath by which to search for elements in the tree
Returns: | an array of Elements that match the supplied path

[Source]

    # File rexml/element.rb, line 405
                    def get_elements( xpath )
                            @elements.to_a( xpath )
                    end

get_text(path = nil)

Returns the first child Text node, if any, or `nil` otherwise. This method returns the actual `Text` node, rather than the String content.

     doc = Document.new "<p>some text <b>this is bold!</b> more text</p>"
     # The element 'p' has two text elements, "some text " and " more text".
     doc.root.get_text.value            #-> "some text "

[Source]

    # File rexml/element.rb, line 466
                    def get_text path = nil
                            rv = nil
                            if path
                                    element = @elements[ path ]
                                    rv = element.get_text unless element.nil?
                            else
                                    rv = @children.find { |node| node.kind_of? Text }
                            end
                            return rv
                    end

has_attributes?()

Evaluates to `true` if this element has any attributes set, false otherwise.

[Source]

    # File rexml/element.rb, line 571
                    def has_attributes?
                            return !@attributes.empty?
                    end

has_elements?()

Evaluates to `true` if this element has at least one child Element

     doc = Document.new "<a><b/><c>Text</c></a>"
     doc.root.has_elements               # -> true
     doc.elements["/a/b"].has_elements   # -> false
     doc.elements["/a/c"].has_elements   # -> false

[Source]

    # File rexml/element.rb, line 329
                    def has_elements?
                            !@elements.empty?
                    end

has_text?()

Evaluates to `true` if this element has at least one Text child

[Source]

    # File rexml/element.rb, line 437
                    def has_text?
                            not text().nil?
                    end

ignore_whitespace_nodes()

[Source]

    # File rexml/element.rb, line 161
                    def ignore_whitespace_nodes
                            @ignore_whitespace_nodes = false
                            if @context
                                    if @context[:ignore_whitespace_nodes]
                                            @ignore_whitespace_nodes =
                                                    (@context[:ignore_whitespace_nodes] == :all or
                                                     @context[:ignore_whitespace_nodes].include? expanded_name)
                                    end
                            end
                    end

inspect()

[Source]

    # File rexml/element.rb, line 76
        def inspect
          rv = "<#@expanded_name"

          @attributes.each_attribute do |attr|
            rv << " "
            attr.write( rv, 0 )
          end

          if children.size > 0
            rv << "> ... </>"
          else
            rv << "/>"
          end
        end

instructions()

Get an array of all Instruction children. IMMUTABLE

[Source]

    # File rexml/element.rb, line 647
                    def instructions
                            find_all { |child| child.kind_of? Instruction }.freeze
                    end

namespace(prefix=nil)

Evalutas to the URI for a prefix, or the empty string if no such namespace is declared for this element. Evaluates recursively for ancestors. Returns the default namespace, if there is one.

prefix: | the prefix to search for. If not supplied, returns the default namespace if one exists
Returns: | the namespace URI as a String, or nil if no such namespace exists. If the namespace is undefined, returns an empty string

     doc = Document.new("<a xmlns='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
     b = doc.elements['//b']
     b.namespace           # -> '1'
     b.namespace("y")      # -> '2'

[Source]

    # File rexml/element.rb, line 222
                    def namespace(prefix=nil)
                            if prefix.nil?
                                    prefix = prefix()
                            end
                            if prefix == ''
                                    prefix = "xmlns"
                            else
                                    prefix = "xmlns:#{prefix}" unless prefix[0,5] == 'xmlns'
                            end
                            ns = attributes[ prefix ]
                            ns = parent.namespace(prefix) if ns.nil? and parent
                            ns = '' if ns.nil? and prefix == 'xmlns'
                            return ns
                    end

namespaces()

[Source]

    # File rexml/element.rb, line 202
                    def namespaces
                            namespaces = []
                            namespaces = parent.namespaces if parent
                            namespaces |= attributes.namespaces
                            return namespaces
                    end

next_element()

Returns the next sibling that is an element, or nil if there is no Element sibling after this one

     doc = Document.new '<a><b/>text<c/></a>'
     doc.root.elements['b'].next_element          #-> <c/>
     doc.root.elements['c'].next_element          #-> nil

[Source]

    # File rexml/element.rb, line 414
                    def next_element
                            element = next_sibling
                            element = element.next_sibling until element.nil? or element.kind_of? Element
                            return element
                    end

node_type()

[Source]

    # File rexml/element.rb, line 540
        def node_type
          :element
        end

prefixes()

Evaluates to an `Array` containing the prefixes (names) of all defined namespaces at this context node.

     doc = Document.new("<a xmlns:x='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
     doc.elements['//b'].prefixes # -> ['x', 'y']

[Source]

    # File rexml/element.rb, line 195
                    def prefixes
                            prefixes = []
                            prefixes = parent.prefixes if parent
                            prefixes |= attributes.prefixes
                            return prefixes
                    end

previous_element()

Returns the previous sibling that is an element, or nil if there is no Element sibling prior to this one

     doc = Document.new '<a><b/>text<c/></a>'
     doc.root.elements['c'].previous_element          #-> <b/>
     doc.root.elements['b'].previous_element          #-> nil

[Source]

    # File rexml/element.rb, line 425
                    def previous_element
                            element = previous_sibling
                            element = element.previous_sibling until element.nil? or element.kind_of? Element
                            return element
                    end

raw()

Evaluates to `true` if raw mode is set for this element. This is the case if the context has :`raw` set to :`all` or an array containing the name of this element.

The evaluation is tested against `expanded_name`, and so is namespace sensitive.

[Source]

    # File rexml/element.rb, line 178
                    def raw
                            @raw = (@context and @context[:raw] and
                            (@context[:raw] == :all or
                            @context[:raw].include? expanded_name))
                            @raw
                    end

root()

[Source]

    # File rexml/element.rb, line 123
        def root
          return elements[1] if self.kind_of? Document
          return self if parent.kind_of? Document or parent.nil?
          return parent.root
        end

root_node()

Evaluates to the root node of the document that this element belongs to. If this element doesn’t belong to a document, but does belong to another Element, the parent’s root will be returned, until the earliest ancestor is found.

Note that this is not the same as the document element. In the following example, <a> is the document element, and the root node is the parent node of the document element. You may ask yourself why the root node is useful: consider the doctype and XML declaration, and any processing instructions before the document element… they are children of the root node, or siblings of the document element. The only time this isn’t true is when an Element is created that is not part of any Document. In this case, the ancestor that has no parent acts as the root node.

     d = Document.new '<a><b><c/></b></a>'
     a = d[1] ; c = a[1][1]
     d.root_node == d   # TRUE
     a.root_node        # namely, d
     c.root_node        # again, d

[Source]

    # File rexml/element.rb, line 119
                    def root_node
                            parent.nil? ? self : parent.root_node
                    end

text( path = nil )

A convenience method which returns the String value of the first child text element, if one exists, and `nil` otherwise.

Note that an element may have multiple Text elements, perhaps separated by other children. Be aware that this method only returns the first Text node.

This method returns the `value` of the first text child node, which ignores the `raw` setting, so always returns normalized text. See the Text::value documentation.

     doc = Document.new "<p>some text <b>this is bold!</b> more text</p>"
     # The element 'p' has two text elements, "some text " and " more text".
     doc.root.text              #-> "some text "

[Source]

    # File rexml/element.rb, line 455
                    def text( path = nil )
                            rv = get_text(path)
                            return rv.value unless rv.nil?
                            nil
                    end

text=( text )

Sets the first Text child of this object. See text() for a discussion about Text children.

If a Text child already exists, the child is replaced by this content. This means that Text content can be deleted by calling this method with a nil argument. In this case, the next Text child becomes the first Text child. In no case is the order of any siblings disturbed.

text: | If a String, a new Text child is created and added to this Element as the first Text child. If Text, the text is set as the first Child element. If nil, then any existing first Text child is removed.
Returns: | this Element.

     doc = Document.new '<a><b/></a>'
     doc.root.text = 'Sean'      #-> '<a><b/>Sean</a>'
     doc.root.text = 'Elliott'   #-> '<a><b/>Elliott</a>'
     doc.root.add_element 'c'    #-> '<a><b/>Elliott<c/></a>'
     doc.root.text = 'Russell'   #-> '<a><b/>Russell<c/></a>'
     doc.root.text = nil         #-> '<a><b/><c/></a>'

[Source]

    # File rexml/element.rb, line 497
                    def text=( text )
          if text.kind_of? String
            text = Text.new( text, whitespace(), nil, raw() )
          elsif text and !text.kind_of? Text
            text = Text.new( text.to_s, whitespace(), nil, raw() )
          end

                            old_text = get_text
                            if text.nil?
                                    old_text.remove unless old_text.nil?
                            else
                                    if old_text.nil?
                                            self << text
                                    else
                                            old_text.replace_with( text )
                                    end
                            end
                            return self
                    end

texts()

Get an array of all Text children. IMMUTABLE

[Source]

    # File rexml/element.rb, line 653
                    def texts
                            find_all { |child| child.kind_of? Text }.freeze
                    end

whitespace()

Evaluates to `true` if whitespace is respected for this element. This is the case if:

1. Neither :`respect_whitespace` nor :`compress_whitespace` has any value
2. The context has :`respect_whitespace` set to :`all` or an array containing the name of this element, and :`compress_whitespace` isn’t set to :`all` or an array containing the name of this element.

The evaluation is tested against `expanded_name`, and so is namespace sensitive.

[Source]

    # File rexml/element.rb, line 145
                    def whitespace
                            @whitespace = nil
                            if @context
                                    if @context[:respect_whitespace]
                                            @whitespace = (@context[:respect_whitespace] == :all or
                                                                                                     @context[:respect_whitespace].include? expanded_name)
                                    end
                                    @whitespace = false if (@context[:compress_whitespace] and
                                            (@context[:compress_whitespace] == :all or
                                             @context[:compress_whitespace].include? expanded_name)
                                    )
                            end
                            @whitespace = true unless @whitespace == false
                            @whitespace
                    end

write(writer=$stdout, indent=-1, transitive=false, ie_hack=false)

Writes out this element, and recursively, all children.

output: | output an object which supports ’<< string’; this is where the

      document will be written.

indent: | An integer. If -1, no indenting will be used; otherwise, the indentation will be this number of spaces, and children will be indented an additional amount. Defaults to -1
transitive: | If transitive is true and indent is >= 0, then the output will be pretty-printed in such a way that the added whitespace does not affect the parse tree of the document
ie_hack: | Internet Explorer is the worst piece of crap to have ever been written, with the possible exception of Windows itself. Since IE is unable to parse proper XML, we have to provide a hack to generate XML that IE’s limited abilities can handle. This hack inserts a space before the /> on empty tags. Defaults to false

     out = ''
     doc.write( out )     #-> doc is written to the string 'out'
     doc.write( $stdout ) #-> doc written to the console

[Source]

    # File rexml/element.rb, line 679
                    def write(writer=$stdout, indent=-1, transitive=false, ie_hack=false)
                            #print "ID:#{indent}"
                            writer << "<#@expanded_name"

                            @attributes.each_attribute do |attr|
                                    writer << " "
                                    attr.write( writer, indent )
                            end unless @attributes.empty?

                            if @children.empty?
            if transitive and indent>-1
              writer << "\n"
              indent( writer, indent )
            elsif ie_hack
              writer << " "
            end
                                    writer << "/"
                            else
                                    if transitive and indent>-1 and !@children[0].kind_of? Text
                                            writer << "\n"
                                            indent writer, indent+1
                                    end
                                    writer << ">"
                                    write_children( writer, indent, transitive, ie_hack )
                                    writer << "</#{expanded_name}"
                            end
                            if transitive and indent>-1 and !@children.empty?
                                    writer << "\n"
                                    indent -= 1 if next_sibling.nil?
                                    indent(writer, indent)
                            end
                            writer << ">"
                    end

xpath()

[Source]

    # File rexml/element.rb, line 544
        def xpath
          path_elements = []
          cur = self
          path_elements << __to_xpath_helper( self )
          while cur.parent
            cur = cur.parent
            path_elements << __to_xpath_helper( cur )
          end
          return path_elements.reverse.join( "/" )
        end

[Validate]