映射两个Nokogiri对象



一个快速问题:

<table>
  <tr>
    <th>foo</th>
    <td><p>bar</p></td>
  </tr>
</table>
  details  = doc.css('table > tr > th')
  details2 = doc.css('table > tr > td > p')
  details  = details.map { |n| { name: n.text }}
  details2 = details2.map { |n| { value: n.text }}

如何在一个map语句中合并那些Nokogiri对象?

输出:

{:name=>"abc"}
{:name=>"ghj"}
{:name=>"lmn"}
{:value=>"123"}
{:value=>"456"}
{:value=>"789"}

我需要这样的东西:

{:name=>"abc", :value=>"123"}

我尝试了这样的事情:

details = details.map { |n| { name: n.text, value: n.css('table > tr > td > p').map { |x| {value: x} }}}
details = details.map { |n| {name: n.text, value: n.css('table > tr > td').attr('p').to_s} }

css支持多个选择器,而诺科吉里(Nokogiri)对CSS的使用尊重:

require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<html>
  <body>
    <table>
      <tr>
        <th>foo</th>
        <td><p>bar</p></td>
      </tr>
    </table>
  </body>
</html>
EOT
text = doc.search('table tr th, table tr td p').map(&:text)
text # => ["foo", "bar"]

或更干净:

rows = doc.search('table tr')
text = rows.search('th, td p').map(&:text)
text # => ["foo", "bar"]

请注意,多个选择器依次工作。换句话说,他们找到了第一个选择器,然后是第二个选择器,因此,如果您需要知道文档中发生的实际顺序,则必须使用单个搜索或查看实际节点以确定其在其中的位置dom。

另外,请注意,我正在使用通用search而不是更具体的css。Nokogiri足够聪明,可以在使用CSS或XPath时大部分时间做正确的事情,因此使用searchat更方便。

假设,数组包含有效/相同顺序中的对象:

details.zip(details2).map { |e| e.inject &:merge }

最简单的方法:

details  = doc.css('table > tr > th')
details2 = doc.css('table > tr > td > p')
details.map!.with_index { |d, i| {name: d.text, value: details2[i].text } }

details看起来像[{name: 'asd', value: '123'}, {name: 'qwe', value: '234'}]

相关内容

  • 没有找到相关文章

最新更新