class REXML::Element

REXML::Element 对象表示一个 XML 元素。

一个元素

  • 有一个名称(字符串)。

  • 可能有一个父节点(另一个元素)。

  • 有零个或多个子节点(其他元素、文本、CDATA、处理指令和注释)。

  • 有零个或多个兄弟节点(其他元素、文本、CDATA、处理指令和注释)。

  • 有零个或多个命名属性。

赶时间?

如果您对 XML 有一定的了解,并且心中有一个特定的任务,您可能需要查看任务页面,特别是元素的任务页面

名称

一个元素有一个名称,该名称在创建元素时最初设置

e = REXML::Element.new('foo')
e.name # => "foo"

可以更改名称

e.name = 'bar'
e.name # => "bar"

父节点

一个元素可能有一个父节点。

可以在创建元素时显式分配其父节点

e0 = REXML::Element.new('foo')
e1 = REXML::Element.new('bar', e0)
e1.parent # => <foo> ... </>

注意:元素的表示形式始终显示元素的名称。如果元素有子节点,则表示形式会通过包含省略号 (...) 来指示。

可以在任何时候显式分配父节点

e2 = REXML::Element.new('baz')
e1.parent = e2
e1.parent # => <baz/>

当元素作为子节点添加时,其父节点会自动设置

e1.add_element(e0)
e0.parent # => <bar> ... </>

对于没有父节点的元素,方法 parent 返回 nil

子节点

一个元素有零个或多个子节点。子节点是所有父节点为元素本身的对象的一个有序集合。

子节点可能包含元素、文本、注释、处理指令和 CDATA 的任意组合。(此示例通过 context 设置控制空格来保持整洁。)

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}" }

输出

"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"

可以使用继承的方法 Parent#insert_beforeParent#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/>]

可以使用 Parent#replace_child 替换子节点

root.replace_child(c, REXML::Element.new('x'))
root.to_a # => [<a/>, <b/>, <x/>, <d/>]

可以使用 Parent#delete 删除子节点

x = root[2] # => <x/>
root.delete(x)
root.to_a # => [<a/>, <b/>, <d/>]

兄弟节点

一个元素有零个或多个兄弟节点,它们是该元素父节点的其他子节点。

在上面的示例中,元素 ele_1 位于 CDATA 兄弟节点和文本兄弟节点之间

ele_1 = root[5]        # => <ele_1/>
ele_1.previous_sibling # => "cdata 0"
ele_1.next_sibling     # => "\n text 1\n "

属性

一个元素有零个或多个命名属性。

一个新元素没有属性

e = REXML::Element.new('foo')
e.attributes      # => {}

可以添加Attributes

e.add_attribute('bar', 'baz')
e.add_attribute('bat', 'bam')
e.attributes.size # => 2
e['bar']          # => "baz"
e['bat']          # => "bam"

可以修改现有属性

e.add_attribute('bar', 'bad')
e.attributes.size # => 2
e['bar']          # => "bad"

可以删除现有属性

e.delete_attribute('bar')
e.attributes.size # => 1
e['bar']          # => nil

这里有什么

首先,看看其他地方有什么?

类 REXML::Element 从其祖先类继承

REXML::Element 本身及其祖先还包括模块

创建元素的方法

::new

返回一个新的空元素。

clone

返回另一个元素的克隆。

属性的方法

[attribute_name]

返回属性值。

add_attribute

添加一个新属性。

add_attributes

添加多个新属性。

attribute

返回给定名称和可选命名空间的属性值。

delete_attribute

删除一个属性。

子节点的方法

[索引]

返回给定偏移量的子节点。

add_element

将一个元素添加为最后一个子节点。

delete_element

删除一个子元素。

each_element

使用每个子元素调用给定的块。

each_element_with_attribute

使用每个满足给定条件的子元素调用给定的块,这些条件可以包括属性名称。

each_element_with_text

使用每个满足给定条件的子元素调用给定的块,这些条件可以包括文本。

get_elements

返回与给定 xpath 匹配的子元素数组。

文本子节点的方法

add_text

向元素添加一个文本节点。

