Reputation: 233
Feels like I'm missing something pretty obvious here but can't see it.
I have an XML file and are using the Nokogiri gem.
The XML looks like this (imagine if you will an infinite amount of 'variants'):
<?xml version="1.0" encoding="UTF-8"?>
<products>
<variant>
<sku type="string">123abc</sku>
<inventory-quantity type="integer">68</inventory-quantity>
</variant>
<variant>
<sku type="string">321cba</sku>
<inventory-quantity type="integer">22</inventory-quantity>
</variant>
</products>
I want to loop over the variants and create a corresponding record for each that contains the 'sku' and 'inventory-quantity' attributes.
This is what I've got so far, but instead of creating individual records, in the above case it creates two records and inserts the complete array or NodeSet that Nokogiri returns into each records attribute. So this:
doc = Nokogiri::XML(File.open("#{Rails.root}/public/new.xml"))
variant = doc.xpath("//variant")
variant.each do |product|
sku = product.xpath("//sku").text
quan = product.xpath("//inventory-quantity").text
Productmapping.create(:sku => sku, :product_quantity => quan)
end
creates this...
sku inventory-quantity
123abc321cba 6822
123abc321cba 6822
Where I actually want:
sku inventory-quantity
123ab 68
321cba 22
It looks like it's because the xpath locator returns all occurrences into an array and I'm calling that array and inserting it for each record.
Thanks!
Upvotes: 3
Views: 6061
Reputation: 1428
The answer is simple - instead of:
sku = product.xpath("//sku").text
quan = product.xpath("//inventory-quantity").text
just use:
sku = product.xpath("sku").text
quan = product.xpath("inventory-quantity").text
It's because //sku
selects all the sku descendants of the document root.
Upvotes: 14
Reputation: 1811
Smth like:
doc = Nokogiri::XML(File.open("#{Rails.root}/public/new.xml"))
variant = doc.xpath("//variant")
sku, quan = nil, nil
variant.each do |product|
product.children.each do |child|
case child.name
when 'sku'
sku = child.text
when 'inventory-quantity'
quan = child.text
end
end
Productmapping.create(:sku => sku, :product_quantity => quan)
end
Or more magic and not beautiful but compact way:
sku = product.children[1].text
quan = product.children[3].text
Upvotes: 1