Domanda

Here's an example file:

<?xml version="1.0" encoding="UTF-8"?>
<response status="success">
   <campaigns>
      <campaign>
         <campaign_id>41381</campaign_id>
         <campaign_name><![CDATA[campaign1]]></campaign_name>
         <campaign_status>1</campaign_status>
         <campaign_type>STANDARD</campaign_type>
         <campaign_notes />
         <campaign_rate />
         <campaign_owner_id>33975</campaign_owner_id>
         <campaign_start_date>11-05-2014</campaign_start_date>
         <campaign_end_date>12-12-2020</campaign_end_date>
         <creation_date>11-05-2014</creation_date>
         <daily_budget>10.000</daily_budget>
         <daily_budget_left>10.000000000000000000000000000000</daily_budget_left>
         <total_budget>X</total_budget>
         <total_budget_left>1000000.000000000000000000000000000000</total_budget_left>
         <reporting>
            <impressions />
            <clicks />
            <total_cost>
               <currency>USD</currency>
               <amount />
            </total_cost>
            <average_cpc>
               <currency>USD</currency>
               <amount>0</amount>
            </average_cpc>
            <conversions />
            <cost_per_conversion>
               <currency>USD</currency>
               <amount>n/a</amount>
            </cost_per_conversion>
         </reporting>
      </campaign>
   </campaigns>
</response>

What I want to do is go through each of the campaigns and parse through the data to generate in memory objects. For example I want to create ruby objects based off of each campaign. I'd like to be able to something like campaigns.each {|campaign| puts impressions = campaign['reporting']['impressions']}

È stato utile?

Soluzione

Here's some code for your requirement described in your post. It only works for Hash like XML structures, such as the campaign node in your sample data. If you want Array like behavior, you may need to handle them explicitly, as what I did for the campaigns node.

require 'nokogiri'

def parse(element)
  children = element.children.reject{|e| e.is_a?(Nokogiri::XML::Text) && e.text =~ /^\s*$/}

  if children.count == 1 && children[0].is_a?(Nokogiri::XML::Text)
    children[0].text
  else
    data = Hash.new
    children.each do |child|
      data[child.name] = parse(child)
    end
    data
  end
end

doc = Nokogiri::XML(open('data.xml')) # suppose the xml is stored in data.xml

campaigns = doc.xpath('/response/campaigns/campaign').map{|c| parse(c)}
p campaigns
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top