get_text

返回满足指定条件的文本节点。

text

从满足指定条件的第一个节点返回文本字符串。

texts

返回元素的文本子节点的数组。

text=

添加、删除或替换元素的第一个文本子节点

其他子节点的方法

cdatas

返回元素的 cdata 子节点的数组。

comments

返回元素的注释子节点的数组。

instructions

返回元素的指令子节点的数组。

命名空间的方法

add_namespace

向元素添加一个命名空间。

delete_namespace

从元素中删除一个命名空间。

namespace

返回元素的字符串命名空间 URI。

namespaces

返回元素中所有已定义的命名空间的哈希值。

prefixes

返回元素中所有已定义的命名空间的字符串前缀(名称)的数组

查询的方法

document

返回元素所属的文档(如果有)。

root

返回元素的最远的元素(非文档)祖先。

root_node

返回元素的最远祖先。

xpath

返回相对于最远父元素的元素的字符串 xpath

has_attributes?

返回元素是否具有属性。

has_elements?

返回元素是否具有元素。

has_text?

返回元素是否具有文本。

next_element

返回下一个作为元素的兄弟节点。

previous_element

返回上一个作为元素的兄弟节点。

raw

返回是否为元素设置了原始模式。

whitespace

返回是否尊重元素的空格。

ignore_whitespace_nodes

返回是否忽略元素的空格节点。

node_type

返回符号 :element

另一个方法

inspect

返回元素的字符串表示形式。

访问器

elements

返回元素的 REXML::Elements 对象。

attributes

返回元素的 REXML::Attributes 对象。

context

返回或设置元素的上下文哈希。

常量

UNDEFINED

属性

attributes[R]

用于访问此元素的属性和子元素的机制。

context[RW]

上下文保存有关处理环境的信息,例如空格处理。

elements[R]

用于访问此元素的属性和子元素的机制。

公共类方法

new(name = 'UNDEFINED', parent = nil, context = nil) → new_element 单击以切换源代码
new(element, parent = nil, context = nil) → new_element

返回一个新的 REXML::Element 对象。

当没有给出参数时,返回名称为 'UNDEFINED' 的元素

e = REXML::Element.new # => <UNDEFINED/>
e.class                # => REXML::Element
e.name                 # => "UNDEFINED"

当仅给出参数 name 时,返回给定名称的元素

REXML::Element.new('foo') # => <foo/>

当仅给出参数 element 时,它必须是 REXML::Element 对象;返回给定元素的浅拷贝

e0 = REXML::Element.new('foo')
e1 = REXML::Element.new(e0) # => <foo/>

当还给出参数 parent 时,它必须是 REXML::Parent 对象

e = REXML::Element.new('foo', REXML::Parent.new)
e.parent # => #<REXML::Parent @parent=nil, @children=[<foo/>]>

当还给出参数 context 时,它必须是一个表示元素上下文的哈希;请参阅 元素上下文

e = REXML::Element.new('foo', nil, {raw: :all})
e.context # => {:raw=>:all}
调用超类方法
# File rexml-3.4.0/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.expanded_name
    arg.attributes.each_attribute{ |attribute|
      @attributes << Attribute.new( attribute )
    }
    @context = arg.context
  end
end

公共实例方法

[index] → object 单击以切换源代码
[attr_name] → attr_value
[attr_sym] → attr_value

当给出整数参数 index 时,返回偏移量为 index 的子节点,如果没有则返回 nil

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

输出

"0: <a/> (REXML::Element)"
"1: text (REXML::Text)"
"2: <b/> (REXML::Element)"
"3: more (REXML::Text)"
"4: <c/> (REXML::Element)"
"5:  (NilClass)"

当给出字符串参数 attr_name 时,如果给定属性名称存在,则返回其字符串值,否则返回 nil

d = REXML::Document.new('<root attr="value"></root>')
root = d.root
root['attr']   # => "value"
root['nosuch'] # => nil

当给出符号参数 attr_sym 时,返回 [attr_sym.to_s]

