通过Nokogiri从XML插入/更新行/导入

时间:2014-04-18 09:23:15

标签: ruby-on-rails xml-parsing nokogiri

我正在将XML文档解析为数据库,我正在为我的代码寻找有效的变体。 ITEM_ID是唯一的,但代码会不断向数据库添加新行,并且不会更新现有行。

这是源XML的一个示例:

<?xml version="1.0" encoding="UTF-8" ?>
<SHOP>
<SHOPITEM>
<ITEM_ID>8159</ITEM_ID>
<PRODUCT></PRODUCT>
<DESCRIPTION></DESCRIPTION>
<URL>http://www.domovhracek.cz/</URL>
<IMGURL>http://www.domovhracek.cz/css/images/beznahledusmall.png</IMGURL>
<EAN></EAN>
<PRICE>2391</PRICE>
<CATEGORYTEXT>zaradit</CATEGORYTEXT>
<MANUFACTURER>Domov hraček</MANUFACTURER>
<PRICE_VAT>2893.00</PRICE_VAT>
<DELIVERY_DATE>0</DELIVERY_DATE>
</SHOPITEM>
</SHOP>

这是导入控制器的来源:

class ImportController < ApplicationController
  def importer
    require 'open-uri'
    require 'nokogiri'
    doc = Nokogiri::XML(open("http://www.domovhracek.cz/feed/heureka.xml"))
    doc.css('SHOPITEM').each do |node|
    children = node.children
    @conditions={:ITEM_ID=> children.css('ITEM_ID').inner_text}
    begin
      record = ShopItem.find(:first, :conditions => {:ITEM_ID=>children.css('ITEM_ID').inner_text} )
      record.PRODUCT=children.css('PRODUCT').inner_text
      record.DESCRIPTION=children.css('DESCRIPTION').inner_text

      record.save
    rescue
      record= ShopItem.create({:ITEM_ID=> children.css('ITEM_ID').inner_text})
      record.PRODUCT=children.css('PRODUCT').inner_text
      record.DESCRIPTION=children.css('DESCRIPTION').inner_text
      record.save
    end
  end
end

如果我找到密钥ITEM_ID,我会更新我的记录,但我的代码每次都会插入一个新行。

1 个答案:

答案 0 :(得分:1)

首先,使用这样的循环来遍历XML:

doc.search('SHOPITEM').each do |shop_item|
  item_id = shop_item.at('ITEM_ID').text
  product = shop_item.at('PRODUCT').text
  description = shop_item.at('DESCRIPTION').text
  # ...
end

每次查找<SHOPITEM>标记的迭代都会收集信息以创建/修改行。

您应该使用csssearch,而不是使用等同于at的{​​{1}}。 at_csscss都返回一个NodeSet,就像一个数组。如果在包含多个节点的NodeSet上使用search,则会将所有文本节点连接在一起作为字符串,这很可能不是您想要的,并且通常是您必须修复的错误:

inner_text

有关详情,请参阅require 'nokogiri' doc = Nokogiri::XML(<<EOT) <foo> <bar>1</bar> <bar>2</bar> </foo> EOT doc.search('bar').inner_text # => "12" doc.css('bar').inner_text # => "12" 页面中csssearchatat_css的文档以及inner_text Nokogiri::XML::Node页面中的文档。