Mechanisms for accessing attributes and child elements of this element.
Mechanisms for accessing attributes and child elements of this element.
The context holds information about the processing environment, such as whitespace handling.
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 59
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
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 willnot
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.
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 567
def [](name_or_index)
case name_or_index
when String
attributes[name_or_index]
when Symbol
attributes[name_or_index.to_s]
else
super
end
end
Fetches an attribute value or a child.
If String or Symbol
is specified, it’s treated as attribute name. Attribute
value as String or nil
is returned. This case is shortcut of attributes[name]
.
If Integer
is specified, it’s treated as the index of child. It returns Nth child.
doc = REXML::Document.new("<a attr='1'><b/><c/></a>") doc.root["attr"] # => "1" doc.root.attributes["attr"] # => "1" doc.root[1] # => <c/>
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 729
def __to_xpath_helper node
rv = node.expanded_name.clone
if node.parent
results = node.parent.find_all {|n|
n.kind_of?(REXML::Element) and n.expanded_name == node.expanded_name
}
if results.length > 1
idx = results.index( node )
rv << "[#{idx+1}]"
end
end
rv
end
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 624
def add_attribute( key, value=nil )
if key.kind_of? Attribute
@attributes << key
else
@attributes[key] = value
end
end
Adds an attribute to this element, overwriting any existing attribute by the same name.
- key
-
can be either an
Attribute
or a String. If anAttribute
, the attribute is added to the list ofElement
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 anAttribute
. This is a String, and is used as the value of the newAttribute
. This should be the unnormalized value of the attribute (without entities). - 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'/>
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 636
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 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"] ] )
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 296
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)
attrs.each do |key, value|
el.attributes[key]=value
end if attrs.kind_of? Hash
el
end
Adds a child to this element, optionally setting attributes in the element.
- element
-
optional. If
Element
, the element is added. Otherwise, a newElement
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 newElement
. - 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
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 251
def add_namespace( prefix, uri=nil )
unless uri
@attributes["xmlns"] = prefix
else
prefix = "xmlns:#{prefix}" unless prefix =~ /^xmlns:/
@attributes[ prefix ] = uri
end
self
end
Adds a namespace to this element.
- prefix
-
the prefix string, or the namespace
URI
ifuri
is not supplied - uri
-
the namespace
URI
. May be nil, in whichprefix
is used as theURI
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'/>
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 523
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
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. IfText
, 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.
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 578
def attribute( name, namespace=nil )
prefix = nil
if namespaces.respond_to? :key
prefix = namespaces.key(namespace) if namespace
else
prefix = namespaces.index(namespace) if namespace
end
prefix = nil if prefix == 'xmlns'
ret_val =
attributes.get_attribute( "#{prefix ? prefix + ':' : ''}#{name}" )
return ret_val unless ret_val.nil?
return nil if prefix.nil?
# now check that prefix'es namespace is not the same as the
# default namespace
return nil unless ( namespaces[ prefix ] == namespaces[ 'xmlns' ] )
attributes.get_attribute( name )
end
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 668
def cdatas
find_all { |child| child.kind_of? CData }.freeze
end
Get an array of all CData
children. IMMUTABLE
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 97
def clone
self.class.new self
end
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/>"
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 674
def comments
find_all { |child| child.kind_of? Comment }.freeze
end
Get an array of all Comment
children. IMMUTABLE
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 657
def delete_attribute(key)
attr = @attributes.get_attribute(key)
attr.remove unless attr.nil?
end
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/>
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 316
def delete_element element
@elements.delete element
end
Deletes a child element.
- element
-
Must be an
Element
,String
, orInteger
. IfElement
, the element is removed. If String, the element is found (viaXPath
) and removed. <em>This means that any parent can remove any descendant.<em> IfInteger
, theElement
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
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 271
def delete_namespace namespace="xmlns"
namespace = "xmlns:#{namespace}" unless namespace == 'xmlns'
attribute = attributes.get_attribute(namespace)
attribute.remove unless attribute.nil?
self
end
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/>
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 132
def document
rt = root
rt.parent if rt
end
Evaluates to the document to which this element belongs, or nil if this element doesn’t belong to a document.
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 393
def each_element( xpath=nil, &block ) # :yields: Element
@elements.each( xpath, &block )
end
Synonym for Element.elements
.each
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 351
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
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}
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 382
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
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 iterate over all
Element
children that contain at least oneText
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}
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 744
def each_with_something( test, max=0, name=nil )
num = 0
@elements.each( name ){ |child|
yield child if test.call(child) and num += 1
return if max>0 and num == max
}
end
A private helper method
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 401
def get_elements( xpath )
@elements.to_a( xpath )
end
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 462
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
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 "
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 603
def has_attributes?
return !@attributes.empty?
end
Evaluates to true
if this element has any attributes set, false otherwise.
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 325
def has_elements?
!@elements.empty?
end
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
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 433
def has_text?
not text().nil?
end
Evaluates to true
if this element has at least one Text
child
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 162
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
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 77
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
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 680
def instructions
find_all { |child| child.kind_of? Instruction }.freeze
end
Get an array of all Instruction
children. IMMUTABLE
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 223
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
Evaluates 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'
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 203
def namespaces
namespaces = {}
namespaces = parent.namespaces if parent
namespaces = namespaces.merge( attributes.namespaces )
return namespaces
end
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 410
def next_element
element = next_sibling
element = element.next_sibling until element.nil? or element.kind_of? Element
return element
end
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
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 535
def node_type
:element
end
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 196
def prefixes
prefixes = []
prefixes = parent.prefixes if parent
prefixes |= attributes.prefixes
return prefixes
end
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']
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 421
def previous_element
element = previous_sibling
element = element.previous_sibling until element.nil? or element.kind_of? Element
return element
end
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
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 179
def raw
@raw = (@context and @context[:raw] and
(@context[:raw] == :all or
@context[:raw].include? expanded_name))
@raw
end
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.
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 124
def root
return elements[1] if self.kind_of? Document
return self if parent.kind_of? Document or parent.nil?
return parent.root
end
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 120
def root_node
parent.nil? ? self : parent.root_node
end
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
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 451
def text( path = nil )
rv = get_text(path)
return rv.value unless rv.nil?
nil
end
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 "
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 493
def text=( text )
if text.kind_of? String
text = Text.new( text, whitespace(), nil, raw() )
elsif !text.nil? 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
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 thisElement
as the firstText
child. IfText
, the text is set as the firstChild
element. If nil, then any existing firstText
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>'
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 686
def texts
find_all { |child| child.kind_of? Text }.freeze
end
Get an array of all Text
children. IMMUTABLE
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 146
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
Evaluates to true
if whitespace is respected for this element. This is the case if:
-
Neither :
respect_whitespace
nor :compress_whitespace
has any value -
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.
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 712
def write(output=$stdout, indent=-1, transitive=false, ie_hack=false)
Kernel.warn("#{self.class.name}.write is deprecated. See REXML::Formatters", uplevel: 1)
formatter = if indent > -1
if transitive
require "rexml/formatters/transitive"
REXML::Formatters::Transitive.new( indent, ie_hack )
else
REXML::Formatters::Pretty.new( indent, ie_hack )
end
else
REXML::Formatters::Default.new( ie_hack )
end
formatter.write( self, output )
end
DEPRECATED
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
-
This hack inserts a space before the /> on empty tags to address a limitation of Internet Explorer. Defaults to false
out = '' doc.write( out ) #-> doc is written to the string 'out' doc.write( $stdout ) #-> doc written to the console
# File tmp/rubies/ruby-2.5.9/lib/rexml/element.rb, line 539
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