root[:attr]   # => "value"
root[:nosuch] # => nil
调用超类方法
# File rexml-3.4.0/lib/rexml/element.rb, line 1246
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(name, value) → value 单击以切换源代码
add_attribute(attribute) → attribute

向此元素添加一个属性,覆盖任何具有相同名称的现有属性。

当给出字符串参数 name 和对象 value 时,添加使用该名称和值创建的属性

e = REXML::Element.new
e.add_attribute('attr', 'value') # => "value"
e['attr'] # => "value"
e.add_attribute('attr', 'VALUE') # => "VALUE"
e['attr'] # => "VALUE"

当仅给出属性对象 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"
# File rexml-3.4.0/lib/rexml/element.rb, line 1345
def add_attribute( key, value=nil )
  if key.kind_of? Attribute
    @attributes << key
  else
    @attributes[key] = value
  end
end
add_attributes(hash) → hash 单击以切换源代码
add_attributes(array)

向元素添加零个或多个属性;返回参数。

如果给出哈希参数 hash,则每个键都必须是一个字符串;添加使用键/值对创建的每个属性

e = REXML::Element.new
h = {'foo' => 'bar', 'baz' => 'bat'}
e.add_attributes(h)

如果给出参数 array,则每个数组元素都必须是一个 2 元素数组 <tt>[name, value];每个名称都必须是一个字符串

e = REXML::Element.new
a = [['foo' => 'bar'], ['baz' => 'bat']]
e.add_attributes(a)
# File rexml-3.4.0/lib/rexml/element.rb, line 1376
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(name, attributes = nil) → new_element 单击以切换源代码
add_element(element, attributes = nil) → element

添加一个子元素,可以选择性地为添加的元素设置属性;返回添加的元素。

如果参数是字符串 name,则创建一个具有该名称的新元素,并将该新元素作为子元素添加。

e0 = REXML::Element.new('foo')
e0.add_element('bar')
e0[0] # => <bar/>

如果参数是 name 和哈希参数 attributes,则在新元素上设置属性。

e0.add_element('baz', {'bat' => '0', 'bam' => '1'})
e0[1] # => <baz bat='0' bam='1'/>

如果参数是元素 element,则将该元素作为子元素添加。

e0 = REXML::Element.new('foo')
e1 = REXML::Element.new('bar')
e0.add_element(e1)
e0[0] # => <bar/>

如果参数是 element 和哈希参数 attributes,则在添加的元素上设置属性。

e0.add_element(e1, {'bat' => '0', 'bam' => '1'})
e0[1] # => <bar bat='0' bam='1'/>
# File rexml-3.4.0/lib/rexml/element.rb, line 732
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) → self 点击以切换源代码

向元素添加命名空间;返回 self

如果只使用参数 prefix,则使用给定的 prefix 和命名空间 URI 添加命名空间。

e = REXML::Element.new('foo')
e.add_namespace('bar')
e.namespaces # => {"xmlns"=>"bar"}

如果同时给出参数 prefixuri,则使用这两个参数添加命名空间。

e.add_namespace('baz', 'bat')
e.namespaces # => {"xmlns"=>"bar", "baz"=>"bat"}
# File rexml-3.4.0/lib/rexml/element.rb, line 655
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(string) → nil 点击以切换源代码
add_text(text_node) → self

向元素添加文本。

当给出字符串参数 string 时,返回 nil

如果元素没有子文本节点,则使用该字符串创建一个 REXML::Text 对象,遵循当前关于空格和原始数据的设置,然后将该节点添加到元素中。

d = REXML::Document.new('<a><b/></a>')
a = d.root
a.add_text('foo')
a.to_a # => [<b/>, "foo"]

如果元素有子文本节点,则将该字符串附加到最后一个文本节点。

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"]

当给出文本节点参数 text_node 时,将该节点作为元素中的最后一个文本节点附加;返回 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"]
# File rexml-3.4.0/lib/rexml/element.rb, line 1147
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) 点击以切换源代码

返回给定属性名称的字符串值。

如果只给出参数 name,则返回命名属性的值(如果存在),否则返回 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

