我正在将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
,我会更新我的记录,但我的代码每次都会插入一个新行。
首先,使用这样的循环遍历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>
标记的迭代都将收集信息来创建/修改一行。
应该使用at
或at_css
,而不是使用等效于search
的css
。css
和search
都返回一个NodeSet,它就像一个数组。如果你在包含多个节点的NodeSet上使用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"
有关详细信息,请阅读Nokogiri::XML::Node页面中css
、search
、at
和at_css
的文档,以及Nokogiri::XML::NodeSet页面中的inner_text
文档。