如何从REXML元素中获取所有叶子单元格并将它们保存到数组中?

时间:2014-05-24 22:33:03

标签: ruby rexml

拥有如下所示的Ruby REXML元素:

<a_1>
  <Tests>
    <test enabled='1'>trans </test>
    <test enabled='1'>ac </test>
    <test enabled='1'>dc </test>
  </Tests>
  <Corners>
    <corner enabled='0'>default</corner>
    <corner enabled='1'>C0 </corner>
  </Corners>
</a_1>

我想找到所有叶元素,因此结果应为:

<test enabled='1'>trans </test>
<test enabled='1'>ac </test>
<test enabled='1'>dc </test>
<corner enabled='0'>default</corner>
<corner enabled='1'>C0 </corner>

我的代码是:

require 'rexml/document' 
include  REXML

def getAllLeaf(xmlElement)
  if xmlElement.has_elements?
    xmlElement.elements.each {|e| 
      getAllLeaf(e)
    }
  else
    return xmlElement
  end
end

它工作正常,并在屏幕上显示正确的输出。但是,当我尝试将结果保存到数组时,我发现我遇到了一个问题,这个递归过程。所以如果有一种方法可以将这个输出保存到一个可以在以后使用的数组,那么我是否更有意思?

我努力以递归的方式做到这一点,虽然有点奇怪,我想分享一下:

def getAllLeaf(eTop,aTemp=Element.new("LeafElements"))
  if eTop.has_elements?
    eTop.elements.each {|e| 
      getAllLeaf(e,aTemp)
    }
  else
    aTemp<< eTop.dup
  end
  return aTemp
end

1 个答案:

答案 0 :(得分:0)

  

它工作正常,并在屏幕上显示正确的输出。

实际上,代码在任何地方都没有输出。在任何情况下,您的递归函数都不起作用,当Tests>看起来像这样时,如果您在元素&lt; <Tests>上调用方法,则可以看到:

  <Tests>
    <test enabled='1'>
      <HELLO>world</HELLO>
    </test>
    <test enabled='1'>ac </test>
    <test enabled='1'>dc </test>
  </Tests>

你的递归方法不起作用,因为当你写:

xmlElement.elements.each {|e|

each()方法返回左边的东西,即xmlElement.elements。给定xml,递归方法等同于:

def getAllLeaf(xmlElement)
    xmlElement.elements.each {|e| 
      "blah"  #your code here has no effect on what each() returns.
    }
end

..相当于:

def getAllLeaf(xmlElement)
    return xmlElement.elements
end

你想坚持递归吗?搜索没有子元素的元素的所有元素要简单得多:

require "rexml/document"
include REXML

xml = <<'END_OF_XML'
<a_1>
  <Tests>
    <test enabled='1'>trans </test>
    <test enabled='1'>ac </test>
    <test enabled='1'>dc </test>
  </Tests>
  <Corners>
    <corner enabled='0'>default</corner>
    <corner enabled='1'>C0 </corner>
  </Corners>
</a_1>
END_OF_XML

doc = Document.new xml
root = doc.root

XPath.each(root, "//*") do |element|
  if not element.has_elements?
    enabled = element.attributes['enabled'] 
    text = element.text
    puts "#{enabled} ... #{text}"
  end
end

--output:--
1 ... trans 
1 ... ac 
1 ... dc 
0 ... default
1 ... C0 

或者,如果所有叶元素都是具有属性&#34;启用&#34;的唯一元素,则应执行此操作:

XPath.each(root, "//*[@enabled]") do |element|
  enabled = element.attributes['enabled'] 
  text = element.text
  puts "#{enabled} ... #{text}"
end

甚至还有一个神秘的xpath会直接选择没有元素子元素的元素:

XPath.each(root, "//*[not(*)]") do |element|
  enabled = element.attributes['enabled'] 
  text = element.text
  puts "#{enabled} ... #{text}"
end

另外,您是否考虑过使用nokogiri宝石?它几乎是ruby的标准XML / HTML解析器。