如果给出参数 namenamespace,则返回命名属性的值(如果存在),否则返回 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'
# File rexml-3.4.0/lib/rexml/element.rb, line 1287
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 → array_of_cdata_children 点击以切换源代码

返回元素 REXML::CData 子元素的冻结数组。

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]
# File rexml-3.4.0/lib/rexml/element.rb, line 1420
def cdatas
  find_all { |child| child.kind_of? CData }.freeze
end
clone → new_element 点击以切换源代码

返回元素的浅拷贝,其中包含名称和属性,但不包含父元素或子元素。

e = REXML::Element.new('foo')
e.add_attributes({'bar' => 0, 'baz' => 1})
e.clone # => <foo bar='0' baz='1'/>
# File rexml-3.4.0/lib/rexml/element.rb, line 383
def clone
  self.class.new self
end
comments → array_of_comment_children 点击以切换源代码

返回元素 REXML::Comment 子元素的冻结数组。

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"]
# File rexml-3.4.0/lib/rexml/element.rb, line 1441
def comments
  find_all { |child| child.kind_of? Comment }.freeze
end
delete_attribute(name) → removed_attribute or nil 点击以切换源代码

如果存在,则删除命名属性;如果找到,则返回删除的属性,否则返回 nil

e = REXML::Element.new('foo')
e.add_attribute('bar', 'baz')
e.delete_attribute('bar') # => <bar/>
e.delete_attribute('bar') # => nil
# File rexml-3.4.0/lib/rexml/element.rb, line 1395
def delete_attribute(key)
  attr = @attributes.get_attribute(key)
  attr.remove unless attr.nil?
end
delete_element(index) → removed_element or nil 点击以切换源代码
delete_element(element) → removed_element or nil
delete_element(xpath) → removed_element or nil

删除一个子元素。

当给出基于 1 的整数参数 index 时,如果存在,则删除并返回该偏移量处的子元素;索引不包括文本节点;如果元素不存在,则返回 nil

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

当给出元素参数 element 时,如果存在,则删除并返回该子元素,否则返回 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

当给出 xpath 参数 xpath 时,如果存在,则删除并返回 xpath 处的元素,否则返回 nil

d = REXML::Document.new '<a><b/>text<c/></a>'
a = d.root              # => <a> ... </>
a.delete_element('//c') # => <c/>
a.delete_element('//c') # => nil
# File rexml-3.4.0/lib/rexml/element.rb, line 778
def delete_element element
  @elements.delete element
end
delete_namespace(namespace = 'xmlns') → self 点击以切换源代码

从元素中删除一个命名空间。

如果不带参数,则删除默认命名空间。

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'/>"

如果使用参数 namespace,则删除指定的命名空间。

d.root.delete_namespace('foo')
d.to_s # => "<a/>"

如果未找到此类命名空间,则不执行任何操作。

d.root.delete_namespace('nosuch')
d.to_s # => "<a/>"
# File rexml-3.4.0/lib/rexml/element.rb, line 687
def delete_namespace namespace="xmlns"
  namespace = "xmlns:#{namespace}" unless namespace == 'xmlns'
  attribute = attributes.get_attribute(namespace)
  attribute.remove unless attribute.nil?
  self
end
document → document or nil 点击以切换源代码

如果元素是文档的一部分,则返回该文档。

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

如果元素不是文档的一部分,则返回 nil

REXML::Element.new.document # => nil

对于文档,返回 self

d.document == d           # => true

相关:rootroot_node

# File rexml-3.4.0/lib/rexml/element.rb, line 475
def document
  rt = root
  rt.parent if rt
end
each_element {|e| ... } 点击以切换源代码

使用每个子元素调用给定的块。

d = REXML::Document.new '<a><b>b</b><c>b</c><d>d</d><e/></a>'
a = d.root
a.each_element {|e| p e }

输出

<b> ... </>
<c> ... </>
<d> ... </>
<e/>
# File rexml-3.4.0/lib/rexml/element.rb, line 930
def each_element( xpath=nil, &block ) # :yields: Element
  @elements.each( xpath, &block )
