【问题标题】:How to parse XML nodes to CSV with Ruby and Nokogiri如何使用 Ruby 和 Nokogiri 将 XML 节点解析为 CSV
【发布时间】:2014-03-18 03:31:54
【问题描述】:

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

我想将 'Offer' 的每个实例解析为 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 文件中的标题?

【问题讨论】:

  • 向我们展示预期的 csv 文件内容,以及您现在得到的内容

标签: ruby xml csv nokogiri


【解决方案1】:

这假定每个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 内容。

【讨论】:

  • 感谢 kardeiz;效果很好。确认我的理解; 'at' 表示首先出现 'Offer',然后搜索 * 查找 'Offer' 下的所有节点。 map/&name 然后获取节点名称(所以在这种情况下 name 属于 nokogiri?但 map 属于 csv 库?)
  • 我在回答中添加了一些有关各种功能的信息。您的理解是正确的,只是这里的map 不是CSV 函数; search 的结果是一个节点集,其行为类似于 Ruby array,因此您可以对其元素进行法线贴图。唯一的 CSV 函数是 open&lt;&lt; 调用,它们将新行推送到 CSV 文件。
【解决方案2】:

试试这个,然后修改它以推送到您的 CSV:

doc.css('Offer').first.elements.each do |n|
  puts "#{n.name}: #{n.content}"
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-03
    • 2014-07-05
    • 2012-01-24
    • 2019-05-12
    • 1970-01-01
    • 2013-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多