Class: REXML::Element
- Includes:
- Namespace
- Defined in:
- lib/rexml/element.rb
Overview
An REXML::Element object represents an XML element.
An element:
-
Has a name (string).
-
May have a parent (another element).
-
Has zero or more children (other elements, text, CDATA, processing instructions, and comments).
-
Has zero or more siblings (other elements, text, CDATA, processing instructions, and comments).
-
Has zero or more named attributes.
In a Hurry?
If you’re somewhat familiar with XML and have a particular task in mind, you may want to see the tasks pages, and in particular, the tasks page for elements.
Name
An element has a name, which is initially set when the element is created:
e = REXML::Element.new('foo')
e.name # => "foo"
The name may be changed:
e.name = 'bar'
e.name # => "bar"
Parent
An element may have a parent.
Its parent may be assigned explicitly when the element is created:
e0 = REXML::Element.new('foo')
e1 = REXML::Element.new('bar', e0)
e1.parent # => <foo> ... </>
Note: the representation of an element always shows the element’s name. If the element has children, the representation indicates that by including an ellipsis (...).
The parent may be assigned explicitly at any time:
e2 = REXML::Element.new('baz')
e1.parent = e2
e1.parent # => <baz/>
When an element is added as a child, its parent is set automatically:
e1.add_element(e0)
e0.parent # => <bar> ... </>
For an element that has no parent, method parent returns nil.
Children
An element has zero or more children. The children are an ordered collection of all objects whose parent is the element itself.
The children may include any combination of elements, text, comments, processing instructions, and CDATA. (This example keeps things clean by controlling whitespace via a context setting.)
xml_string = <<-EOT
<root>
<ele_0/>
text 0
<!--comment 0-->
<?target_0 pi_0?>
<![CDATA[cdata 0]]>
<ele_1/>
text 1
<!--comment 1-->
<?target_0 pi_1?>
<![CDATA[cdata 1]]>
</root>
EOT
context = {ignore_whitespace_nodes: :all, compress_whitespace: :all}
d = REXML::Document.new(xml_string, context)
root = d.root
root.children.size # => 10
root.each {|child| p "#{child.class}: #{child}" }
Output:
"REXML::Element: <ele_0/>"
"REXML::Text: \n text 0\n "
"REXML::Comment: comment 0"
"REXML::Instruction: <?target_0 pi_0?>"
"REXML::CData: cdata 0"
"REXML::Element: <ele_1/>"
"REXML::Text: \n text 1\n "
"REXML::Comment: comment 1"
"REXML::Instruction: <?target_0 pi_1?>"
"REXML::CData: cdata 1"
A child may be added using inherited methods Parent#insert_before or Parent#insert_after:
xml_string = '<root><a/><c/><d/></root>'
d = REXML::Document.new(xml_string)
root = d.root
c = d.root[1] # => <c/>
root.insert_before(c, REXML::Element.new('b'))
root.to_a # => [<a/>, <b/>, <c/>, <d/>]
A child may be replaced using Parent#replace_child:
root.replace_child(c, REXML::Element.new('x'))
root.to_a # => [<a/>, <b/>, <x/>, <d/>]
A child may be removed using Parent#delete:
x = root[2] # => <x/>
root.delete(x)
root.to_a # => [<a/>, <b/>, <d/>]
Siblings
An element has zero or more siblings, which are the other children of the element’s parent.
In the example above, element ele_1 is between a CDATA sibling and a text sibling:
ele_1 = root[5] # => <ele_1/>
ele_1.previous_sibling # => "cdata 0"
ele_1.next_sibling # => "\n text 1\n "
Attributes
An element has zero or more named attributes.
A new element has no attributes:
e = REXML::Element.new('foo')
e.attributes # => {}
Attributes may be added:
e.add_attribute('bar', 'baz')
e.add_attribute('bat', 'bam')
e.attributes.size # => 2
e['bar'] # => "baz"
e['bat'] # => "bam"
An existing attribute may be modified:
e.add_attribute('bar', 'bad')
e.attributes.size # => 2
e['bar'] # => "bad"
An existing attribute may be deleted:
e.delete_attribute('bar')
e.attributes.size # => 1
e['bar'] # => nil
What’s Here
To begin with, what’s elsewhere?
Class REXML::Element inherits from its ancestor classes:
-
REXML::Child
-
REXML::Parent
REXML::Element itself and its ancestors also include modules:
-
REXML::Namespace
-
REXML::Node
-
REXML::XMLTokens
Methods for Creating an Element
- ::new
-
Returns a new empty element.
- #clone
-
Returns a clone of another element.
Methods for Attributes
- [attribute_name]
-
Returns an attribute value.
- #add_attribute
-
Adds a new attribute.
- #add_attributes
-
Adds multiple new attributes.
- #attribute
-
Returns the attribute value for a given name and optional namespace.
- #delete_attribute
-
Removes an attribute.
Methods for Children
- [index]
-
Returns the child at the given offset.
- #add_element
-
Adds an element as the last child.
- #delete_element
-
Deletes a child element.
- #each_element
-
Calls the given block with each child element.
- #each_element_with_attribute
-
Calls the given block with each child element that meets given criteria, which can include the attribute name.
- #each_element_with_text
-
Calls the given block with each child element that meets given criteria, which can include text.
- #get_elements
-
Returns an array of element children that match a given xpath.
Methods for Text Children
- #add_text
-
Adds a text node to the element.
- #get_text
-
Returns a text node that meets specified criteria.
- #text
-
Returns the text string from the first node that meets specified criteria.
- #texts
-
Returns an array of the text children of the element.
- #text=
-
Adds, removes, or replaces the first text child of the element
Methods for Other Children
- #cdatas
-
Returns an array of the cdata children of the element.
- #comments
-
Returns an array of the comment children of the element.
- #instructions
-
Returns an array of the instruction children of the element.
Methods for Namespaces
- #add_namespace
-
Adds a namespace to the element.
- #delete_namespace
-
Removes a namespace from the element.
- #namespace
-
Returns the string namespace URI for the element.
- #namespaces
-
Returns a hash of all defined namespaces in the element.
- #prefixes
-
Returns an array of the string prefixes (names) of all defined namespaces in the element
Methods for Querying
- #document
-
Returns the document, if any, that the element belongs to.
- #root
-
Returns the most distant element (not document) ancestor of the element.
- #root_node
-
Returns the most distant ancestor of the element.
- #xpath
-
Returns the string xpath to the element relative to the most distant parent
- #has_attributes?
-
Returns whether the element has attributes.
- #has_elements?
-
Returns whether the element has elements.
- #has_text?
-
Returns whether the element has text.
- #next_element
-
Returns the next sibling that is an element.
- #previous_element
-
Returns the previous sibling that is an element.
- #raw
-
Returns whether raw mode is set for the element.
- #whitespace
-
Returns whether whitespace is respected for the element.
- #ignore_whitespace_nodes
-
Returns whether whitespace nodes are to be ignored for the element.
- #node_type
-
Returns symbol
:element.
One More Method
- #inspect
-
Returns a string representation of the element.
Accessors
- #elements
-
Returns the REXML::Elements object for the element.
- #attributes
-
Returns the REXML::Attributes object for the element.
- #context
-
Returns or sets the context hash for the element.
Direct Known Subclasses
Constant Summary collapse
- UNDEFINED =
The default name
"UNDEFINED"
Constants included from Namespace
Namespace::NAMESPLIT, Namespace::NAME_WITHOUT_NAMESPACE
Constants included from XMLTokens
XMLTokens::NAME, XMLTokens::NAMECHAR, XMLTokens::NAME_CHAR, XMLTokens::NAME_START_CHAR, XMLTokens::NAME_STR, XMLTokens::NCNAME_STR, XMLTokens::NMTOKEN, XMLTokens::NMTOKENS, XMLTokens::REFERENCE
Instance Attribute Summary collapse
-
#attributes ⇒ Object
readonly
Mechanisms for accessing attributes and child elements of this element.
-
#context ⇒ Object
The context holds information about the processing environment, such as whitespace handling.
-
#elements ⇒ Object
readonly
Mechanisms for accessing attributes and child elements of this element.
Attributes included from Namespace
#expanded_name, #name, #prefix
Attributes inherited from Child
Instance Method Summary collapse
-
#[](name_or_index) ⇒ Object
:call-seq: [index] -> object [attr_name] -> attr_value [attr_sym] -> attr_value.
-
#add_attribute(key, value = nil) ⇒ Object
:call-seq: add_attribute(name, value) -> value add_attribute(attribute) -> attribute.
-
#add_attributes(hash) ⇒ Object
:call-seq: add_attributes(hash) -> hash add_attributes(array).
-
#add_element(element, attrs = nil) ⇒ Object
:call-seq: add_element(name, attributes = nil) -> new_element add_element(element, attributes = nil) -> element.
-
#add_namespace(prefix, uri = nil) ⇒ Object
:call-seq: add_namespace(prefix, uri = nil) -> self.
-
#add_text(text) ⇒ Object
:call-seq: add_text(string) -> nil add_text(text_node) -> self.
-
#attribute(name, namespace = nil) ⇒ Object
:call-seq: attribute(name, namespace = nil).
-
#cdatas ⇒ Object
:call-seq: cdatas -> array_of_cdata_children.
-
#clone ⇒ Object
:call-seq: clone -> new_element.
-
#comments ⇒ Object
:call-seq: comments -> array_of_comment_children.
-
#delete_attribute(key) ⇒ Object
:call-seq: delete_attribute(name) -> removed_attribute or nil.
-
#delete_element(element) ⇒ Object
:call-seq: delete_element(index) -> removed_element or nil delete_element(element) -> removed_element or nil delete_element(xpath) -> removed_element or nil.
-
#delete_namespace(namespace = "xmlns") ⇒ Object
:call-seq: delete_namespace(namespace = ‘xmlns’) -> self.
-
#document ⇒ Object
:call-seq: document -> document or nil.
-
#each_element(xpath = nil, &block) ⇒ Object
:call-seq: each_element {|e| … }.
-
#each_element_with_attribute(key, value = nil, max = 0, name = nil, &block) ⇒ Object
:call-seq: each_element_with_attribute(attr_name, value = nil, max = 0, xpath = nil) {|e| … }.
-
#each_element_with_text(text = nil, max = 0, name = nil, &block) ⇒ Object
:call-seq: each_element_with_text(text = nil, max = 0, xpath = nil) {|e| … }.
-
#get_elements(xpath) ⇒ Object
:call-seq: get_elements(xpath).
-
#get_text(path = nil) ⇒ Object
:call-seq: get_text(xpath = nil) -> text_node or nil.
-
#has_attributes? ⇒ Boolean
:call-seq: has_attributes? -> true or false.
-
#has_elements? ⇒ Boolean
:call-seq: has_elements?.
-
#has_text? ⇒ Boolean
:call-seq: has_text? -> true or false.
-
#ignore_whitespace_nodes ⇒ Object
:call-seq: ignore_whitespace_nodes.
-
#initialize(arg = UNDEFINED, parent = nil, context = nil) ⇒ Element
constructor
:call-seq: Element.new(name = ‘UNDEFINED’, parent = nil, context = nil) -> new_element Element.new(element, parent = nil, context = nil) -> new_element.
-
#inspect ⇒ Object
:call-seq: inspect -> string.
-
#instructions ⇒ Object
:call-seq: instructions -> array_of_instruction_children.
-
#namespace(prefix = nil) ⇒ Object
:call-seq: namespace(prefix = nil) -> string_uri or nil.
-
#namespaces ⇒ Object
:call-seq: namespaces -> array_of_namespace_names.
-
#next_element ⇒ Object
:call-seq: next_element.
-
#node_type ⇒ Object
:call-seq: node_type -> :element.
-
#prefixes ⇒ Object
:call-seq: prefixes -> array_of_namespace_prefixes.
-
#previous_element ⇒ Object
:call-seq: previous_element.
-
#raw ⇒ Object
:call-seq: raw.
-
#root ⇒ Object
:call-seq: root -> element.
-
#root_node ⇒ Object
:call-seq: root_node -> document or element.
-
#text(path = nil) ⇒ Object
:call-seq: text(xpath = nil) -> text_string or nil.
-
#text=(text) ⇒ Object
:call-seq: text = string -> string text = nil -> nil.
-
#texts ⇒ Object
:call-seq: texts -> array_of_text_children.
-
#whitespace ⇒ Object
:call-seq: whitespace.
-
#write(output = $stdout, indent = -1,, transitive = false, ie_hack = false) ⇒ Object
DEPRECATED See REXML::Formatters.
-
#xpath ⇒ Object
:call-seq: xpath -> string_xpath.
Methods included from Namespace
#fully_expanded_name, #has_name?
Methods inherited from Parent
#[]=, #add, #deep_clone, #delete, #delete_at, #delete_if, #each, #each_index, #index, #insert_after, #insert_before, #parent?, #replace_child, #size, #to_a, #unshift
Methods inherited from Child
#bytes, #next_sibling=, #previous_sibling=, #remove, #replace_with
Methods included from Node
#each_recursive, #find_first_recursive, #indent, #index_in_parent, #next_sibling_node, #parent?, #previous_sibling_node, #to_s
Constructor Details
#initialize(arg = UNDEFINED, parent = nil, context = nil) ⇒ Element
:call-seq:
Element.new(name = 'UNDEFINED', parent = nil, context = nil) -> new_element
Element.new(element, parent = nil, context = nil) -> new_element
Returns a new REXML::Element object.
When no arguments are given, returns an element with name 'UNDEFINED':
e = REXML::Element.new # => <UNDEFINED/>
e.class # => REXML::Element
e.name # => "UNDEFINED"
When only argument name is given, returns an element of the given name:
REXML::Element.new('foo') # => <foo/>
When only argument element is given, it must be an REXML::Element object; returns a shallow copy of the given element:
e0 = REXML::Element.new('foo')
e1 = REXML::Element.new(e0) # => <foo/>
When argument parent is also given, it must be an REXML::Parent object:
e = REXML::Element.new('foo', REXML::Parent.new)
e.parent # => #<REXML::Parent @parent=nil, @children=[<foo/>]>
When argument context is also given, it must be a hash representing the context for the element; see Element Context:
e = REXML::Element.new('foo', nil, {raw: :all})
e.context # => {:raw=>:all}
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
# File 'lib/rexml/element.rb', line 319 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. arg.attributes.each_attribute{ |attribute| @attributes << Attribute.new( attribute ) } @context = arg.context end end |
Instance Attribute Details
#attributes ⇒ Object (readonly)
Mechanisms for accessing attributes and child elements of this element.
278 279 280 |
# File 'lib/rexml/element.rb', line 278 def attributes @attributes end |
#context ⇒ Object
The context holds information about the processing environment, such as whitespace handling.
281 282 283 |
# File 'lib/rexml/element.rb', line 281 def context @context end |
#elements ⇒ Object (readonly)
Mechanisms for accessing attributes and child elements of this element.
278 279 280 |
# File 'lib/rexml/element.rb', line 278 def elements @elements end |
Instance Method Details
#[](name_or_index) ⇒ Object
:call-seq:
[index] -> object
[attr_name] -> attr_value
[attr_sym] -> attr_value
With integer argument index given, returns the child at offset index, or nil if none:
d = REXML::Document.new '><root><a/>text<b/>more<c/></root>'
root = d.root
(0..root.size).each do |index|
node = root[index]
p "#{index}: #{node} (#{node.class})"
end
Output:
"0: <a/> (REXML::Element)"
"1: text (REXML::Text)"
"2: <b/> (REXML::Element)"
"3: more (REXML::Text)"
"4: <c/> (REXML::Element)"
"5: (NilClass)"
With string argument attr_name given, returns the string value for the given attribute name if it exists, otherwise nil:
d = REXML::Document.new('<root attr="value"></root>')
root = d.root
root['attr'] # => "value"
root['nosuch'] # => nil
With symbol argument attr_sym given, returns [attr_sym.to_s]:
root[:attr] # => "value"
root[:nosuch] # => nil
1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 |
# File 'lib/rexml/element.rb', line 1238 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 |
#add_attribute(key, value = nil) ⇒ Object
:call-seq:
add_attribute(name, value) -> value
add_attribute(attribute) -> attribute
Adds an attribute to this element, overwriting any existing attribute by the same name.
With string argument name and object value are given, adds the attribute created with that name and value:
e = REXML::Element.new
e.add_attribute('attr', 'value') # => "value"
e['attr'] # => "value"
e.add_attribute('attr', 'VALUE') # => "VALUE"
e['attr'] # => "VALUE"
With only attribute object attribute given, adds the given attribute:
a = REXML::Attribute.new('attr', 'value')
e.add_attribute(a) # => attr='value'
e['attr'] # => "value"
a = REXML::Attribute.new('attr', 'VALUE')
e.add_attribute(a) # => attr='VALUE'
e['attr'] # => "VALUE"
1336 1337 1338 1339 1340 1341 1342 |
# File 'lib/rexml/element.rb', line 1336 def add_attribute( key, value=nil ) if key.kind_of? Attribute @attributes << key else @attributes[key] = value end end |
#add_attributes(hash) ⇒ Object
:call-seq:
add_attributes(hash) -> hash
add_attributes(array)
Adds zero or more attributes to the element; returns the argument.
If hash argument hash is given, each key must be a string; adds each attribute created with the key/value pair:
e = REXML::Element.new
h = {'foo' => 'bar', 'baz' => 'bat'}
e.add_attributes(h)
If argument array is given, each array member must be a 2-element array <tt>[name, value]; each name must be a string:
e = REXML::Element.new
a = [['foo' => 'bar'], ['baz' => 'bat']]
e.add_attributes(a)
1367 1368 1369 1370 1371 1372 1373 |
# File 'lib/rexml/element.rb', line 1367 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) ⇒ Object
:call-seq:
add_element(name, attributes = nil) -> new_element
add_element(element, attributes = nil) -> element
Adds a child element, optionally setting attributes on the added element; returns the added element.
With string argument name, creates a new element with that name and adds the new element as a child:
e0 = REXML::Element.new('foo')
e0.add_element('bar')
e0[0] # => <bar/>
With argument name and hash argument attributes, sets attributes on the new element:
e0.add_element('baz', {'bat' => '0', 'bam' => '1'})
e0[1] # => <baz bat='0' bam='1'/>
With element argument element, adds that element as a child:
e0 = REXML::Element.new('foo')
e1 = REXML::Element.new('bar')
e0.add_element(e1)
e0[0] # => <bar/>
With argument element and hash argument attributes, sets attributes on the added element:
e0.add_element(e1, {'bat' => '0', 'bam' => '1'})
e0[1] # => <bar bat='0' bam='1'/>
725 726 727 728 729 730 731 732 |
# File 'lib/rexml/element.rb', line 725 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 |
#add_namespace(prefix, uri = nil) ⇒ Object
:call-seq:
add_namespace(prefix, uri = nil) -> self
Adds a namespace to the element; returns self.
With the single argument prefix, adds a namespace using the given prefix and the namespace URI:
e = REXML::Element.new('foo')
e.add_namespace('bar')
e.namespaces # => {"xmlns"=>"bar"}
With both arguments prefix and uri given, adds a namespace using both arguments:
e.add_namespace('baz', 'bat')
e.namespaces # => {"xmlns"=>"bar", "baz"=>"bat"}
648 649 650 651 652 653 654 655 656 |
# File 'lib/rexml/element.rb', line 648 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) ⇒ Object
:call-seq:
add_text(string) -> nil
add_text(text_node) -> self
Adds text to the element.
When string argument string is given, returns nil.
If the element has no child text node, creates a REXML::Text object using the string, honoring the current settings for whitespace and raw, then adds that node to the element:
d = REXML::Document.new('<a><b/></a>')
a = d.root
a.add_text('foo')
a.to_a # => [<b/>, "foo"]
If the element has child text nodes, appends the string to the last text node:
d = REXML::Document.new('<a>foo<b/>bar</a>')
a = d.root
a.add_text('baz')
a.to_a # => ["foo", <b/>, "barbaz"]
a.add_text('baz')
a.to_a # => ["foo", <b/>, "barbazbaz"]
When text node argument text_node is given, appends the node as the last text node in the element; returns self:
d = REXML::Document.new('<a>foo<b/>bar</a>')
a = d.root
a.add_text(REXML::Text.new('baz'))
a.to_a # => ["foo", <b/>, "bar", "baz"]
a.add_text(REXML::Text.new('baz'))
a.to_a # => ["foo", <b/>, "bar", "baz", "baz"]
1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 |
# File 'lib/rexml/element.rb', line 1139 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? self end |
#attribute(name, namespace = nil) ⇒ Object
:call-seq:
attribute(name, namespace = nil)
Returns the string value for the given attribute name.
With only argument name given, returns the value of the named attribute if it exists, otherwise nil:
xml_string = <<-EOT
<root xmlns="ns0">
<a xmlns="ns1" attr="value"></a>
<b xmlns="ns2" attr="value"></b>
<c attr="value"/>
</root>
EOT
d = REXML::Document.new(xml_string)
root = d.root
a = root[1] # => <a xmlns='ns1' attr='value'/>
a.attribute('attr') # => attr='value'
a.attribute('nope') # => nil
With arguments name and namespace given, returns the value of the named attribute if it exists, otherwise nil:
xml_string = "<root xmlns:a='a' a:x='a:x' x='x'/>"
document = REXML::Document.new(xml_string)
document.root.attribute("x") # => x='x'
document.root.attribute("x", "a") # => a:x='a:x'
1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 |
# File 'lib/rexml/element.rb', line 1279 def attribute( name, namespace=nil ) prefix = namespaces.key(namespace) if namespace prefix = nil if prefix == 'xmlns' ret_val = attributes.get_attribute( prefix ? "#{prefix}:#{name}" : 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 |
#cdatas ⇒ Object
:call-seq:
cdatas -> array_of_cdata_children
Returns a frozen array of the REXML::CData children of the element:
xml_string = <<-EOT
<root>
<![CDATA[foo]]>
<![CDATA[bar]]>
</root>
EOT
d = REXML::Document.new(xml_string)
cds = d.root.cdatas # => ["foo", "bar"]
cds.frozen? # => true
cds.map {|cd| cd.class } # => [REXML::CData, REXML::CData]
1411 1412 1413 |
# File 'lib/rexml/element.rb', line 1411 def cdatas find_all { |child| child.kind_of? CData }.freeze end |
#clone ⇒ Object
383 384 385 |
# File 'lib/rexml/element.rb', line 383 def clone self.class.new self end |
#comments ⇒ Object
:call-seq:
comments -> array_of_comment_children
Returns a frozen array of the REXML::Comment children of the element:
xml_string = <<-EOT
<root>
<!--foo-->
<!--bar-->
</root>
EOT
d = REXML::Document.new(xml_string)
cs = d.root.comments
cs.frozen? # => true
cs.map {|c| c.class } # => [REXML::Comment, REXML::Comment]
cs.map {|c| c.to_s } # => ["foo", "bar"]
1432 1433 1434 |
# File 'lib/rexml/element.rb', line 1432 def comments find_all { |child| child.kind_of? Comment }.freeze end |
#delete_attribute(key) ⇒ Object
1386 1387 1388 1389 |
# File 'lib/rexml/element.rb', line 1386 def delete_attribute(key) attr = @attributes.get_attribute(key) attr.remove unless attr.nil? end |
#delete_element(element) ⇒ Object
:call-seq:
delete_element(index) -> removed_element or nil
delete_element(element) -> removed_element or nil
delete_element(xpath) -> removed_element or nil
Deletes a child element.
When 1-based integer argument index is given, removes and returns the child element at that offset if it exists; indexing does not include text nodes; returns nil if the element does not exist:
d = REXML::Document.new '<a><b/>text<c/></a>'
a = d.root # => <a> ... </>
a.delete_element(1) # => <b/>
a.delete_element(1) # => <c/>
a.delete_element(1) # => nil
When element argument element is given, removes and returns that child element if it exists, otherwise returns nil:
d = REXML::Document.new '<a><b/>text<c/></a>'
a = d.root # => <a> ... </>
c = a[2] # => <c/>
a.delete_element(c) # => <c/>
a.delete_element(c) # => nil
When xpath argument xpath is given, removes and returns the element at xpath if it exists, otherwise returns nil:
d = REXML::Document.new '<a><b/>text<c/></a>'
a = d.root # => <a> ... </>
a.delete_element('//c') # => <c/>
a.delete_element('//c') # => nil
771 772 773 |
# File 'lib/rexml/element.rb', line 771 def delete_element element @elements.delete element end |
#delete_namespace(namespace = "xmlns") ⇒ Object
:call-seq:
delete_namespace(namespace = 'xmlns') -> self
Removes a namespace from the element.
With no argument, removes the default namespace:
d = REXML::Document.new "<a xmlns:foo='bar' xmlns='twiddle'/>"
d.to_s # => "<a xmlns:foo='bar' xmlns='twiddle'/>"
d.root.delete_namespace # => <a xmlns:foo='bar'/>
d.to_s # => "<a xmlns:foo='bar'/>"
With argument namespace, removes the specified namespace:
d.root.delete_namespace('foo')
d.to_s # => "<a/>"
Does nothing if no such namespace is found:
d.root.delete_namespace('nosuch')
d.to_s # => "<a/>"
680 681 682 683 684 685 |
# File 'lib/rexml/element.rb', line 680 def delete_namespace namespace="xmlns" namespace = "xmlns:#{namespace}" unless namespace == 'xmlns' attribute = attributes.get_attribute(namespace) attribute.remove unless attribute.nil? self end |
#document ⇒ Object
:call-seq:
document -> document or nil
If the element is part of a document, returns that document:
d = REXML::Document.new('<a><b><c/></b></a>')
top_element = d.first
child = top_element.first
top_element.document == d # => true
child.document == d # => true
If the element is not part of a document, returns nil:
REXML::Element.new.document # => nil
For a document, returns self:
d.document == d # => true
Related: #root, #root_node.
475 476 477 |
# File 'lib/rexml/element.rb', line 475 def document root&.parent end |
#each_element(xpath = nil, &block) ⇒ Object
923 924 925 |
# File 'lib/rexml/element.rb', line 923 def each_element( xpath=nil, &block ) # :yields: Element @elements.each( xpath, &block ) end |
#each_element_with_attribute(key, value = nil, max = 0, name = nil, &block) ⇒ Object
:call-seq:
each_element_with_attribute(attr_name, value = nil, max = 0, xpath = nil) {|e| ... }
Calls the given block with each child element that meets given criteria.
When only string argument attr_name is given, calls the block with each child element that has that attribute:
d = REXML::Document.new '<a><b id="1"/><c id="2"/><d id="1"/><e/></a>'
a = d.root
a.each_element_with_attribute('id') {|e| p e }
Output:
<b id='1'/>
<c id='2'/>
<d id='1'/>
With argument attr_name and string argument value given, calls the block with each child element that has that attribute with that value:
a.each_element_with_attribute('id', '1') {|e| p e }
Output:
<b id='1'/>
<d id='1'/>
With arguments attr_name, value, and integer argument max given, calls the block with at most max child elements:
a.each_element_with_attribute('id', '1', 1) {|e| p e }
Output:
<b id='1'/>
With all arguments given, including xpath, calls the block with only those child elements that meet the first three criteria, and also match the given xpath:
a.each_element_with_attribute('id', '1', 2, '//d') {|e| p e }
Output:
<d id='1'/>
840 841 842 843 844 845 846 847 848 |
# File 'lib/rexml/element.rb', line 840 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, &block) ⇒ Object
:call-seq:
each_element_with_text(text = nil, max = 0, xpath = nil) {|e| ... }
Calls the given block with each child element that meets given criteria.
With no arguments, calls the block with each child element that has text:
d = REXML::Document.new '<a><b>b</b><c>b</c><d>d</d><e/></a>'
a = d.root
a.each_element_with_text {|e| p e }
Output:
<b> ... </>
<c> ... </>
<d> ... </>
With the single string argument text, calls the block with each element that has exactly that text:
a.each_element_with_text('b') {|e| p e }
Output:
<b> ... </>
<c> ... </>
With argument text and integer argument max, calls the block with at most max elements:
a.each_element_with_text('b', 1) {|e| p e }
Output:
<b> ... </>
With all arguments given, including xpath, calls the block with only those child elements that meet the first two criteria, and also match the given xpath:
a.each_element_with_text('b', 2, '//c') {|e| p e }
Output:
<c> ... </>
897 898 899 900 901 902 903 904 905 |
# File 'lib/rexml/element.rb', line 897 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) ⇒ Object
942 943 944 |
# File 'lib/rexml/element.rb', line 942 def get_elements( xpath ) @elements.to_a( xpath ) end |
#get_text(path = nil) ⇒ Object
:call-seq:
get_text(xpath = nil) -> text_node or nil
Returns the first text node child in a specified element, if it exists, nil otherwise.
With no argument, returns the first text node from self:
d = REXML::Document.new "<p>some text <b>this is bold!</b> more text</p>"
d.root.get_text.class # => REXML::Text
d.root.get_text # => "some text "
With argument xpath, returns the first text node from the element that matches xpath:
d.root.get_text(1) # => "this is bold!"
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 |
# File 'lib/rexml/element.rb', line 1045 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 rv end |
#has_attributes? ⇒ Boolean
1306 1307 1308 |
# File 'lib/rexml/element.rb', line 1306 def has_attributes? !@attributes.empty? end |
#has_elements? ⇒ Boolean
787 788 789 |
# File 'lib/rexml/element.rb', line 787 def has_elements? !@elements.empty? end |
#has_text? ⇒ Boolean
995 996 997 |
# File 'lib/rexml/element.rb', line 995 def has_text? not text().nil? end |
#ignore_whitespace_nodes ⇒ Object
:call-seq:
ignore_whitespace_nodes
Returns true if whitespace nodes are ignored for the element.
See Element Context.
512 513 514 515 516 517 518 519 520 521 |
# File 'lib/rexml/element.rb', line 512 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? ) end end end |
#inspect ⇒ Object
:call-seq:
inspect -> string
Returns a string representation of the element.
For an element with no attributes and no children, shows the element name:
REXML::Element.new.inspect # => "<UNDEFINED/>"
Shows attributes, if any:
e = REXML::Element.new('foo')
e.add_attributes({'bar' => 0, 'baz' => 1})
e.inspect # => "<foo bar='0' baz='1'/>"
Shows an ellipsis (...), if there are child elements:
e.add_element(REXML::Element.new('bar'))
e.add_element(REXML::Element.new('baz'))
e.inspect # => "<foo bar='0' baz='1'> ... </>"
358 359 360 361 362 363 364 365 366 367 368 369 370 371 |
# File 'lib/rexml/element.rb', line 358 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 ⇒ Object
:call-seq:
instructions -> array_of_instruction_children
Returns a frozen array of the REXML::Instruction children of the element:
xml_string = <<-EOT
<root>
<?target0 foo?>
<?target1 bar?>
</root>
EOT
d = REXML::Document.new(xml_string)
is = d.root.instructions
is.frozen? # => true
is.map {|i| i.class } # => [REXML::Instruction, REXML::Instruction]
is.map {|i| i.to_s } # => ["<?target0 foo?>", "<?target1 bar?>"]
1453 1454 1455 |
# File 'lib/rexml/element.rb', line 1453 def instructions find_all { |child| child.kind_of? Instruction }.freeze end |
#namespace(prefix = nil) ⇒ Object
:call-seq:
namespace(prefix = nil) -> string_uri or nil
Returns the string namespace URI for the element, possibly deriving from one of its ancestors.
xml_string = <<-EOT
<root>
<a xmlns='1' xmlns:y='2'>
<b/>
<c xmlns:z='3'/>
</a>
</root>
EOT
d = REXML::Document.new(xml_string)
b = d.elements['//b']
b.namespace # => "1"
b.namespace('y') # => "2"
b.namespace('nosuch') # => nil
619 620 621 622 623 624 625 626 627 628 |
# File 'lib/rexml/element.rb', line 619 def namespace(prefix=nil) if prefix.nil? prefix = prefix() end prefix = (prefix == '') ? 'xmlns' : prefix.delete_prefix("xmlns:") ns = namespaces[prefix] ns = '' if ns.nil? and prefix == 'xmlns' ns end |
#namespaces ⇒ Object
:call-seq:
namespaces -> array_of_namespace_names
Returns a hash of all defined namespaces in the element and its ancestors:
xml_string = <<-EOT
<root>
<a xmlns:x='1' xmlns:y='2'>
<b/>
<c xmlns:z='3'/>
</a>
</root>
EOT
d = REXML::Document.new(xml_string)
d.elements['//a'].namespaces # => {"x"=>"1", "y"=>"2"}
d.elements['//b'].namespaces # => {"x"=>"1", "y"=>"2"}
d.elements['//c'].namespaces # => {"x"=>"1", "y"=>"2", "z"=>"3"}
590 591 592 593 594 595 596 597 |
# File 'lib/rexml/element.rb', line 590 def namespaces namespaces_cache = document&.__send__(:namespaces_cache) if namespaces_cache namespaces_cache[self] ||= calculate_namespaces else calculate_namespaces end end |
#next_element ⇒ Object
956 957 958 959 960 |
# File 'lib/rexml/element.rb', line 956 def next_element element = next_sibling element = element.next_sibling until element.nil? or element.kind_of? Element element end |
#node_type ⇒ Object
1160 1161 1162 |
# File 'lib/rexml/element.rb', line 1160 def node_type :element end |
#prefixes ⇒ Object
:call-seq:
prefixes -> array_of_namespace_prefixes
Returns an array of the string prefixes (names) of all defined namespaces in the element and its ancestors:
xml_string = <<-EOT
<root>
<a xmlns:x='1' xmlns:y='2'>
<b/>
<c xmlns:z='3'/>
</a>
</root>
EOT
d = REXML::Document.new(xml_string, {compress_whitespace: :all})
d.elements['//a'].prefixes # => ["x", "y"]
d.elements['//b'].prefixes # => ["x", "y"]
d.elements['//c'].prefixes # => ["x", "y", "z"]
564 565 566 567 568 569 |
# File 'lib/rexml/element.rb', line 564 def prefixes prefixes = [] prefixes = parent.prefixes if parent prefixes |= attributes.prefixes prefixes end |
#previous_element ⇒ Object
972 973 974 975 976 |
# File 'lib/rexml/element.rb', line 972 def previous_element element = previous_sibling element = element.previous_sibling until element.nil? or element.kind_of? Element element end |
#raw ⇒ Object
:call-seq:
raw
Returns true if raw mode is set for the element.
See Element Context.
The evaluation is tested against expanded_name, and so is namespace sensitive.
532 533 534 535 536 537 |
# File 'lib/rexml/element.rb', line 532 def raw @raw = (@context and @context[:raw] and (@context[:raw] == :all or @context[:raw].include? )) @raw end |
#root ⇒ Object
:call-seq:
root -> element
Returns the most distant element (not document) ancestor of the element:
d = REXML::Document.new('<a><b><c/></b></a>')
top_element = d.first
child = top_element.first
top_element.root == top_element # => true
child.root == top_element # => true
For a document, returns the topmost element:
d.root == top_element # => true
Related: #root_node, #document.
443 444 445 446 447 448 449 450 451 452 |
# File 'lib/rexml/element.rb', line 443 def root target = self while target return target.elements[1] if target.kind_of? Document parent = target.parent return target if parent.kind_of? Document or parent.nil? target = parent end nil end |
#root_node ⇒ Object
:call-seq:
root_node -> document or element
Returns the most distant ancestor of self.
When the element is part of a document, returns the root node of the document. Note that the root node is different from the document element; in this example a is document element and the root node is its parent:
d = REXML::Document.new('<a><b><c/></b></a>')
top_element = d.first # => <a> ... </>
child = top_element.first # => <b> ... </>
d.root_node == d # => true
top_element.root_node == d # => true
child.root_node == d # => true
When the element is not part of a document, but does have ancestor elements, returns the most distant ancestor element:
e0 = REXML::Element.new('foo')
e1 = REXML::Element.new('bar')
e1.parent = e0
e2 = REXML::Element.new('baz')
e2.parent = e1
e2.root_node == e0 # => true
When the element has no ancestor elements, returns self:
e = REXML::Element.new('foo')
e.root_node == e # => true
Related: #root, #document.
422 423 424 |
# File 'lib/rexml/element.rb', line 422 def root_node parent.nil? ? self : parent.root_node end |
#text(path = nil) ⇒ Object
:call-seq:
text(xpath = nil) -> text_string or nil
Returns the text string from the first text node child in a specified element, if it exists, nil otherwise.
With no argument, returns the text from the first text node in self:
d = REXML::Document.new "<p>some text <b>this is bold!</b> more text</p>"
d.root.text.class # => String
d.root.text # => "some text "
With argument xpath, returns text from the first text node in the element that matches xpath:
d.root.text(1) # => "this is bold!"
Note that an element may have multiple text nodes, possibly separated by other non-text children, as above. Even so, the returned value is the string text from the first such node.
Note also that the text note is retrieved by method get_text, and so is always normalized text.
1023 1024 1025 1026 |
# File 'lib/rexml/element.rb', line 1023 def text( path = nil ) rv = get_text(path) rv&.value end |
#text=(text) ⇒ Object
:call-seq:
text = string -> string
text = nil -> nil
Adds, replaces, or removes the first text node child in the element.
With string argument string, creates a new REXML::Text node containing that string, honoring the current settings for whitespace and row, then places the node as the first text child in the element; returns string.
If the element has no text child, the text node is added:
d = REXML::Document.new '<a><b/></a>'
d.root.text = 'foo' #-> '<a><b/>foo</a>'
If the element has a text child, it is replaced:
d.root.text = 'bar' #-> '<a><b/>bar</a>'
With argument nil, removes the first text child:
d.root.text = nil #-> '<a><b/><c/></a>'
1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 |
# File 'lib/rexml/element.rb', line 1081 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 self end |
#texts ⇒ Object
:call-seq:
texts -> array_of_text_children
Returns a frozen array of the REXML::Text children of the element:
xml_string = '<root><a/>text<b/>more<c/></root>'
d = REXML::Document.new(xml_string)
ts = d.root.texts
ts.frozen? # => true
ts.map {|t| t.class } # => [REXML::Text, REXML::Text]
ts.map {|t| t.to_s } # => ["text", "more"]
1469 1470 1471 |
# File 'lib/rexml/element.rb', line 1469 def texts find_all { |child| child.kind_of? Text }.freeze end |
#whitespace ⇒ Object
:call-seq:
whitespace
Returns true if whitespace is respected for this element, false otherwise.
See Element Context.
The evaluation is tested against the element’s expanded_name, and so is namespace-sensitive.
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 |
# File 'lib/rexml/element.rb', line 489 def whitespace @whitespace = nil if @context if @context[:respect_whitespace] @whitespace = (@context[:respect_whitespace] == :all or @context[:respect_whitespace].include? ) end @whitespace = false if (@context[:compress_whitespace] and (@context[:compress_whitespace] == :all or @context[:compress_whitespace].include? ) ) end @whitespace = true unless @whitespace == false @whitespace end |
#write(output = $stdout, indent = -1,, transitive = false, ie_hack = false) ⇒ Object
DEPRECATED
See REXML::Formatters
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
1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 |
# File 'lib/rexml/element.rb', line 1495 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_relative "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 |
#xpath ⇒ Object
:call-seq:
xpath -> string_xpath
Returns the string xpath to the element relative to the most distant parent:
d = REXML::Document.new('<a><b><c/></b></a>')
a = d.root # => <a> ... </>
b = a[0] # => <b> ... </>
c = b[0] # => <c/>
d.xpath # => ""
a.xpath # => "/a"
b.xpath # => "/a/b"
c.xpath # => "/a/b/c"
If there is no parent, returns the expanded name of the element:
e = REXML::Element.new('foo')
e.xpath # => "foo"
1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 |
# File 'lib/rexml/element.rb', line 1184 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 path_elements.reverse.join( "/" ) end |