Rails 4将XML解析为表



我有一个类似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                         

在这个地方使用nokogiri似乎有点过大。您可以使用普通ruby:

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)

那么您就可以访问作为散列对象的数据。

如果我们缩进你的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>

And try again…


如果不能更改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

只需改变一行:

doc.css("CATEGORY").each do |node|

到下面:

doc.css("CATEGORY:has(CATEGORY_FULLNAME)").each do |node|

只选择包含CATEGORY_FULLNAME子元素的CATEGORY元素

作为替代,等价的XPath:
doc.xpath("//CATEGORY[CATEGORY_FULLNAME]").each do |node|

相关内容

  • 没有找到相关文章

最新更新