Использование 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