0

有一个 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
4

1 回答 1

0

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

事实上,代码在任何地方都没有显示任何输出。在任何情况下,您的递归函数都不起作用,如果您在元素 < 上调用您的方法,您可以看到它Tests>看起来<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 

或者,如果所有叶子元素都是唯一具有“启用”属性的元素,则应该这样做:

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 解析器。

于 2014-05-25T03:07:57.943 回答