Using Nokogiri to parse an XML page

Public, Ruby General, Gems

harrylevine

Created: Feb 16, 2019     Updated: Feb 16, 2019


My solution for Upcase's Analyzing Shakespeare challenge where we:

Solution

# macbeth_analyzer.rb

require 'nokogiri'
require 'httparty'

class MacbethAnalyzer
  URL = 'http://www.ibiblio.org/xml/examples/shakespeare/macbeth.xml'

  def tally_lines_per_actor
    speeches.each_with_object(Hash.new(0)) do |speech, results|
      speech.xpath('LINE').each do |line|
        results[speaker_in(speech)] += 1
      end
    end
  end

  private

  def speeches
    parsed_xml.xpath('//SPEECH')
  end

  def parsed_xml
    Nokogiri::XML(gulped_file)
  end

  def gulped_file
    response = HTTParty.get(URL)

    response.body
  end

  def speaker_in(speech)
    speech.xpath('SPEAKER').text
  end
end

Associated spec

# macbeth_analyzer_spec.rb

require 'spec_helper'

RSpec.describe MacbethAnalyzer do
  let(:xml_content) { File.read('spec/support/macbeth.xml') }

  describe '#tally_lines_per_actor' do
    it 'calculates and returns the number of lines spoken per actor', :aggregate_failures do
      allow_any_instance_of(MacbethAnalyzer).to receive(:gulped_file).and_return(xml_content)

      response = MacbethAnalyzer.new.tally_lines_per_actor

      expect(response['First Witch']).to eq 2
      expect(response['Second Witch']).to eq 4
      expect(response['ALL']).to eq 4
      expect(response['DUNCAN']).to eq 4
      expect(response['MALCOLM']).to eq 2
      expect(response['Macbeth']).to eq 4
    end
  end
end

Resources