end
each_element_with_attribute(attr_name, value = nil, max = 0, xpath = nil) {|e| ... } 点击以切换源代码

使用符合给定条件的每个子元素调用给定的块。

如果只给出字符串参数 attr_name,则使用具有该属性的每个子元素调用该块。

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 }

输出

<b id='1'/>
<c id='2'/>
<d id='1'/>

如果给出参数 attr_name 和字符串参数 value,则使用具有该属性且具有该值的每个子元素调用该块。

a.each_element_with_attribute('id', '1') {|e| p e }

输出

<b id='1'/>
<d id='1'/>

如果给出参数 attr_namevalue 和整数参数 max,则最多使用 max 个子元素调用该块。

a.each_element_with_attribute('id', '1', 1) {|e| p e }

输出

<b id='1'/>

如果给出所有参数,包括 xpath,则只使用符合前三个条件并且还匹配给定 xpath 的子元素调用该块。

a.each_element_with_attribute('id', '1', 2, '//d') {|e| p e }

输出

<d id='1'/>
# File rexml-3.4.0/lib/rexml/element.rb, line 847
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, xpath = nil) {|e| ... } 点击以切换源代码

使用符合给定条件的每个子元素调用给定的块。

如果没有参数,则使用每个具有文本的子元素调用该块。

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 }

输出

<b> ... </>
<c> ... </>
<d> ... </>

如果使用单个字符串参数 text,则使用具有完全相同文本的每个元素调用该块。

a.each_element_with_text('b') {|e| p e }

输出

<b> ... </>
<c> ... </>

如果使用参数 text 和整数参数 max,则最多使用 max 个元素调用该块。

a.each_element_with_text('b', 1) {|e| p e }

输出

<b> ... </>

如果给出所有参数,包括 xpath,则只使用符合前两个条件并且还匹配给定 xpath 的子元素调用该块。

a.each_element_with_text('b', 2, '//c') {|e| p e }

输出

<c> ... </>
# File rexml-3.4.0/lib/rexml/element.rb, line 904
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) 点击以切换源代码

返回与给定 xpath 匹配的元素数组。

xml_string = <<-EOT
<root>
  <a level='1'>
    <a level='2'/>
  </a>
</root>
EOT
d = REXML::Document.new(xml_string)
d.root.get_elements('//a') # => [<a level='1'> ... </>, <a level='2'/>]
# File rexml-3.4.0/lib/rexml/element.rb, line 949
def get_elements( xpath )
  @elements.to_a( xpath )
end
get_text(xpath = nil) → text_node or nil 点击以切换源代码

返回指定元素中的第一个文本节点子节点(如果存在),否则返回 nil

如果没有参数,则从 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 "

如果使用参数 xpath,则从与 xpath 匹配的元素返回第一个文本节点。

d.root.get_text(1) # => "this is bold!"
# File rexml-3.4.0/lib/rexml/element.rb, line 1053
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? → true or false 点击以切换源代码

如果元素具有属性,则返回 true,否则返回 false

d = REXML::Document.new('<root><a attr="val"/><b/></root>')
a, b = *d.root
a.has_attributes? # => true
b.has_attributes? # => false
# File rexml-3.4.0/lib/rexml/element.rb, line 1315
def has_attributes?
  return !@attributes.empty?
end
has_elements? 点击以切换源代码

如果元素有一个或多个元素子节点,则返回 true,否则返回 false

d = REXML::Document.new '<a><b/>text<c/></a>'
a = d.root              # => <a> ... </>
a.has_elements? # => true
b = a[0]        # => <b/>
b.has_elements? # => false
# File rexml-3.4.0/lib/rexml/element.rb, line 794
def has_elements?
  !@elements.empty?
end
has_text? → true or false 点击以切换源代码

如果元素有一个或多个文本节点,则返回 true,否则返回 false

d = REXML::Document.new '<a><b/>text<c/></a>'
a = d.root
a.has_text? # => true
b = a[0]
b.has_text? # => false
# File rexml-3.4.0/lib/rexml/element.rb, line 1002
def has_text?
  not text().nil?
end
ignore_whitespace_nodes 点击以切换源代码

