Я бы начал с чего-то вроде этого:
require 'csv'
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<Products>
<Product>
<Name>36-In. Homeowner Bent Single-Bit Axe Handle</Name>
<Description>This single bit curved grip axe handle is made for 3 to 5 pound axes. A good quality replacement handle made of American hickory with a natural wax finish. Hardwood handles do not conduct electricity and American Hickory is known for its strength, elasticity and ability to absorb shock. These handles provide exceptional value and economy for homeowners and other occasional use applications. Each Link handle comes with the required wedges, rivets, or epoxy needed for proper application of the tool head.</Description>
<ImageFile>100024.jpg</ImageFile>
<AltImageFile1>103387-1.jpg</AltImageFile1>
<ItemNumber>100024</ItemNumber>
<ModelNumber>64707</ModelNumber>
</Product>
<Product>
<Name>1-1/4-Inch Lavatory Pop Up Assembly</Name>
<Description>Classic chrome finish with ABS plastic top & body includes push rod, no overflow.</Description>
<ImageFile>100024.jpg</ImageFile>
<AltImageFile1>103429-1.jpg</AltImageFile1>
<ItemNumber>100024</ItemNumber>
<ModelNumber>64707</ModelNumber>
</Product>
<Product>
<Name>30-Inch Belt-Drive Whole-House Attic Fan With Shutter</Name>
<Description>The 30" belt drive whole house fan (5700 CFM) with automatic shutter helps cool living spaces up to 1900 square feet. It runs on high & low and a 2 speed wall switch is included. The automatic shutter is white. It needs 1095 square inches of open exhaust vents in attic space, with a rough opening of 34-1/4" x 29". You do have to cut joist when installing fan, with the motor mounted on struts above housing. The fan will be quieter than direct drive models. There is a 10 year limited parts warranty, 5 year limited labor warranty.</Description>
<ImageFile>100073.jpg</ImageFile>
<AltImageFile1>
<ItemNumber>100024</ItemNumber>
<ModelNumber>64707</ModelNumber>
</Product>
</Products>
EOT
Это логика c:
NODES_TO_COLUMNS = {
'ItemNumber' => 'handle',
'Name' => 'title',
'Description' => 'description',
# 'FLDeptName' => 'collection',
'ImageFile' => 'image1'
}
all_things = doc.search('Product').map do |product|
NODES_TO_COLUMNS.keys.map { |node|
product.at(node).text
}
end
CSV.open('/dev/stdout', 'wb') do |csv|
csv << NODES_TO_COLUMNS.values
all_things.each do |r|
csv << r
end
end
, которая при запуске приводит к:
handle,title,description,image1
100024,36-In. Homeowner Bent Single-Bit Axe Handle,"This single bit curved grip axe handle is made for 3 to 5 pound axes. A good quality replacement handle made of American hickory with a natural wax finish. Hardwood handles do not conduct electricity and American Hickory is known for its strength, elasticity and ability to absorb shock. These handles provide exceptional value and economy for homeowners and other occasional use applications. Each Link handle comes with the required wedges, rivets, or epoxy needed for proper application of the tool head.",100024.jpg
100024,1-1/4-Inch Lavatory Pop Up Assembly,"Classic chrome finish with ABS plastic top & body includes push rod, no overflow.",100024.jpg
100024,30-Inch Belt-Drive Whole-House Attic Fan With Shutter,"The 30"" belt drive whole house fan (5700 CFM) with automatic shutter helps cool living spaces up to 1900 square feet. It runs on high & low and a 2 speed wall switch is included. The automatic shutter is white. It needs 1095 square inches of open exhaust vents in attic space, with a rough opening of 34-1/4"" x 29"". You do have to cut joist when installing fan, with the motor mounted on struts above housing. The fan will be quieter than direct drive models. There is a 10 year limited parts warranty, 5 year limited labor warranty.",100073.jpg
Поскольку в XML отсутствует FLDeptName
, который не должен быть , чтобы быть правильным вопросом для SO, я прокомментировал это. Как использовать это оставлено для вас.
Вы хотите изменить:
CSV.open('/dev/stdout', 'wb') do |csv|
на то, что вы хотите использовать для имени файла. '/dev/stdout'
- это просто способ сохранить кодирование и направить вывод в STDOUT для его отображения.
В вашем коде вы используете такие вещи, как:
xpath("./ItemNumber").first.text
Не сделай это. Nokogiri предоставляет ярлык at
, который эквивалентен xpath....first
, но является более кратким. Кроме того, нет необходимости использовать xpath
, поскольку методы Nokogiri search
и at
достаточно умны, чтобы почти каждый раз выяснять, что такое селектор XPath или CSS.
Я бы также рекомендовал не использовать XPath, если не принужден. Селекторы CSS более читабельны и включают в себя множество jQuery CSS расширений (если не все к настоящему времени), так что вы можете избежать некоторого визуального шума XPath, используя их.
Ваше требование создать вторичный, в основном- Пустая строка, если AltImageFile1
не пуста, я бы не рекомендовал. Строка CSV считается отдельной, отдельной записью, и будет интерпретироваться как таковая каждым приложением, которое поддерживает CSV, который я видел, поэтому вы просите создать вторичную запись без полей нестандартного формата. Вместо этого это поле должно быть добавлено к той же строке, что и дополнительное поле. Этот лог c не сложен и оставлен на ваше усмотрение.
Документ IETF CSV указывает:
Каждая запись расположена на отдельная строка, разделенная разрывом строки (CRLF). Например:
aaa,bbb,ccc CRLF
zzz,yyy,xxx CRLF
В результате, , а не , что нарушит движение данных во многих других приложениях, чего вы должны избегать, так как CSV должен быть для передачи данных.
Если вы перемещаете данные в DBM, создайте временную таблицу для импорта непосредственно из XML, выполните операторы базы данных, чтобы соответствующим образом управлять записями, а затем добавьте их в основную таблицу. Если вы импортируете данные в Excel, используйте отдельную таблицу, измените поля, затем скопируйте или объедините данные в обычную таблицу. Создание нестандартного представления данных кажется мне тупиком.
Альтернативой может быть использование файлов YAML, которые являются более гибкими и гораздо более надежными.