我有像http://www.heureka.cz/direct/xml-export/shops/heureka-sekce.xml这样的XML文件。我无法改变它,因为它不是我的。它只是从另一个网站解析。
这是XML(带结构):
<HEUREKA>
<CATEGORY>
<CATEGORY_ID>971</CATEGORY_ID>
<CATEGORY_NAME>Auto-moto</CATEGORY_NAME>
<CATEGORY>
<CATEGORY_ID>881</CATEGORY_ID>
<CATEGORY_NAME>Alkohol testery</CATEGORY_NAME>
<CATEGORY_FULLNAME>Heureka.cz | Auto-moto | Alkohol testery</CATEGORY_FULLNAME>
</CATEGORY>
</CATEGORY>
</HEUREKA>
感谢所有评论,这是最终的代码
def heureka
require 'open-uri'
require 'nokogiri'
doc = Nokogiri::XML(open("http://www.heureka.cz/direct/xml-export/shops/heureka-sekce.xml"))
doc.xpath("//CATEGORY[CATEGORY_FULLNAME]").each do |node|
record = Heureka.where("name" => node.css('CATEGORY_NAME').inner_text).first_or_initialize
record.fullname=node.xpath('CATEGORY_FULLNAME').inner_text
record.name=node.xpath('CATEGORY_NAME').inner_text
record.save unless record.fullname.blank?
end
end
答案 0 :(得分:5)
在这个地方使用nokogiri似乎有点过分。你可以用普通红宝石做到这一点:
require 'net/http'
xml_content = Net::HTTP.get(URI.parse('http://www.heureka.cz/direct/xml-export/shops/heureka-sekce.xml'))
data = Hash.from_xml(xml_content)
然后您可以作为哈希对象访问数据。
答案 1 :(得分:1)
如果我们缩进您的XML,您将看到问题:
<HEUREKA>
<CATEGORY>
<CATEGORY_ID>971</CATEGORY_ID>
<CATEGORY_NAME>Auto-moto</CATEGORY_NAME>
<CATEGORY>
<CATEGORY_ID>881</CATEGORY_ID>
<CATEGORY_NAME>Alkohol testery</CATEGORY_NAME>
<CATEGORY_FULLNAME>Heureka.cz | Auto-moto | Alkohol testery</CATEGORY_FULLNAME>
</CATEGORY>
</CATEGORY>
</HEUREKA>
第二个类别节点是里面第一个类别节点,所以它也是它的子节点。因为children.css('CATEGORY_NAME').inner_text
将返回第一个节点连接的两个名称(Auto-motoAlkohol testery
),最后一个将具有预期的数据 - (Alkohol testery
)。
修复您的XML:
<HEUREKA>
<CATEGORY>
<CATEGORY_ID>971</CATEGORY_ID>
<CATEGORY_NAME>Auto-moto</CATEGORY_NAME>
</CATEGORY>
<CATEGORY>
<CATEGORY_ID>881</CATEGORY_ID>
<CATEGORY_NAME>Alkohol testery</CATEGORY_NAME>
<CATEGORY_FULLNAME>Heureka.cz | Auto-moto | Alkohol testery</CATEGORY_FULLNAME>
</CATEGORY>
</HEUREKA>
再试一次......
<强>更新强>
如果您无法更改XML,则可以使用XPATH
代替CSS
,因为其默认行为是找到直接子项,而不是所有的孩子(深儿):
def heurekacat
require 'open-uri'
require 'nokogiri'
doc = Nokogiri::XML(open("http://www.heureka.cz/direct/xml-export/shops/heureka-sekce.xml"))
doc.css("CATEGORY").each do |node|
record = HeurekaCat.where("name" => children.xpath('CATEGORY_NAME').inner_text).first_or_initialize
record.category=node.xpath('CATEGORY_FULLNAME').inner_text
record.name=node.xpath('CATEGORY_NAME').inner_text
record.save
end
end
答案 2 :(得分:0)
只需更改一行:
doc.css("CATEGORY").each do |node|
以下内容:
doc.css("CATEGORY:has(CATEGORY_FULLNAME)").each do |node|
这仅选择包含CATEGORY
子元素的CATEGORY_FULLNAME
个元素。
作为替代方案,等效的XPath:
doc.xpath("//CATEGORY[CATEGORY_FULLNAME]").each do |node|