如果为元素忽略空格节点,则返回 true

请参阅 元素上下文

# File rexml-3.4.0/lib/rexml/element.rb, line 513
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 → string 点击以切换源代码

返回元素的字符串表示形式。

对于没有属性且没有子元素的元素,显示元素名称。

REXML::Element.new.inspect # => "<UNDEFINED/>"

显示属性(如果有)。

e = REXML::Element.new('foo')
e.add_attributes({'bar' => 0, 'baz' => 1})
e.inspect # => "<foo bar='0' baz='1'/>"

如果有子元素,则显示省略号(...)。

e.add_element(REXML::Element.new('bar'))
e.add_element(REXML::Element.new('baz'))
e.inspect # => "<foo bar='0' baz='1'> ... </>"
# File rexml-3.4.0/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 → array_of_instruction_children 点击以切换源代码

返回元素 REXML::Instruction 子元素的冻结数组。

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?>"]
# File rexml-3.4.0/lib/rexml/element.rb, line 1462
def instructions
  find_all { |child| child.kind_of? Instruction }.freeze
end
namespace(prefix = nil) → string_uri or nil 点击以切换源代码

返回元素的字符串命名空间 URI,可能派生自其祖先之一。

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
# File rexml-3.4.0/lib/rexml/element.rb, line 618
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 = nil
  target = self
  while ns.nil? and target
    ns = target.attributes[prefix]
    target = target.parent
  end
  ns = '' if ns.nil? and prefix == 'xmlns'
  return ns
end
namespaces → array_of_namespace_names 点击以切换源代码

返回元素及其祖先中所有已定义命名空间的哈希值。

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"}
# File rexml-3.4.0/lib/rexml/element.rb, line 591
def namespaces
  namespaces = {}
  namespaces = parent.namespaces if parent
  namespaces = namespaces.merge( attributes.namespaces )
  return namespaces
end
next_element 点击以切换源代码

如果存在,则返回下一个兄弟元素,否则返回 nil

d = REXML::Document.new '<a><b/>text<c/></a>'
d.root.elements['b'].next_element #-> <c/>
d.root.elements['c'].next_element #-> nil
# File rexml-3.4.0/lib/rexml/element.rb, line 963
def next_element
  element = next_sibling
  element = element.next_sibling until element.nil? or element.kind_of? Element
  return element
end
node_type → :element 点击以切换源代码

返回符号 :element

d = REXML::Document.new('<a/>')
a = d.root  # => <a/>
a.node_type # => :element
# File rexml-3.4.0/lib/rexml/element.rb, line 1168
def node_type
  :element
end
prefixes → array_of_namespace_prefixes 点击以切换源代码

返回元素及其祖先中所有已定义命名空间的字符串前缀(名称)数组。

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"]
# File rexml-3.4.0/lib/rexml/element.rb, line 565
def prefixes
  prefixes = []
  prefixes = parent.prefixes if parent
  prefixes |= attributes.prefixes
  return prefixes
end
previous_element 点击以切换源代码

如果存在,则返回上一个兄弟元素,否则返回 nil

d = REXML::Document.new '<a><b/>text<c/></a>'
d.root.elements['c'].previous_element #-> <b/>
d.root.elements['b'].previous_element #-> nil
# File rexml-3.4.0/lib/rexml/element.rb, line 979
def previous_element
  element = previous_sibling
  element = element.previous_sibling until element.nil? or element.kind_of? Element
  return element
end
raw 点击以切换源代码

如果为元素设置了原始模式,则返回 true

请参阅 元素上下文

该评估针对 expanded_name 进行测试,因此对命名空间敏感。

# File rexml-3.4.0/lib/rexml/element.rb, line 533
def raw
  @raw = (@context and @context[:raw] and
          (@context[:raw] == :all or
           @context[:raw].include? expanded_name))
  @raw
end
root → 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

对于文档,返回最顶层的元素。

d.root == top_element # => true

相关:root_nodedocument

# File rexml-3.4.0/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 → document or element 点击以切换源代码

返回 self 的最远祖先。

