Использование nokogiri для анализа XML и создания записей с несколькими атрибутами

Такое ощущение, что я упускаю что-то довольно очевидное здесь, но не вижу этого.

У меня есть XML-файл, и я использую драгоценный камень Nokogiri.

XML выглядит следующим образом (представьте, что у вас будет бесконечное количество "вариантов"):

<?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>

Я хочу перебрать варианты и создать соответствующую запись для каждого, которая содержит атрибуты "sku" и "инвентарь-количество".

Это то, что я получил до сих пор, но вместо создания отдельных записей в вышеупомянутом случае он создает две записи и вставляет полный массив или NodeSet, который Nokogiri возвращает в каждый атрибут records. Итак, это:

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

создает это...

sku              inventory-quantity

123abc321cba     6822
123abc321cba     6822

Где я на самом деле хочу:

sku              inventory-quantity

123ab            68
321cba           22

Похоже, это потому, что локатор xpath возвращает все вхождения в массив, и я вызываю этот массив и вставляю его для каждой записи.

Спасибо!

2 ответа

Решение

Ответ прост - вместо:

sku = product.xpath("//sku").text
quan = product.xpath("//inventory-quantity").text

просто используйте:

sku = product.xpath("sku").text
quan = product.xpath("inventory-quantity").text

Это потому что //sku выбирает всех потомков sku корня документа.

Что-то вроде:

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

Или более волшебным и не красивым, но компактным способом:

sku = product.children[1].text
quan = product.children[3].text
Другие вопросы по тегам