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

正常に動作し、画面に正しい出力が表示されました。ただし、この再帰的な手順のために、結果を配列に保存しようとすると問題が発生することがわかりました。この出力を後で使用できる1つの配列に保存する方法があれば、私はうんざりしますか?

少し奇妙ですが、再帰的な方法でそれを行うのに苦労しました。それを共有したいと思います。

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

また、ノコギリジェムの使用は検討されましたか?Ruby の標準的な XML/HTML パーサーとほぼ同じです。

于 2014-05-25T03:07:57.943 に答える