如何用nokogiri正确解析和查看?

时间:2015-03-07 06:11:16

标签: ruby-on-rails ruby nokogiri

我在查看正确的xml数据时遇到问题。这是我在控制器和视图中的代码。

  def new
    doc = Nokogiri::XML(open('sample3.xml'))

    @link = doc.xpath('//match').map do |t| {
      'home' => t.at('home').attr('name')
    }
  end

    @odds = doc.xpath('//odds/type[@name="1x2"]/bookmaker[@id="781"]').map do |t| {
      '1' => t.at('odd[@name="1"]').attr('value'),
      '2' => t.at('odd[@name="2"]').attr('value'),
      'X' => t.at('odd[@name="X"]').attr('value')
    }

  end
  end
  end

查看:

<table class="flat-table">
    <tbody>

        <tr>
            <% @link.each do |t| %>
            <tr>

            <td><%= t['home'] %></td>

            <td> <%= t['1'] %> </td>
            <td> <%= t['2'] %> </td>
            <td> <%= t['X'] %> </td>
        </tr>
                <% end %>

我的问题是,如何显示@odds的值,因为我已经为@link添加了“each do”代码?谢谢。请帮忙!

2 个答案:

答案 0 :(得分:1)

xml.xml:

<?xml version="1.0" encoding="UTF-8"?>
<data>
  <match>
    <home name="Wembley"></home>
  </match>

  <match>
    <home name="Old Trafford"></home>
  </match>

  <odds>
    <type name="1x2">
      <bookmaker id="781">
        <odd name="1" value="10"></odd>
        <odd name="2" value="20"></odd>
        <odd name="X" value="30"></odd>
      </bookmaker>
    </type>
  </odds>

  <odds>
    <type name="1x2">
      <bookmaker id="781">
        <odd name="1" value="100"></odd>
        <odd name="2" value="200"></odd>
        <odd name="X" value="300"></odd>
      </bookmaker>
    </type>
  </odds>

</data>

代码:

require 'nokogiri'

doc = Nokogiri::XML(
  File.read('xml.xml')
)

links = doc.xpath('//match').map do |match|
  { 'home' => match.at('home').attr('name') }
end

my_xpath = '//odds/type[@name="1x2"]/bookmaker[@id="781"]' 

odds = doc.xpath(my_xpath).map do |bmaker|
  {
    '1' => bmaker.at('odd[@name="1"]').attr('value'),
    '2' => bmaker.at('odd[@name="2"]').attr('value'),
    'X' => bmaker.at('odd[@name="X"]').attr('value'),
  }
end

您可以使用这样的循环:

(0...links.size).each do |i|  #Note the 3 dots, which excludes the last.
  puts links[i]['home']

  puts odds[i]['1']
  puts odds[i]['2']
  puts odds[i]['X']

  puts '-' * 10
end

--output:--
Wembley
10
20
30
----------
Old Trafford
100
200
300
----------

或者,像这样:

links.each_with_index do |link, i|
  puts link['home']

  puts odds[i]['1']
  puts odds[i]['2']
  puts odds[i]['X']

  puts '-' * 10
end

或者,像这样:

links.each do |link|
  puts link['home']

  odd = odds.shift  #Remove first item from odds array. The other items shuffle to the left one position.
  puts odd['1']
  puts odd['2']
  puts odd['X']

  puts '-' * 10
end

但我更喜欢:

links_enum = links.each
odds_enum = odds.each

loop do   
  puts links_enum.next['home']  #The loop will end immediately if next() is called and there are no more items.

  odd = odds_enum.next   #The loop will end immediately if next() is called and there are no more items.
  puts odd['1']
  puts odd['2']
  puts odd['X']

  puts '-' * 10
end

--output:--
Wembley
10
20
30
----------
Old Trafford
100
200
300
----------

在您的rails应用中,操作会是这样的:

#Get the xml from somewhere:
doc = Nokogiri::XML(
  File.read("#{Rails.root}/files/xml.xml")
)

links = doc.xpath('//match').map do |match|
  { 'home' => match.at('home').attr('name') }
end

my_xpath = '//odds/type[@name="1x2"]/bookmaker[@id="781"]' 

odds = doc.xpath(my_xpath).map do |bmaker|
  {
    '1' => bmaker.at('odd[@name="1"]').attr('value'),
    '2' => bmaker.at('odd[@name="2"]').attr('value'),
    'X' => bmaker.at('odd[@name="X"]').attr('value'),
  }
end

#Set the view variables:
@links_enum = links.each
@odds_enum = odds.each

然后你的观点是这样的:

<table class="flat-table">
<tbody>

<% loop do %>
  <tr>
    <td><%= @links_enum.next['home'] %></td>

    <% odd = @odds_enum.next %>
    <td> <%= odd['1'] %> </td>
    <td> <%= odd['2'] %> </td>
    <td> <%= odd['X'] %> </td>
  </tr>
<% end %>

</tbody>
</table>

但要使用对你来说最有意义的循环。 :)

对评论的回应

require 'nokogiri'
require 'open-uri'

doc = Nokogiri::XML(
  open("http://www.tipgin.net/example-data/odds-worldcup-example.xml")
)

match_xpath = '/odds/league/matches/match[./odds/type]'

doc.xpath(match_xpath).each do |match|
  puts match.at_xpath("./home")['name']
  puts 'vs.'
  puts match.at_xpath("./away")['name']

  match.xpath('./odds/type/bookmaker').each do |bmaker|
    puts bmaker['name']

    bmaker.xpath('./odd').each do |odd|
      puts "#{odd['name']} ... #{odd['value']}"
    end

    break
  end
  break
end

--output:--
Brazil
vs.
Croatia
12Bet
1 ... 1.27
2 ... 9.56
X ... 5.32

答案 1 :(得分:0)

       <td> <%= @odds[0]['1'] %> </td>
       <td> <%= @odds[0]['2'] %> </td>
       <td> <%= @odds[0]['X'] %> </td>

显示第一个条目。或者在循环内部迭代,无论如何。

你确定你明白你在做什么吗?