当元素是文档的一部分时,返回文档的根节点。请注意,根节点与文档元素不同;在此示例中,a 是文档元素,根节点是它的父节点。

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

当元素不是文档的一部分,但确实有祖先元素时,返回最远的祖先元素。

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

当元素没有祖先元素时,返回 self

e = REXML::Element.new('foo')
e.root_node == e # => true

相关:rootdocument

# File rexml-3.4.0/lib/rexml/element.rb, line 422
def root_node
  parent.nil? ? self : parent.root_node
end
text(xpath = nil) → text_string or nil 点击以切换源代码

返回指定元素中第一个文本节点子节点的文本字符串(如果存在),否则返回 nil

如果没有参数,则从 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 "

如果使用参数 xpath,则从与 xpath 匹配的元素中的第一个文本节点返回文本。

d.root.text(1) # => "this is bold!"

请注意,一个元素可能具有多个文本节点,这些文本节点可能被其他非文本子节点分隔开,如上所示。即便如此,返回的值也是来自第一个此类节点的字符串文本。

另请注意,文本注释是通过方法 get_text 检索的,因此始终是规范化的文本。

# File rexml-3.4.0/lib/rexml/element.rb, line 1030
def text( path = nil )
  rv = get_text(path)
  return rv.value unless rv.nil?
  nil
end
text = string → string 点击以切换源代码
text = nil → nil

添加、替换或删除元素中的第一个文本节点子节点。

如果使用字符串参数 string,则创建一个包含该字符串的新 REXML::Text 节点,遵循当前关于空格和行的设置,然后将该节点作为元素中的第一个文本子节点放置;返回 string

如果元素没有文本子节点,则添加文本节点。

d = REXML::Document.new '<a><b/></a>'
d.root.text = 'foo' #-> '<a><b/>foo</a>'

如果元素有文本子节点,则替换它。

d.root.text = 'bar' #-> '<a><b/>bar</a>'

如果使用参数 nil,则删除第一个文本子节点。

d.root.text = nil   #-> '<a><b/><c/></a>'
# File rexml-3.4.0/lib/rexml/element.rb, line 1089
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
texts → array_of_text_children 点击切换源代码

返回该元素的 REXML::Text 子元素的冻结数组

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"]
# File rexml-3.4.0/lib/rexml/element.rb, line 1478
def texts
  find_all { |child| child.kind_of? Text }.freeze
end
whitespace 点击切换源代码

如果此元素保留空格,则返回 true,否则返回 false

请参阅 元素上下文

该评估会针对元素的 expanded_name 进行测试,因此是区分命名空间的。

# File rexml-3.4.0/lib/rexml/element.rb, line 490
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(output=$stdout, indent=-1, transitive=false, ie_hack=false) 点击切换源代码

已弃用

请参阅 REXML::Formatters

输出此元素,并递归输出所有子元素。

output

输出一个支持“<< string”的对象;这是

document will be written.
indent

一个整数。 如果为 -1,则不使用缩进;否则,缩进将为此空格数,并且子元素将额外缩进。 默认为 -1

transitive

如果 transitive 为 true 并且 indent >= 0,则输出将以美观打印的方式进行,这样添加的空格不会影响文档的解析树

ie_hack

此 hack 在空标签上的 /> 前插入一个空格,以解决 Internet Explorer 的一个限制。默认为 false

out = ''
doc.write( out )     #-> doc is written to the string 'out'
doc.write( $stdout ) #-> doc written to the console
# File rexml-3.4.0/lib/rexml/element.rb, line 1504
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 → string_xpath 点击切换源代码

返回相对于最远父元素的元素的字符串 xpath

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"

如果没有父节点,则返回元素的扩展名称

e = REXML::Element.new('foo')
e.xpath    # => "foo"
# File rexml-3.4.0/lib/rexml/element.rb, line 1192
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

私有实例方法

__to_xpath_helper(node) 点击切换源代码
# File rexml-3.4.0/lib/rexml/element.rb, line 1521
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
each_with_something( test, max=0, name=nil ) { |child| ... } 点击切换源代码

一个私有辅助方法

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