如何使用Ruby和Nokogiri将XML节点解析为CSV

问题描述 投票:2回答:2

我有一个XML文件:

?xml version="1.0" encoding="iso-8859-1"?>
<Offers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ssc.channeladvisor.com/files/cageneric.xsd">
  <Offer>
   <Model><![CDATA[11016001]]></Model>
   <Manufacturer><![CDATA[Crocs, Inc.]]></Manufacturer>
   <ManufacturerModel><![CDATA[11016-001]]></ManufacturerModel>
   ...lots more nodes
   <Custom6><![CDATA[<li>Bold midsole stripe for a sporty look.</li>
    <li>Odor-resistant, easy to clean, and quick to dry.</li>
    <li>Ventilation ports for enhanced breathability.</li>
    <li>Lightweight, non-marking soles.</li>
    <li>Water-friendly and buoyant; weighs only ounces.</li>
    <li>Fully molded Croslite&trade; material for lightweight cushioning and comfort.</li>
    <li>Heel strap swings back for snug fit, forward for wear as a clog.</li>]]></Custom6>
  </Offer>
....lots lots more <Offer> entries
</Offers>

我想将“要约”的每个实例解析为CSV文件中自己的行:

require 'csv'
require 'nokogiri'

file = File.read('input.xml')
doc = Nokogiri::XML(file)
a = []
csv = CSV.open('output.csv', 'wb') 

doc.css('Offer').each do |node|
    a.push << node.content.split
end

a.each { |a| csv << a } 

这很好,除了我在空格上而不是在Offer节点的每个元素上进行拆分,因此每个单词都将进入CSV文件中自己的列。

是否有一种方法可以提取每个节点的内容,以及如何使用节点名称作为CSV文件中的标题?

ruby xml csv nokogiri
2个回答
6
投票

这假设每个Offer元素始终具有相同的子节点(尽管它们可以为空):

CSV.open('output.csv', 'wb') do |csv|
  doc.search('Offer').each do |x|
    csv << x.search('*').map(&:text)
  end
end

并获得标头(从第一个Offer元素中获得:]

CSV.open('output.csv', 'wb') do |csv|
  csv << doc.at('Offer').search('*').map(&:name)
  doc.search('Offer').each do |x|
    csv << x.search('*').map(&:text)
  end
end

searchat是Nokogiri函数,可以采用XPath或CSS选择器字符串。 at将返回元素的第一次出现; search将提供匹配元素的数组(如果找不到匹配项,则为空数组)。在这种情况下,*将选择作为当前节点的直接子节点的所有节点。

nametext都是Nokogiri函数(对于元素)。 name提供元素的名称; text提供节点的文本或CDATA内容。


0
投票

尝试一下,并对其进行修改以将其推送到您的CSV文件中:

doc.css('Offer').first.elements.each do |n|
  puts "#{n.name}: #{n.content}"
end
© www.soinside.com 2019 - 2024. All rights reserved.