Ramy
Ramy

Reputation: 21261

Is there a better way to get this element/node with Nokogiri?

I think the best way to explain this is via some code. Basically the only way to identify the TR I need inside the table (i've already reached the table itself and named it annual_income_statement) is by the text of the first TD in the TR, like this:

this may be helpful to know, too:

actual html:

doc = Nokogiri::HTML(open('https://www.google.com/finance?q=NYSE%3AAA&fstype=iii'))

html snippet:

<div id="incannualdiv">
  <table id="fs-table">
    <tbody>
      <tr>..</tr>
      ...
      <tr>
        <td>Net Income</td>
        <td>100</td>
      </tr>
      <tr>..</tr>
    </tbody>
  </table>
</div>

original xpath

irb(main):161:0> annual_income_statement = doc.xpath("//div[@id='incannualdiv']/table[@id='fs-table']/tbody")

irb(main):121:0> a = nil
=> nil
irb(main):122:0> annual_income_statement.children.each { |e| if e.text.include? "Net Income" and e.text.exclude? "Ex"
irb(main):123:2>   a = e.text
irb(main):124:2> end }
=> 0
irb(main):125:0> a
=> "Net Income\n\n191.00\n611.00\n254.00\n-1,151.00\n"
irb(main):127:0> a.split "\n"
=> ["Net Income", "", "191.00", "611.00", "254.00", "-1,151.00"]

but is there a better way?

more details:

doc = Nokogiri::HTML(open('https://www.google.com/finance?q=NYSE%3AAA&fstype=iii'))
div = doc.at "div[@id='incannualdiv']" #div containing the table i want
table = div.at 'table' #table containing tbody i want
tbody = table.at 'tbody' #tbody containing tr's I want
trs = tbody.at 'tr' #SHOULD be all tr's of that table/tbody - but it's only the first TR?

I expect that last bit to give me ALL the TR's (which would include the TD i'm looking for) but in fact it only gives me the first TR

Upvotes: 0

Views: 68

Answers (1)

pguardiario
pguardiario

Reputation: 54984

Best is probably:

table.at 'tr:has(td[1][text()="Net Income"])' 

Edit

More info:

doc = Nokogiri::HTML <<EOF
<div id="incannualdiv">
  <table id="fs-table">
    <tbody>
      <tr>..</tr>
      ...
      <tr>
        <td>Net Income</td>
        <td>100</td>
      </tr>
      <tr>..</tr>
    </tbody>
  </table>
</div>
EOF
table = doc.at 'table'
table.at('tr:has(td[1][text()="Net Income"])').to_s
#=> "<tr>\n<td>Net Income</td>\n        <td>100</td>\n      </tr>\n"

Upvotes: 1

Related Questions