2

次の XML があります。

<attributes>
    <intelligence>27</intelligence>
    <memory>21</memory>
    <charisma>17</charisma>
    <perception>17</perception>
    <willpower>17</willpower>
</attributes>

以下を解析したい:

intelligence: 27, memory: 21, charisma: 17, perception: 17, willpower: 17

このコードを試すと:

def get_attributes(api)
  attributes = []
  api.xpath("//attributes").children.each do |attribute|
    name = attribute.name.tr('^A-Za-z0-9', '')
    text = attribute.text
    attributes << "#{name}: #{text}"
  end
  attributes
end

偶数の子ごとに改行データを使用して結果を取得します (書式設定のため):

#(Text "\n      ")
#(Element:0x3ffe166fdb9c { name = "intelligence", children = [ #(Text "20")] })
#(Text "\n      ")
#(Element:0x3ffe166f71ac { name = "memory", children = [ #(Text "25")] })
#(Text "\n      ")
#(Element:0x3ffe166f3818 { name = "charisma", children = [ #(Text "23")] })
#(Text "\n      ")
#(Element:0x3ffe166f0604 { name = "perception", children = [ #(Text "16")] })
#(Text "\n      ")
#(Element:0x3ffe166b52e8 { name = "willpower", children = [ #(Text "15")] })
#(Text "\n    ")

これらの「書式設定のみ」の子をスキップする方法が Nokogiri にありますか? または、奇数番号の要素のみを手動でトラバースする必要がありますか?

api.xpath("//attributes").children書式設定テキストではなく、実際の子をナビゲートする ことを期待しています。

4

3 に答える 3

6

このchildrenメソッドは、テキスト ノードを含む、ターゲット ノードのすべての子ノードを返します。すべての要素ノードの子だけが必要な場合は、次を使用して XPath クエリで指定できます*

def attributes(api)
  api.xpath('//attributes/*').each_with_object([]) do |n, ary|
    ary << "#{n.name}: #{n.text}"
  end
end

これにより、 format の文字列の配列が返されますname: value。これは、必要なように見えます。

于 2013-02-28T15:51:31.220 に答える
1

短い答えは「いいえ」だと思います。ただし、次のことは簡単にできます。

if attribute.element?
    name = attribute.name.tr('^A-Za-z0-9', '')
    text = attribute.text
    attributes << "#{name}: #{text}"
end

目的の効果を得るために。あるいは、このバージョンの方が少し読みやすいかもしれません:

if ! attribute.text?
   name = ...
   ...
end
于 2013-02-28T15:35:43.940 に答える
1

子のテキスト ノードだけが必要な場合は、次を使用します。

require 'nokogiri'
require 'pp'

doc = Nokogiri::HTML(<<EOT)
<attributes>
    <intelligence>27</intelligence>
    <memory>21</memory>
    <charisma>17</charisma>
    <perception>17</perception>
    <willpower>17</willpower>
</attributes>
EOT

doc.at('attributes').children.map(&:text)

どちらが返されますか:

["27", "21", "17", "17", "17"]

そこから簡単にできます:

'intelligence: %02d, memory: %02d, charisma: %02d, perception: %02d, willpower: %02d' % doc.at('attributes').children.map(&:text)
=> "intelligence: 27, memory: 21, charisma: 17, perception: 17, willpower: 17"

もう少し構造化したい場合は、次のようにします。

doc.at('attributes').children.each_with_object({}){ |o,h| h[o.name] = o.text }
=> {"intelligence"=>"27", "memory"=>"21", "charisma"=>"17", "perception"=>"17", "willpower"=>"17"}

または:

doc.at('attributes').children.each_with_object({}){ |o,h| h[o.name.to_sym] = o.text }
=> {:intelligence=>"27", :memory=>"21", :charisma=>"17", :perception=>"17", :willpower=>"17"}

doc.at('attributes').children
=> [#<Nokogiri::XML::Element:0x3fc3245fb8fc name="intelligence" children=[#<Nokogiri::XML::Text:0x3fc3245fb6f4 "27">]>, #<Nokogiri::XML::Element:0x3fc3245fb4ec name="memory" children=[#<Nokogiri::XML::Text:0x3fc3245fb2e4 "21">]>, #<Nokogiri::XML::Element:0x3fc3245fb0dc name="charisma" children=[#<Nokogiri::XML::Text:0x3fc3245faed4 "17">]>, #<Nokogiri::XML::Element:0x3fc3245fecb4 name="perception" children=[#<Nokogiri::XML::Text:0x3fc3245feaac "17">]>, #<Nokogiri::XML::Element:0x3fc3245fe8a4 name="willpower" children=[#<Nokogiri::XML::Text:0x3fc3245fe69c "17">]>]
于 2013-02-28T15:38:24.200 に答える